tizen 2.3 release tizen_2.3 submit/tizen_2.3/20150202.074155 tizen_2.3_release
authorjk7744.park <jk7744.park@samsung.com>
Sun, 1 Feb 2015 05:25:58 +0000 (14:25 +0900)
committerjk7744.park <jk7744.park@samsung.com>
Sun, 1 Feb 2015 05:25:58 +0000 (14:25 +0900)
1362 files changed:
.gitignore [new file with mode: 0644]
CMakeLists.txt [new file with mode: 0755]
Doxyfile [new file with mode: 0644]
LICENSE [new file with mode: 0755]
clean.sh [new file with mode: 0755]
config.dtd [new file with mode: 0644]
packaging/wrt-plugins-tizen.spec [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-account.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-alarm.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-application.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-archive.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-badge.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-bluetooth.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-bookmark.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-calendar.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-callhistory.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-common.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-contact.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-content.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-datacontrol.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-datasync.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-download.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-exif.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-filesystem.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-filesystem_new.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-fmradio.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-humanactivitymonitor.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-log.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-mediakey.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-messageport.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-messaging.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-networkbearerselection.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-nfc.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-notification.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-package.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-power.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-push.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-secureelement.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-sensor.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-sound.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-systeminfo.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-systemsetting.pc.in [new file with mode: 0755]
pkgconfigs/wrt-plugins-tizen-timeutil.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-tizen.pc.in [new file with mode: 0644]
pkgconfigs/wrt-plugins-tizen-websetting.pc.in [new file with mode: 0755]
src/Account/Account.cpp [new file with mode: 0755]
src/Account/Account.h [new file with mode: 0755]
src/Account/AccountArrayCallback.cpp [new file with mode: 0755]
src/Account/AccountArrayCallback.h [new file with mode: 0755]
src/Account/AccountChangeCallback.cpp [new file with mode: 0755]
src/Account/AccountChangeCallback.h [new file with mode: 0755]
src/Account/AccountExtendedData.cpp [new file with mode: 0755]
src/Account/AccountExtendedData.h [new file with mode: 0755]
src/Account/AccountExtendedDataCallback.cpp [new file with mode: 0755]
src/Account/AccountExtendedDataCallback.h [new file with mode: 0755]
src/Account/AccountManager.cpp [new file with mode: 0755]
src/Account/AccountManager.h [new file with mode: 0755]
src/Account/AccountProvider.cpp [new file with mode: 0755]
src/Account/AccountProvider.h [new file with mode: 0755]
src/Account/AccountProviderArrayCallback.cpp [new file with mode: 0755]
src/Account/AccountProviderArrayCallback.h [new file with mode: 0755]
src/Account/AccountTypes.h [new file with mode: 0755]
src/Account/AccountUtil.cpp [new file with mode: 0755]
src/Account/AccountUtil.h [new file with mode: 0755]
src/Account/CMakeLists.txt [new file with mode: 0755]
src/Account/JSAccount.cpp [new file with mode: 0755]
src/Account/JSAccount.h [new file with mode: 0755]
src/Account/JSAccountExtendedData.cpp [new file with mode: 0755]
src/Account/JSAccountExtendedData.h [new file with mode: 0755]
src/Account/JSAccountManager.cpp [new file with mode: 0755]
src/Account/JSAccountManager.h [new file with mode: 0755]
src/Account/JSAccountProvider.cpp [new file with mode: 0755]
src/Account/JSAccountProvider.h [new file with mode: 0755]
src/Account/OperationCallback.cpp [new file with mode: 0755]
src/Account/OperationCallback.h [new file with mode: 0755]
src/Account/config.xml [new file with mode: 0755]
src/Account/plugin_config.cpp [new file with mode: 0755]
src/Account/plugin_config.h [new file with mode: 0755]
src/Account/plugin_initializer.cpp [new file with mode: 0755]
src/Alarm/AlarmAbsolute.cpp [new file with mode: 0755]
src/Alarm/AlarmAbsolute.h [new file with mode: 0755]
src/Alarm/AlarmConverter.cpp [new file with mode: 0755]
src/Alarm/AlarmConverter.h [new file with mode: 0755]
src/Alarm/AlarmRelative.cpp [new file with mode: 0755]
src/Alarm/AlarmRelative.h [new file with mode: 0755]
src/Alarm/AlarmUtil.cpp [new file with mode: 0755]
src/Alarm/AlarmUtil.h [new file with mode: 0755]
src/Alarm/CMakeLists.txt [new file with mode: 0755]
src/Alarm/JSAlarmAbsolute.cpp [new file with mode: 0755]
src/Alarm/JSAlarmAbsolute.h [new file with mode: 0755]
src/Alarm/JSAlarmManager.cpp [new file with mode: 0755]
src/Alarm/JSAlarmManager.h [new file with mode: 0755]
src/Alarm/JSAlarmRelative.cpp [new file with mode: 0755]
src/Alarm/JSAlarmRelative.h [new file with mode: 0755]
src/Alarm/alarm_common.h [new file with mode: 0755]
src/Alarm/config.xml [new file with mode: 0755]
src/Alarm/plugin_config.cpp [new file with mode: 0755]
src/Alarm/plugin_config.h [new file with mode: 0755]
src/Alarm/plugin_config_impl.h [new file with mode: 0755]
src/Alarm/plugin_initializer.cpp [new file with mode: 0755]
src/Application/AppManagerWrapper.cpp [new file with mode: 0755]
src/Application/AppManagerWrapper.h [new file with mode: 0755]
src/Application/Application.cpp [new file with mode: 0755]
src/Application/Application.h [new file with mode: 0644]
src/Application/ApplicationAsyncCallbackManager.cpp [new file with mode: 0755]
src/Application/ApplicationAsyncCallbackManager.h [new file with mode: 0644]
src/Application/ApplicationCert.cpp [new file with mode: 0644]
src/Application/ApplicationCert.h [new file with mode: 0644]
src/Application/ApplicationContext.cpp [new file with mode: 0755]
src/Application/ApplicationContext.h [new file with mode: 0755]
src/Application/ApplicationControl.cpp [new file with mode: 0755]
src/Application/ApplicationControl.h [new file with mode: 0755]
src/Application/ApplicationControlData.cpp [new file with mode: 0644]
src/Application/ApplicationControlData.h [new file with mode: 0755]
src/Application/ApplicationController.cpp [new file with mode: 0755]
src/Application/ApplicationController.h [new file with mode: 0755]
src/Application/ApplicationConverter.cpp [new file with mode: 0755]
src/Application/ApplicationConverter.h [new file with mode: 0755]
src/Application/ApplicationFactory.cpp [new file with mode: 0755]
src/Application/ApplicationFactory.h [new file with mode: 0755]
src/Application/ApplicationInformation.cpp [new file with mode: 0755]
src/Application/ApplicationInformation.h [new file with mode: 0755]
src/Application/ApplicationInformationEventPrivateData.h [new file with mode: 0755]
src/Application/ApplicationListenerManager.cpp [new file with mode: 0755]
src/Application/ApplicationListenerManager.h [new file with mode: 0755]
src/Application/ApplicationManager.cpp [new file with mode: 0755]
src/Application/ApplicationManager.h [new file with mode: 0755]
src/Application/ApplicationMetaData.cpp [new file with mode: 0644]
src/Application/ApplicationMetaData.h [new file with mode: 0644]
src/Application/ApplicationUtil.cpp [new file with mode: 0755]
src/Application/ApplicationUtil.h [new file with mode: 0755]
src/Application/CMakeLists.txt [new file with mode: 0644]
src/Application/EventApplicationAddAppInfoEventListener.h [new file with mode: 0755]
src/Application/EventApplicationAppInfoEventListener.h [new file with mode: 0755]
src/Application/EventApplicationFindAppControl.h [new file with mode: 0755]
src/Application/EventApplicationGetAppCerts.h [new file with mode: 0644]
src/Application/EventApplicationGetAppContext.h [new file with mode: 0755]
src/Application/EventApplicationGetAppInfo.h [new file with mode: 0755]
src/Application/EventApplicationGetAppSharedURI.h [new file with mode: 0644]
src/Application/EventApplicationGetAppsContext.h [new file with mode: 0755]
src/Application/EventApplicationGetAppsInfo.h [new file with mode: 0755]
src/Application/EventApplicationGetCurrApp.h [new file with mode: 0755]
src/Application/EventApplicationGetRequestedAppControl.h [new file with mode: 0755]
src/Application/EventApplicationKill.h [new file with mode: 0755]
src/Application/EventApplicationLaunch.h [new file with mode: 0755]
src/Application/EventApplicationLaunchAppControl.h [new file with mode: 0755]
src/Application/EventApplicationRemoveAppInfoEventListener.h [new file with mode: 0755]
src/Application/IApplicationManager.cpp [new file with mode: 0644]
src/Application/IApplicationManager.h [new file with mode: 0644]
src/Application/JSApplication.cpp [new file with mode: 0755]
src/Application/JSApplication.h [new file with mode: 0644]
src/Application/JSApplicationCert.cpp [new file with mode: 0644]
src/Application/JSApplicationCert.h [new file with mode: 0755]
src/Application/JSApplicationContext.cpp [new file with mode: 0644]
src/Application/JSApplicationContext.h [new file with mode: 0755]
src/Application/JSApplicationControl.cpp [new file with mode: 0755]
src/Application/JSApplicationControl.h [new file with mode: 0755]
src/Application/JSApplicationControlData.cpp [new file with mode: 0755]
src/Application/JSApplicationControlData.h [new file with mode: 0755]
src/Application/JSApplicationEventCallbackManager.cpp [new file with mode: 0755]
src/Application/JSApplicationEventCallbackManager.h [new file with mode: 0755]
src/Application/JSApplicationInformation.cpp [new file with mode: 0755]
src/Application/JSApplicationInformation.h [new file with mode: 0755]
src/Application/JSApplicationManager.cpp [new file with mode: 0755]
src/Application/JSApplicationManager.h [new file with mode: 0644]
src/Application/JSApplicationMetaData.cpp [new file with mode: 0644]
src/Application/JSApplicationMetaData.h [new file with mode: 0755]
src/Application/JSRequestedApplicationControl.cpp [new file with mode: 0644]
src/Application/JSRequestedApplicationControl.h [new file with mode: 0644]
src/Application/RequestedApplicationControl.cpp [new file with mode: 0755]
src/Application/RequestedApplicationControl.h [new file with mode: 0644]
src/Application/config.xml [new file with mode: 0755]
src/Application/plugin_config.cpp [new file with mode: 0755]
src/Application/plugin_config.h [new file with mode: 0755]
src/Application/plugin_config_impl.h [new file with mode: 0755]
src/Application/plugin_initializer.cpp [new file with mode: 0644]
src/Archive/ArchiveCallbackData.cpp [new file with mode: 0755]
src/Archive/ArchiveCallbackData.h [new file with mode: 0644]
src/Archive/ArchiveFile.cpp [new file with mode: 0644]
src/Archive/ArchiveFile.h [new file with mode: 0755]
src/Archive/ArchiveFileEntry.cpp [new file with mode: 0644]
src/Archive/ArchiveFileEntry.h [new file with mode: 0755]
src/Archive/ArchiveManager.cpp [new file with mode: 0644]
src/Archive/ArchiveManager.h [new file with mode: 0755]
src/Archive/ArchiveUtils.cpp [new file with mode: 0644]
src/Archive/ArchiveUtils.h [new file with mode: 0644]
src/Archive/CMakeLists.txt [new file with mode: 0755]
src/Archive/JSArchiveFile.cpp [new file with mode: 0755]
src/Archive/JSArchiveFile.h [new file with mode: 0644]
src/Archive/JSArchiveFileEntry.cpp [new file with mode: 0755]
src/Archive/JSArchiveFileEntry.h [new file with mode: 0644]
src/Archive/JSArchiveManager.cpp [new file with mode: 0755]
src/Archive/JSArchiveManager.h [new file with mode: 0644]
src/Archive/UnZip.cpp [new file with mode: 0644]
src/Archive/UnZip.h [new file with mode: 0644]
src/Archive/UnZipExtractRequest.cpp [new file with mode: 0644]
src/Archive/UnZipExtractRequest.h [new file with mode: 0644]
src/Archive/Zip.cpp [new file with mode: 0644]
src/Archive/Zip.h [new file with mode: 0644]
src/Archive/ZipAddRequest.cpp [new file with mode: 0644]
src/Archive/ZipAddRequest.h [new file with mode: 0644]
src/Archive/config.xml [new file with mode: 0755]
src/Archive/plugin_config.cpp [new file with mode: 0755]
src/Archive/plugin_config.h [new file with mode: 0755]
src/Archive/plugin_config_impl.h [new file with mode: 0755]
src/Archive/plugin_initializer.cpp [new file with mode: 0644]
src/Badge/BadgeManager.cpp [new file with mode: 0755]
src/Badge/BadgeManager.h [new file with mode: 0755]
src/Badge/BadgeUtil.cpp [new file with mode: 0755]
src/Badge/BadgeUtil.h [new file with mode: 0755]
src/Badge/CMakeLists.txt [new file with mode: 0755]
src/Badge/JSBadgeManager.cpp [new file with mode: 0755]
src/Badge/JSBadgeManager.h [new file with mode: 0755]
src/Badge/config.xml [new file with mode: 0755]
src/Badge/plugin_config.cpp [new file with mode: 0755]
src/Badge/plugin_config.h [new file with mode: 0755]
src/Badge/plugin_initializer.cpp [new file with mode: 0755]
src/Bluetooth/BluetoothAdapter.cpp [new file with mode: 0755]
src/Bluetooth/BluetoothAdapter.h [new file with mode: 0755]
src/Bluetooth/BluetoothCallback.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothCallback.h [new file with mode: 0644]
src/Bluetooth/BluetoothCallbackUtil.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothCallbackUtil.h [new file with mode: 0644]
src/Bluetooth/BluetoothClass.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothClass.h [new file with mode: 0644]
src/Bluetooth/BluetoothClassDeviceMajor.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothClassDeviceMajor.h [new file with mode: 0644]
src/Bluetooth/BluetoothClassDeviceMinor.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothClassDeviceMinor.h [new file with mode: 0644]
src/Bluetooth/BluetoothClassDeviceService.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothClassDeviceService.h [new file with mode: 0644]
src/Bluetooth/BluetoothDevice.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothDevice.h [new file with mode: 0644]
src/Bluetooth/BluetoothHealthApplication.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothHealthApplication.h [new file with mode: 0644]
src/Bluetooth/BluetoothHealthChannel.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothHealthChannel.h [new file with mode: 0644]
src/Bluetooth/BluetoothHealthProfileHandler.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothHealthProfileHandler.h [new file with mode: 0644]
src/Bluetooth/BluetoothHealthProfileHandlerCallback.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothHealthProfileHandlerCallback.h [new file with mode: 0644]
src/Bluetooth/BluetoothServiceHandler.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothServiceHandler.h [new file with mode: 0644]
src/Bluetooth/BluetoothSocket.cpp [new file with mode: 0755]
src/Bluetooth/BluetoothSocket.h [new file with mode: 0644]
src/Bluetooth/BluetoothUtil.cpp [new file with mode: 0644]
src/Bluetooth/BluetoothUtil.h [new file with mode: 0644]
src/Bluetooth/CMakeLists.txt [new file with mode: 0644]
src/Bluetooth/JSBluetoothAdapter.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothAdapter.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothClass.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothClass.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothClassDeviceMajor.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothClassDeviceMajor.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothClassDeviceMinor.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothClassDeviceMinor.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothClassDeviceService.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothClassDeviceService.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothDevice.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothDevice.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothHealthApplication.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothHealthApplication.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothHealthChannel.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothHealthChannel.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothHealthProfileHandler.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothHealthProfileHandler.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothManager.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothManager.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothProfileHandler.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothProfileHandler.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothServiceHandler.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothServiceHandler.h [new file with mode: 0644]
src/Bluetooth/JSBluetoothSocket.cpp [new file with mode: 0644]
src/Bluetooth/JSBluetoothSocket.h [new file with mode: 0644]
src/Bluetooth/config.xml [new file with mode: 0644]
src/Bluetooth/plugin_config.cpp [new file with mode: 0644]
src/Bluetooth/plugin_config.h [new file with mode: 0644]
src/Bluetooth/plugin_config_impl.h [new file with mode: 0644]
src/Bluetooth/plugin_initializer.cpp [new file with mode: 0644]
src/Bookmark/BookmarkData.h [new file with mode: 0755]
src/Bookmark/BookmarkManager.cpp [new file with mode: 0755]
src/Bookmark/BookmarkManager.h [new file with mode: 0755]
src/Bookmark/BookmarkUtil.cpp [new file with mode: 0644]
src/Bookmark/BookmarkUtil.h [new file with mode: 0644]
src/Bookmark/CMakeLists.txt [new file with mode: 0755]
src/Bookmark/JSBookmarkFolder.cpp [new file with mode: 0755]
src/Bookmark/JSBookmarkFolder.h [new file with mode: 0755]
src/Bookmark/JSBookmarkItem.cpp [new file with mode: 0755]
src/Bookmark/JSBookmarkItem.h [new file with mode: 0755]
src/Bookmark/JSBookmarkManager.cpp [new file with mode: 0755]
src/Bookmark/JSBookmarkManager.h [new file with mode: 0755]
src/Bookmark/config.xml [new file with mode: 0755]
src/Bookmark/plugin_config.cpp [new file with mode: 0755]
src/Bookmark/plugin_config.h [new file with mode: 0755]
src/Bookmark/plugin_initializer.cpp [new file with mode: 0644]
src/CMakeLists.txt [new file with mode: 0755]
src/Calendar/CMakeLists.txt [new file with mode: 0755]
src/Calendar/Calendar.cpp [new file with mode: 0755]
src/Calendar/Calendar.h [new file with mode: 0755]
src/Calendar/CalendarAlarm.cpp [new file with mode: 0755]
src/Calendar/CalendarAlarm.h [new file with mode: 0644]
src/Calendar/CalendarAttendee.cpp [new file with mode: 0755]
src/Calendar/CalendarAttendee.h [new file with mode: 0755]
src/Calendar/CalendarCallbackUserData.cpp [new file with mode: 0755]
src/Calendar/CalendarCallbackUserData.h [new file with mode: 0644]
src/Calendar/CalendarChangeCallback.cpp [new file with mode: 0755]
src/Calendar/CalendarChangeCallback.h [new file with mode: 0644]
src/Calendar/CalendarEvent.cpp [new file with mode: 0755]
src/Calendar/CalendarEvent.h [new file with mode: 0644]
src/Calendar/CalendarEventId.cpp [new file with mode: 0644]
src/Calendar/CalendarEventId.h [new file with mode: 0644]
src/Calendar/CalendarFindCallbackData.cpp [new file with mode: 0644]
src/Calendar/CalendarFindCallbackData.h [new file with mode: 0644]
src/Calendar/CalendarItem.cpp [new file with mode: 0755]
src/Calendar/CalendarItem.h [new file with mode: 0644]
src/Calendar/CalendarItemSearchEngine.cpp [new file with mode: 0755]
src/Calendar/CalendarItemSearchEngine.h [new file with mode: 0755]
src/Calendar/CalendarManager.cpp [new file with mode: 0755]
src/Calendar/CalendarManager.h [new file with mode: 0644]
src/Calendar/CalendarRecurrenceRule.cpp [new file with mode: 0755]
src/Calendar/CalendarRecurrenceRule.h [new file with mode: 0644]
src/Calendar/CalendarTask.cpp [new file with mode: 0755]
src/Calendar/CalendarTask.h [new file with mode: 0644]
src/Calendar/CalendarUtility.cpp [new file with mode: 0755]
src/Calendar/CalendarUtility.h [new file with mode: 0644]
src/Calendar/ChangeListenerContainer.cpp [new file with mode: 0755]
src/Calendar/ChangeListenerContainer.h [new file with mode: 0644]
src/Calendar/JSCalendar.cpp [new file with mode: 0755]
src/Calendar/JSCalendar.h [new file with mode: 0644]
src/Calendar/JSCalendarAlarm.cpp [new file with mode: 0755]
src/Calendar/JSCalendarAlarm.h [new file with mode: 0755]
src/Calendar/JSCalendarAttendee.cpp [new file with mode: 0755]
src/Calendar/JSCalendarAttendee.h [new file with mode: 0755]
src/Calendar/JSCalendarEvent.cpp [new file with mode: 0755]
src/Calendar/JSCalendarEvent.h [new file with mode: 0755]
src/Calendar/JSCalendarEventId.cpp [new file with mode: 0755]
src/Calendar/JSCalendarEventId.h [new file with mode: 0755]
src/Calendar/JSCalendarItem.cpp [new file with mode: 0755]
src/Calendar/JSCalendarItem.h [new file with mode: 0755]
src/Calendar/JSCalendarManager.cpp [new file with mode: 0755]
src/Calendar/JSCalendarManager.h [new file with mode: 0755]
src/Calendar/JSCalendarRecurrenceRule.cpp [new file with mode: 0755]
src/Calendar/JSCalendarRecurrenceRule.h [new file with mode: 0755]
src/Calendar/JSCalendarTask.cpp [new file with mode: 0755]
src/Calendar/JSCalendarTask.h [new file with mode: 0755]
src/Calendar/config.xml [new file with mode: 0755]
src/Calendar/plugin_config.cpp [new file with mode: 0755]
src/Calendar/plugin_config.h [new file with mode: 0755]
src/Calendar/plugin_config_impl.h [new file with mode: 0644]
src/Calendar/plugin_initializer.cpp [new file with mode: 0755]
src/Callhistory/CMakeLists.txt [new file with mode: 0755]
src/Callhistory/CallHistory.cpp [new file with mode: 0755]
src/Callhistory/CallHistory.h [new file with mode: 0755]
src/Callhistory/CallHistoryChangeCallback.cpp [new file with mode: 0755]
src/Callhistory/CallHistoryChangeCallback.h [new file with mode: 0755]
src/Callhistory/CallHistoryEntry.cpp [new file with mode: 0755]
src/Callhistory/CallHistoryEntry.h [new file with mode: 0755]
src/Callhistory/CallHistoryEntryArraySuccessCallback.cpp [new file with mode: 0755]
src/Callhistory/CallHistoryEntryArraySuccessCallback.h [new file with mode: 0755]
src/Callhistory/CallHistoryFilterQueryGenerator.cpp [new file with mode: 0755]
src/Callhistory/CallHistoryFilterQueryGenerator.h [new file with mode: 0755]
src/Callhistory/CallHistoryTypes.h [new file with mode: 0755]
src/Callhistory/CallHistoryUtil.cpp [new file with mode: 0644]
src/Callhistory/CallHistoryUtil.h [new file with mode: 0644]
src/Callhistory/Converter.cpp [new file with mode: 0755]
src/Callhistory/Converter.h [new file with mode: 0755]
src/Callhistory/JSCallHistory.cpp [new file with mode: 0755]
src/Callhistory/JSCallHistory.h [new file with mode: 0755]
src/Callhistory/JSCallHistoryEntry.cpp [new file with mode: 0755]
src/Callhistory/JSCallHistoryEntry.h [new file with mode: 0755]
src/Callhistory/JSRemoteParty.cpp [new file with mode: 0755]
src/Callhistory/JSRemoteParty.h [new file with mode: 0755]
src/Callhistory/RemoteParty.cpp [new file with mode: 0755]
src/Callhistory/RemoteParty.h [new file with mode: 0755]
src/Callhistory/config.xml [new file with mode: 0755]
src/Callhistory/plugin_config.cpp [new file with mode: 0755]
src/Callhistory/plugin_config.h [new file with mode: 0755]
src/Callhistory/plugin_config_impl.h [new file with mode: 0644]
src/Callhistory/plugin_initializer.cpp [new file with mode: 0755]
src/Common/ArgumentValidator.cpp [new file with mode: 0755]
src/Common/ArgumentValidator.h [new file with mode: 0755]
src/Common/AsyncCallbackManager.cpp [new file with mode: 0644]
src/Common/AsyncCallbackManager.h [new file with mode: 0644]
src/Common/CMakeLists.txt [new file with mode: 0755]
src/Common/CallbackUserData.cpp [new file with mode: 0644]
src/Common/CallbackUserData.h [new file with mode: 0644]
src/Common/DBusOperation.cpp [new file with mode: 0755]
src/Common/DBusOperation.h [new file with mode: 0755]
src/Common/Export.h [new file with mode: 0644]
src/Common/GlobalContextManager.cpp [new file with mode: 0644]
src/Common/GlobalContextManager.h [new file with mode: 0644]
src/Common/IListenerManager.h [new file with mode: 0644]
src/Common/JSArray.cpp [new file with mode: 0755]
src/Common/JSArray.h [new file with mode: 0755]
src/Common/JSStringRefWrapper.cpp [new file with mode: 0644]
src/Common/JSStringRefWrapper.h [new file with mode: 0644]
src/Common/JSTizenSecurityObject.cpp [new file with mode: 0644]
src/Common/JSTizenSecurityObject.h [new file with mode: 0644]
src/Common/JSUtil.cpp [new file with mode: 0755]
src/Common/JSUtil.h [new file with mode: 0644]
src/Common/JSVector.h [new file with mode: 0644]
src/Common/JSWebAPIError.cpp [new file with mode: 0644]
src/Common/JSWebAPIError.h [new file with mode: 0644]
src/Common/JSWebAPIErrorFactory.cpp [new file with mode: 0644]
src/Common/JSWebAPIErrorFactory.h [new file with mode: 0644]
src/Common/JSWebAPIException.cpp [new file with mode: 0644]
src/Common/JSWebAPIException.h [new file with mode: 0644]
src/Common/Logger.h [new file with mode: 0755]
src/Common/MultiCallbackUserData.cpp [new file with mode: 0755]
src/Common/MultiCallbackUserData.h [new file with mode: 0755]
src/Common/PlatformException.cpp [new file with mode: 0644]
src/Common/PlatformException.h [new file with mode: 0644]
src/Common/PropertyBag.cpp [new file with mode: 0755]
src/Common/PropertyBag.h [new file with mode: 0755]
src/Common/Security.h [new file with mode: 0644]
src/Common/SecurityAccessor.cpp [new file with mode: 0644]
src/Common/SecurityAccessor.h [new file with mode: 0644]
src/Common/SecurityExceptions.h [new file with mode: 0644]
src/Common/Singleton.h [new file with mode: 0644]
src/Common/StandaloneConsole/CMakeLists.txt [new file with mode: 0644]
src/Common/StandaloneConsole/JSConsole.cpp [new file with mode: 0755]
src/Common/StandaloneConsole/JSConsole.h [new file with mode: 0644]
src/Common/StandaloneConsole/StandaloneConsole.cpp [new file with mode: 0755]
src/Common/StandaloneConsole/StandaloneConsole.h [new file with mode: 0644]
src/Common/TimeTracer/CMakeLists.txt [new file with mode: 0644]
src/Common/TimeTracer/TimeTracer.c [new file with mode: 0755]
src/Common/TimeTracer/TimeTracer.h [new file with mode: 0755]
src/Common/WebAPIError.cpp [new file with mode: 0644]
src/Common/WebAPIError.h [new file with mode: 0644]
src/Common/WebKitProxy.cpp [new file with mode: 0644]
src/Common/WebKitProxy.h [new file with mode: 0644]
src/Contact/AddressBook.cpp [new file with mode: 0755]
src/Contact/AddressBook.h [new file with mode: 0644]
src/Contact/AddressBookCallbackData.cpp [new file with mode: 0644]
src/Contact/AddressBookCallbackData.h [new file with mode: 0644]
src/Contact/AddressBookChangeCallback.cpp [new file with mode: 0644]
src/Contact/AddressBookChangeCallback.h [new file with mode: 0644]
src/Contact/CMakeLists.txt [new file with mode: 0755]
src/Contact/Contact.cpp [new file with mode: 0644]
src/Contact/Contact.h [new file with mode: 0644]
src/Contact/ContactAddress.cpp [new file with mode: 0644]
src/Contact/ContactAddress.h [new file with mode: 0644]
src/Contact/ContactAnniversary.cpp [new file with mode: 0644]
src/Contact/ContactAnniversary.h [new file with mode: 0644]
src/Contact/ContactEmailAddress.cpp [new file with mode: 0644]
src/Contact/ContactEmailAddress.h [new file with mode: 0644]
src/Contact/ContactGroup.cpp [new file with mode: 0644]
src/Contact/ContactGroup.h [new file with mode: 0644]
src/Contact/ContactInstantMessenger.cpp [new file with mode: 0644]
src/Contact/ContactInstantMessenger.h [new file with mode: 0644]
src/Contact/ContactManager.cpp [new file with mode: 0755]
src/Contact/ContactManager.h [new file with mode: 0644]
src/Contact/ContactManagerCallbackData.cpp [new file with mode: 0644]
src/Contact/ContactManagerCallbackData.h [new file with mode: 0644]
src/Contact/ContactName.cpp [new file with mode: 0644]
src/Contact/ContactName.h [new file with mode: 0644]
src/Contact/ContactOrganization.cpp [new file with mode: 0644]
src/Contact/ContactOrganization.h [new file with mode: 0644]
src/Contact/ContactPhoneNumber.cpp [new file with mode: 0644]
src/Contact/ContactPhoneNumber.h [new file with mode: 0644]
src/Contact/ContactRef.cpp [new file with mode: 0644]
src/Contact/ContactRef.h [new file with mode: 0644]
src/Contact/ContactRelationship.cpp [new file with mode: 0644]
src/Contact/ContactRelationship.h [new file with mode: 0644]
src/Contact/ContactSearchEngine.cpp [new file with mode: 0644]
src/Contact/ContactSearchEngine.h [new file with mode: 0644]
src/Contact/ContactUtil.cpp [new file with mode: 0644]
src/Contact/ContactUtil.h [new file with mode: 0644]
src/Contact/ContactWebSite.cpp [new file with mode: 0644]
src/Contact/ContactWebSite.h [new file with mode: 0644]
src/Contact/JSAddressBook.cpp [new file with mode: 0644]
src/Contact/JSAddressBook.h [new file with mode: 0755]
src/Contact/JSContact.cpp [new file with mode: 0644]
src/Contact/JSContact.h [new file with mode: 0755]
src/Contact/JSContactAddress.cpp [new file with mode: 0755]
src/Contact/JSContactAddress.h [new file with mode: 0755]
src/Contact/JSContactAnniversary.cpp [new file with mode: 0644]
src/Contact/JSContactAnniversary.h [new file with mode: 0755]
src/Contact/JSContactEmailAddress.cpp [new file with mode: 0755]
src/Contact/JSContactEmailAddress.h [new file with mode: 0755]
src/Contact/JSContactGroup.cpp [new file with mode: 0644]
src/Contact/JSContactGroup.h [new file with mode: 0755]
src/Contact/JSContactInstantMessenger.cpp [new file with mode: 0644]
src/Contact/JSContactInstantMessenger.h [new file with mode: 0644]
src/Contact/JSContactManager.cpp [new file with mode: 0644]
src/Contact/JSContactManager.h [new file with mode: 0755]
src/Contact/JSContactName.cpp [new file with mode: 0644]
src/Contact/JSContactName.h [new file with mode: 0755]
src/Contact/JSContactOrganization.cpp [new file with mode: 0644]
src/Contact/JSContactOrganization.h [new file with mode: 0755]
src/Contact/JSContactPhoneNumber.cpp [new file with mode: 0755]
src/Contact/JSContactPhoneNumber.h [new file with mode: 0755]
src/Contact/JSContactRef.cpp [new file with mode: 0644]
src/Contact/JSContactRef.h [new file with mode: 0755]
src/Contact/JSContactRelationship.cpp [new file with mode: 0644]
src/Contact/JSContactRelationship.h [new file with mode: 0644]
src/Contact/JSContactWebSite.cpp [new file with mode: 0644]
src/Contact/JSContactWebSite.h [new file with mode: 0755]
src/Contact/JSPerson.cpp [new file with mode: 0644]
src/Contact/JSPerson.h [new file with mode: 0755]
src/Contact/Person.cpp [new file with mode: 0644]
src/Contact/Person.h [new file with mode: 0644]
src/Contact/PersonChangeCallback.cpp [new file with mode: 0644]
src/Contact/PersonChangeCallback.h [new file with mode: 0644]
src/Contact/PersonSearchEngine.cpp [new file with mode: 0755]
src/Contact/PersonSearchEngine.h [new file with mode: 0644]
src/Contact/config.xml [new file with mode: 0755]
src/Contact/plugin_config.cpp [new file with mode: 0755]
src/Contact/plugin_config.h [new file with mode: 0755]
src/Contact/plugin_config_impl.h [new file with mode: 0644]
src/Contact/plugin_initializer.cpp [new file with mode: 0644]
src/Content/AddBatchCallbackUserData.cpp [new file with mode: 0644]
src/Content/AddBatchCallbackUserData.h [new file with mode: 0644]
src/Content/AudioContent.cpp [new file with mode: 0755]
src/Content/AudioContent.h [new file with mode: 0755]
src/Content/AudioContentLyrics.cpp [new file with mode: 0644]
src/Content/AudioContentLyrics.h [new file with mode: 0755]
src/Content/AudioLyricsUtil.cpp [new file with mode: 0755]
src/Content/AudioLyricsUtil.h [new file with mode: 0755]
src/Content/BaseCallbackUserData.cpp [new file with mode: 0644]
src/Content/BaseCallbackUserData.h [new file with mode: 0644]
src/Content/CMakeLists.txt [new file with mode: 0755]
src/Content/Content.cpp [new file with mode: 0755]
src/Content/Content.h [new file with mode: 0755]
src/Content/ContentCallback.cpp [new file with mode: 0644]
src/Content/ContentCallback.h [new file with mode: 0755]
src/Content/ContentChangeCallback.cpp [new file with mode: 0755]
src/Content/ContentChangeCallback.h [new file with mode: 0755]
src/Content/ContentDirectory.cpp [new file with mode: 0644]
src/Content/ContentDirectory.h [new file with mode: 0755]
src/Content/ContentFilterQueryGenerator.cpp [new file with mode: 0644]
src/Content/ContentFilterQueryGenerator.h [new file with mode: 0644]
src/Content/ContentFindCallback.h [new file with mode: 0755]
src/Content/ContentGetDirectoryCallback.h [new file with mode: 0755]
src/Content/ContentHelper.cpp [new file with mode: 0755]
src/Content/ContentHelper.h [new file with mode: 0755]
src/Content/ContentManager.cpp [new file with mode: 0755]
src/Content/ContentManager.h [new file with mode: 0755]
src/Content/ContentScanFileCallback.h [new file with mode: 0755]
src/Content/ContentTypes.h [new file with mode: 0644]
src/Content/ContentUpdateBatchCallback.h [new file with mode: 0755]
src/Content/ContentUtility.cpp [new file with mode: 0755]
src/Content/ContentUtility.h [new file with mode: 0755]
src/Content/CreatePlaylistCallbackUserData.cpp [new file with mode: 0644]
src/Content/CreatePlaylistCallbackUserData.h [new file with mode: 0644]
src/Content/GetPlaylistItemsRequest.cpp [new file with mode: 0755]
src/Content/GetPlaylistItemsRequest.h [new file with mode: 0644]
src/Content/GetPlaylistsRequest.cpp [new file with mode: 0644]
src/Content/GetPlaylistsRequest.h [new file with mode: 0644]
src/Content/ImageContent.cpp [new file with mode: 0755]
src/Content/ImageContent.h [new file with mode: 0755]
src/Content/JSAudioContent.cpp [new file with mode: 0755]
src/Content/JSAudioContent.h [new file with mode: 0755]
src/Content/JSAudioContentLyrics.cpp [new file with mode: 0755]
src/Content/JSAudioContentLyrics.h [new file with mode: 0755]
src/Content/JSContent.cpp [new file with mode: 0755]
src/Content/JSContent.h [new file with mode: 0755]
src/Content/JSContentDirectory.cpp [new file with mode: 0755]
src/Content/JSContentDirectory.h [new file with mode: 0755]
src/Content/JSContentManager.cpp [new file with mode: 0755]
src/Content/JSContentManager.h [new file with mode: 0644]
src/Content/JSImageContent.cpp [new file with mode: 0755]
src/Content/JSImageContent.h [new file with mode: 0755]
src/Content/JSPlaylist.cpp [new file with mode: 0644]
src/Content/JSPlaylist.h [new file with mode: 0644]
src/Content/JSPlaylistItem.cpp [new file with mode: 0644]
src/Content/JSPlaylistItem.h [new file with mode: 0644]
src/Content/JSVideoContent.cpp [new file with mode: 0755]
src/Content/JSVideoContent.h [new file with mode: 0755]
src/Content/MoveItemCallbackUserData.cpp [new file with mode: 0644]
src/Content/MoveItemCallbackUserData.h [new file with mode: 0644]
src/Content/Playlist.cpp [new file with mode: 0644]
src/Content/Playlist.h [new file with mode: 0644]
src/Content/PlaylistArraySuccessCallbackUserData.cpp [new file with mode: 0644]
src/Content/PlaylistArraySuccessCallbackUserData.h [new file with mode: 0644]
src/Content/PlaylistContentCallback.cpp [new file with mode: 0644]
src/Content/PlaylistContentCallback.h [new file with mode: 0755]
src/Content/PlaylistCopyUtil.cpp [new file with mode: 0644]
src/Content/PlaylistCopyUtil.h [new file with mode: 0644]
src/Content/PlaylistItem.cpp [new file with mode: 0644]
src/Content/PlaylistItem.h [new file with mode: 0644]
src/Content/PlaylistUtils.cpp [new file with mode: 0644]
src/Content/PlaylistUtils.h [new file with mode: 0644]
src/Content/RemoveBatchCallbackUserData.cpp [new file with mode: 0644]
src/Content/RemoveBatchCallbackUserData.h [new file with mode: 0644]
src/Content/RemovePlaylistCallbackUserData.cpp [new file with mode: 0644]
src/Content/RemovePlaylistCallbackUserData.h [new file with mode: 0644]
src/Content/SetItemsOrderCallbackUserData.cpp [new file with mode: 0644]
src/Content/SetItemsOrderCallbackUserData.h [new file with mode: 0644]
src/Content/VideoContent.cpp [new file with mode: 0755]
src/Content/VideoContent.h [new file with mode: 0755]
src/Content/config.xml [new file with mode: 0644]
src/Content/plugin_config.cpp [new file with mode: 0755]
src/Content/plugin_config.h [new file with mode: 0644]
src/Content/plugin_config_impl.h [new file with mode: 0644]
src/Content/plugin_initializer.cpp [new file with mode: 0755]
src/DataControl/CMakeLists.txt [new file with mode: 0755]
src/DataControl/DataControlCallback.cpp [new file with mode: 0755]
src/DataControl/DataControlCallback.h [new file with mode: 0755]
src/DataControl/DataControlConsumer.cpp [new file with mode: 0755]
src/DataControl/DataControlConsumer.h [new file with mode: 0755]
src/DataControl/DataControlGetValueCallback.cpp [new file with mode: 0755]
src/DataControl/DataControlGetValueCallback.h [new file with mode: 0755]
src/DataControl/DataControlInsertCallback.cpp [new file with mode: 0755]
src/DataControl/DataControlInsertCallback.h [new file with mode: 0755]
src/DataControl/DataControlMapCallback.cpp [new file with mode: 0755]
src/DataControl/DataControlMapCallback.h [new file with mode: 0755]
src/DataControl/DataControlSQLCallback.cpp [new file with mode: 0755]
src/DataControl/DataControlSQLCallback.h [new file with mode: 0755]
src/DataControl/DataControlSelectCallback.cpp [new file with mode: 0755]
src/DataControl/DataControlSelectCallback.h [new file with mode: 0755]
src/DataControl/JSDataControlConsumer.cpp [new file with mode: 0755]
src/DataControl/JSDataControlConsumer.h [new file with mode: 0755]
src/DataControl/JSDataControlManager.cpp [new file with mode: 0755]
src/DataControl/JSDataControlManager.h [new file with mode: 0755]
src/DataControl/JSMappedDataControlConsumer.cpp [new file with mode: 0755]
src/DataControl/JSMappedDataControlConsumer.h [new file with mode: 0755]
src/DataControl/JSSQLDataControlConsumer.cpp [new file with mode: 0755]
src/DataControl/JSSQLDataControlConsumer.h [new file with mode: 0755]
src/DataControl/MappedDataControlConsumer.cpp [new file with mode: 0755]
src/DataControl/MappedDataControlConsumer.h [new file with mode: 0755]
src/DataControl/SQLDataControlConsumer.cpp [new file with mode: 0755]
src/DataControl/SQLDataControlConsumer.h [new file with mode: 0755]
src/DataControl/config.xml [new file with mode: 0755]
src/DataControl/plugin_config.cpp [new file with mode: 0755]
src/DataControl/plugin_config.h [new file with mode: 0755]
src/DataControl/plugin_config_impl.h [new file with mode: 0755]
src/DataControl/plugin_initializer.cpp [new file with mode: 0755]
src/DataSync/CMakeLists.txt [new file with mode: 0755]
src/DataSync/DataSyncConverter.cpp [new file with mode: 0755]
src/DataSync/DataSyncConverter.h [new file with mode: 0755]
src/DataSync/DataSyncManager.cpp [new file with mode: 0755]
src/DataSync/DataSyncManager.h [new file with mode: 0755]
src/DataSync/DataSyncMultiCallback.h [new file with mode: 0755]
src/DataSync/DataSyncResponseDispatcher.cpp [new file with mode: 0755]
src/DataSync/DataSyncResponseDispatcher.h [new file with mode: 0755]
src/DataSync/IDataSyncManager.cpp [new file with mode: 0755]
src/DataSync/IDataSyncManager.h [new file with mode: 0755]
src/DataSync/IEventAddProfile.h [new file with mode: 0755]
src/DataSync/IEventGetAllProfiles.h [new file with mode: 0755]
src/DataSync/IEventGetLastSyncStatistics.h [new file with mode: 0755]
src/DataSync/IEventGetMaxProfilesNum.h [new file with mode: 0755]
src/DataSync/IEventGetProfile.h [new file with mode: 0755]
src/DataSync/IEventGetProfilesNum.h [new file with mode: 0755]
src/DataSync/IEventRemoveProfile.h [new file with mode: 0755]
src/DataSync/IEventStartSync.h [new file with mode: 0755]
src/DataSync/IEventStopSync.h [new file with mode: 0755]
src/DataSync/IEventUpdateProfile.h [new file with mode: 0755]
src/DataSync/JSDataSyncManager.cpp [new file with mode: 0755]
src/DataSync/JSDataSyncManager.h [new file with mode: 0755]
src/DataSync/JSSyncInfo.cpp [new file with mode: 0755]
src/DataSync/JSSyncInfo.h [new file with mode: 0755]
src/DataSync/JSSyncProfileInfo.cpp [new file with mode: 0755]
src/DataSync/JSSyncProfileInfo.h [new file with mode: 0755]
src/DataSync/JSSyncServiceInfo.cpp [new file with mode: 0755]
src/DataSync/JSSyncServiceInfo.h [new file with mode: 0755]
src/DataSync/JSSyncStatistics.cpp [new file with mode: 0644]
src/DataSync/JSSyncStatistics.h [new file with mode: 0755]
src/DataSync/OnDataSyncStateChanged.h [new file with mode: 0755]
src/DataSync/SyncInfo.cpp [new file with mode: 0755]
src/DataSync/SyncInfo.h [new file with mode: 0755]
src/DataSync/SyncProfileInfo.cpp [new file with mode: 0755]
src/DataSync/SyncProfileInfo.h [new file with mode: 0755]
src/DataSync/SyncServiceInfo.cpp [new file with mode: 0755]
src/DataSync/SyncServiceInfo.h [new file with mode: 0755]
src/DataSync/SyncStatistics.cpp [new file with mode: 0755]
src/DataSync/SyncStatistics.h [new file with mode: 0755]
src/DataSync/config.xml [new file with mode: 0755]
src/DataSync/plugin_config.cpp [new file with mode: 0755]
src/DataSync/plugin_config.h [new file with mode: 0755]
src/DataSync/plugin_initializer.cpp [new file with mode: 0755]
src/Download/CMakeLists.txt [new file with mode: 0755]
src/Download/DownloadCallback.cpp [new file with mode: 0755]
src/Download/DownloadCallback.h [new file with mode: 0755]
src/Download/DownloadManager.cpp [new file with mode: 0755]
src/Download/DownloadManager.h [new file with mode: 0755]
src/Download/DownloadNetworkType.h [new file with mode: 0755]
src/Download/DownloadRequest.cpp [new file with mode: 0755]
src/Download/DownloadRequest.h [new file with mode: 0755]
src/Download/DownloadState.h [new file with mode: 0755]
src/Download/DownloadUtil.cpp [new file with mode: 0755]
src/Download/DownloadUtil.h [new file with mode: 0755]
src/Download/JSDownloadManager.cpp [new file with mode: 0755]
src/Download/JSDownloadManager.h [new file with mode: 0755]
src/Download/JSDownloadRequest.cpp [new file with mode: 0755]
src/Download/JSDownloadRequest.h [new file with mode: 0755]
src/Download/config.xml [new file with mode: 0755]
src/Download/plugin_config.cpp [new file with mode: 0755]
src/Download/plugin_config.h [new file with mode: 0755]
src/Download/plugin_config_impl.h [new file with mode: 0755]
src/Download/plugin_initializer.cpp [new file with mode: 0755]
src/Exif/CMakeLists.txt [new file with mode: 0644]
src/Exif/ExifGPSLocation.cpp [new file with mode: 0644]
src/Exif/ExifGPSLocation.h [new file with mode: 0644]
src/Exif/ExifGPSTime.cpp [new file with mode: 0644]
src/Exif/ExifGPSTime.h [new file with mode: 0644]
src/Exif/ExifInformation.cpp [new file with mode: 0644]
src/Exif/ExifInformation.h [new file with mode: 0644]
src/Exif/ExifManager.cpp [new file with mode: 0755]
src/Exif/ExifManager.h [new file with mode: 0755]
src/Exif/ExifManagerCallbacks.cpp [new file with mode: 0644]
src/Exif/ExifManagerCallbacks.h [new file with mode: 0755]
src/Exif/ExifTagSaver.cpp [new file with mode: 0644]
src/Exif/ExifTagSaver.h [new file with mode: 0644]
src/Exif/ExifUtil.cpp [new file with mode: 0644]
src/Exif/ExifUtil.h [new file with mode: 0644]
src/Exif/JSExifInformation.cpp [new file with mode: 0644]
src/Exif/JSExifInformation.h [new file with mode: 0644]
src/Exif/JSExifManager.cpp [new file with mode: 0755]
src/Exif/JSExifManager.h [new file with mode: 0644]
src/Exif/JpegFile.cpp [new file with mode: 0644]
src/Exif/JpegFile.h [new file with mode: 0644]
src/Exif/Rational.cpp [new file with mode: 0644]
src/Exif/Rational.h [new file with mode: 0644]
src/Exif/config.xml [new file with mode: 0644]
src/Exif/plugin_config.cpp [new file with mode: 0644]
src/Exif/plugin_config.h [new file with mode: 0644]
src/Exif/plugin_config_impl.h [new file with mode: 0644]
src/Exif/plugin_initializer.cpp [new file with mode: 0644]
src/FMRadio/CMakeLists.txt [new file with mode: 0755]
src/FMRadio/FMRadioCallback.cpp [new file with mode: 0755]
src/FMRadio/FMRadioCallback.h [new file with mode: 0755]
src/FMRadio/FMRadioManager.cpp [new file with mode: 0755]
src/FMRadio/FMRadioManager.h [new file with mode: 0755]
src/FMRadio/FMRadioUtil.cpp [new file with mode: 0755]
src/FMRadio/FMRadioUtil.h [new file with mode: 0755]
src/FMRadio/JSFMRadioManager.cpp [new file with mode: 0755]
src/FMRadio/JSFMRadioManager.h [new file with mode: 0755]
src/FMRadio/config.xml [new file with mode: 0755]
src/FMRadio/plugin_config.cpp [new file with mode: 0755]
src/FMRadio/plugin_config.h [new file with mode: 0755]
src/FMRadio/plugin_initializer.cpp [new file with mode: 0755]
src/Filesystem/CMakeLists.txt [new file with mode: 0755]
src/Filesystem/Converter.cpp [new file with mode: 0755]
src/Filesystem/Converter.h [new file with mode: 0644]
src/Filesystem/Encodings.cpp [new file with mode: 0755]
src/Filesystem/Encodings.h [new file with mode: 0644]
src/Filesystem/Enums.h [new file with mode: 0644]
src/Filesystem/EventCopy.cpp [new file with mode: 0755]
src/Filesystem/EventCopy.h [new file with mode: 0644]
src/Filesystem/EventGetStorage.cpp [new file with mode: 0755]
src/Filesystem/EventGetStorage.h [new file with mode: 0644]
src/Filesystem/EventListNodes.cpp [new file with mode: 0755]
src/Filesystem/EventListNodes.h [new file with mode: 0644]
src/Filesystem/EventListStorages.cpp [new file with mode: 0755]
src/Filesystem/EventListStorages.h [new file with mode: 0644]
src/Filesystem/EventMove.cpp [new file with mode: 0755]
src/Filesystem/EventMove.h [new file with mode: 0644]
src/Filesystem/EventOpen.cpp [new file with mode: 0755]
src/Filesystem/EventOpen.h [new file with mode: 0644]
src/Filesystem/EventReadText.h [new file with mode: 0644]
src/Filesystem/EventRemove.cpp [new file with mode: 0755]
src/Filesystem/EventRemove.h [new file with mode: 0644]
src/Filesystem/EventResolve.cpp [new file with mode: 0755]
src/Filesystem/EventResolve.h [new file with mode: 0644]
src/Filesystem/EventStorageStateChanged.cpp [new file with mode: 0755]
src/Filesystem/EventStorageStateChanged.h [new file with mode: 0644]
src/Filesystem/File.cpp [new file with mode: 0644]
src/Filesystem/File.h [new file with mode: 0644]
src/Filesystem/FilesystemErrorUtil.cpp [new file with mode: 0755]
src/Filesystem/FilesystemErrorUtil.h [new file with mode: 0755]
src/Filesystem/FilesystemExternalUtils.cpp [new file with mode: 0755]
src/Filesystem/FilesystemExternalUtils.h [new file with mode: 0644]
src/Filesystem/FilesystemPathUtils.cpp [new file with mode: 0755]
src/Filesystem/FilesystemPathUtils.h [new file with mode: 0644]
src/Filesystem/FilesystemUtils.cpp [new file with mode: 0755]
src/Filesystem/FilesystemUtils.h [new file with mode: 0755]
src/Filesystem/JSErrors.cpp [new file with mode: 0755]
src/Filesystem/JSErrors.h [new file with mode: 0644]
src/Filesystem/JSFile.cpp [new file with mode: 0755]
src/Filesystem/JSFile.h [new file with mode: 0644]
src/Filesystem/JSFilestream.cpp [new file with mode: 0755]
src/Filesystem/JSFilestream.h [new file with mode: 0644]
src/Filesystem/JSFilesystemManager.cpp [new file with mode: 0755]
src/Filesystem/JSFilesystemManager.h [new file with mode: 0644]
src/Filesystem/JSStorage.cpp [new file with mode: 0755]
src/Filesystem/JSStorage.h [new file with mode: 0644]
src/Filesystem/Manager.cpp [new file with mode: 0755]
src/Filesystem/Manager.h [new file with mode: 0755]
src/Filesystem/Node.cpp [new file with mode: 0755]
src/Filesystem/Node.h [new file with mode: 0644]
src/Filesystem/NodeFilter.cpp [new file with mode: 0644]
src/Filesystem/NodeFilter.h [new file with mode: 0644]
src/Filesystem/NodeFilterMatcher.cpp [new file with mode: 0755]
src/Filesystem/NodeFilterMatcher.h [new file with mode: 0644]
src/Filesystem/NodeTypes.h [new file with mode: 0644]
src/Filesystem/Path.cpp [new file with mode: 0755]
src/Filesystem/Path.h [new file with mode: 0644]
src/Filesystem/StorageProperties.cpp [new file with mode: 0755]
src/Filesystem/StorageProperties.h [new file with mode: 0644]
src/Filesystem/Stream.cpp [new file with mode: 0755]
src/Filesystem/Stream.h [new file with mode: 0644]
src/Filesystem/config.xml [new file with mode: 0644]
src/Filesystem/plugin_config.cpp [new file with mode: 0644]
src/Filesystem/plugin_config.h [new file with mode: 0644]
src/Filesystem/plugin_config_impl.h [new file with mode: 0644]
src/Filesystem/plugin_initializer.cpp [new file with mode: 0644]
src/HumanActivityMonitor/CMakeLists.txt [new file with mode: 0755]
src/HumanActivityMonitor/ContextTypes.h [new file with mode: 0755]
src/HumanActivityMonitor/JSMotionManager.cpp [new file with mode: 0755]
src/HumanActivityMonitor/JSMotionManager.h [new file with mode: 0755]
src/HumanActivityMonitor/JSPedometerInfo.cpp [new file with mode: 0755]
src/HumanActivityMonitor/JSPedometerInfo.h [new file with mode: 0755]
src/HumanActivityMonitor/MotionManager.cpp [new file with mode: 0755]
src/HumanActivityMonitor/MotionManager.h [new file with mode: 0755]
src/HumanActivityMonitor/PedometerInfo.cpp [new file with mode: 0755]
src/HumanActivityMonitor/PedometerInfo.h [new file with mode: 0755]
src/HumanActivityMonitor/config.xml [new file with mode: 0755]
src/HumanActivityMonitor/plugin_config.cpp [new file with mode: 0755]
src/HumanActivityMonitor/plugin_config.h [new file with mode: 0755]
src/HumanActivityMonitor/plugin_initializer.cpp [new file with mode: 0755]
src/Mediakey/CMakeLists.txt [new file with mode: 0644]
src/Mediakey/JSMediaKeyManager.cpp [new file with mode: 0644]
src/Mediakey/JSMediaKeyManager.h [new file with mode: 0644]
src/Mediakey/MediaKeyEventCallback.cpp [new file with mode: 0644]
src/Mediakey/MediaKeyEventCallback.h [new file with mode: 0644]
src/Mediakey/MediaKeyManager.cpp [new file with mode: 0644]
src/Mediakey/MediaKeyManager.h [new file with mode: 0644]
src/Mediakey/MediaKeyUtil.cpp [new file with mode: 0644]
src/Mediakey/MediaKeyUtil.h [new file with mode: 0644]
src/Mediakey/config.xml [new file with mode: 0644]
src/Mediakey/plugin_config.cpp [new file with mode: 0644]
src/Mediakey/plugin_config.h [new file with mode: 0644]
src/Mediakey/plugin_initializer.cpp [new file with mode: 0644]
src/MessagePort/CMakeLists.txt [new file with mode: 0644]
src/MessagePort/EventLocalMessagePortAddMessagePortListener.h [new file with mode: 0644]
src/MessagePort/EventLocalMessagePortListener.h [new file with mode: 0644]
src/MessagePort/EventLocalMessagePortRemoveMessagePortListener.h [new file with mode: 0644]
src/MessagePort/EventMessagePortManagerRequestLocalMessagePort.h [new file with mode: 0644]
src/MessagePort/EventMessagePortManagerRequestRemoteMessagePort.h [new file with mode: 0644]
src/MessagePort/EventMessagePortManagerRequestTrustedLocalMessagePort.h [new file with mode: 0644]
src/MessagePort/EventMessagePortManagerRequestTrustedRemoteMessagePort.h [new file with mode: 0644]
src/MessagePort/EventRemoteMessagePortSendMessage.h [new file with mode: 0644]
src/MessagePort/ILocalMessagePort.cpp [new file with mode: 0644]
src/MessagePort/ILocalMessagePort.h [new file with mode: 0644]
src/MessagePort/IMessagePortManager.cpp [new file with mode: 0644]
src/MessagePort/IMessagePortManager.h [new file with mode: 0644]
src/MessagePort/IRemoteMessagePort.cpp [new file with mode: 0644]
src/MessagePort/IRemoteMessagePort.h [new file with mode: 0755]
src/MessagePort/JSLocalMessagePort.cpp [new file with mode: 0755]
src/MessagePort/JSLocalMessagePort.h [new file with mode: 0755]
src/MessagePort/JSMessagePortManager.cpp [new file with mode: 0755]
src/MessagePort/JSMessagePortManager.h [new file with mode: 0755]
src/MessagePort/JSRemoteMessagePort.cpp [new file with mode: 0755]
src/MessagePort/JSRemoteMessagePort.h [new file with mode: 0755]
src/MessagePort/LocalMessagePort.cpp [new file with mode: 0755]
src/MessagePort/LocalMessagePort.h [new file with mode: 0755]
src/MessagePort/LocalMessagePortController.cpp [new file with mode: 0755]
src/MessagePort/LocalMessagePortController.h [new file with mode: 0755]
src/MessagePort/MessagePortDataItem.h [new file with mode: 0755]
src/MessagePort/MessagePortFactory.cpp [new file with mode: 0755]
src/MessagePort/MessagePortFactory.h [new file with mode: 0755]
src/MessagePort/MessagePortImpl.h [new file with mode: 0755]
src/MessagePort/MessagePortJSUtil.cpp [new file with mode: 0755]
src/MessagePort/MessagePortJSUtil.h [new file with mode: 0755]
src/MessagePort/MessagePortListenerManager.cpp [new file with mode: 0755]
src/MessagePort/MessagePortListenerManager.h [new file with mode: 0755]
src/MessagePort/MessagePortManager.cpp [new file with mode: 0755]
src/MessagePort/MessagePortManager.h [new file with mode: 0755]
src/MessagePort/MessagePortManagerProxy.cpp [new file with mode: 0755]
src/MessagePort/MessagePortManagerProxy.h [new file with mode: 0755]
src/MessagePort/MessagePortUtility.cpp [new file with mode: 0755]
src/MessagePort/MessagePortUtility.h [new file with mode: 0755]
src/MessagePort/RemoteMessagePort.cpp [new file with mode: 0755]
src/MessagePort/RemoteMessagePort.h [new file with mode: 0644]
src/MessagePort/config.xml [new file with mode: 0644]
src/MessagePort/plugin_initializer.cpp [new file with mode: 0755]
src/Messaging/BaseFilterVisitor.cpp [new file with mode: 0644]
src/Messaging/CMakeLists.txt [new file with mode: 0755]
src/Messaging/ChangeListenerContainer.cpp [new file with mode: 0644]
src/Messaging/ChangeListenerContainer.h [new file with mode: 0755]
src/Messaging/ConversationCallbackData.cpp [new file with mode: 0644]
src/Messaging/ConversationCallbackData.h [new file with mode: 0644]
src/Messaging/ConversationsChangeCallback.cpp [new file with mode: 0644]
src/Messaging/ConversationsChangeCallback.h [new file with mode: 0644]
src/Messaging/DBus/Connection.cpp [new file with mode: 0644]
src/Messaging/DBus/Connection.h [new file with mode: 0644]
src/Messaging/DBus/EmailSignalProxy.cpp [new file with mode: 0644]
src/Messaging/DBus/EmailSignalProxy.h [new file with mode: 0644]
src/Messaging/DBus/LoadAttachmentProxy.cpp [new file with mode: 0644]
src/Messaging/DBus/LoadAttachmentProxy.h [new file with mode: 0644]
src/Messaging/DBus/LoadBodyProxy.cpp [new file with mode: 0644]
src/Messaging/DBus/LoadBodyProxy.h [new file with mode: 0644]
src/Messaging/DBus/MessageProxy.cpp [new file with mode: 0644]
src/Messaging/DBus/MessageProxy.h [new file with mode: 0644]
src/Messaging/DBus/Proxy.cpp [new file with mode: 0644]
src/Messaging/DBus/Proxy.h [new file with mode: 0644]
src/Messaging/DBus/SendProxy.cpp [new file with mode: 0644]
src/Messaging/DBus/SendProxy.h [new file with mode: 0644]
src/Messaging/DBus/SyncProxy.cpp [new file with mode: 0644]
src/Messaging/DBus/SyncProxy.h [new file with mode: 0644]
src/Messaging/EmailManager.cpp [new file with mode: 0644]
src/Messaging/EmailManager.h [new file with mode: 0644]
src/Messaging/FindMsgCallbackUserData.cpp [new file with mode: 0644]
src/Messaging/FindMsgCallbackUserData.h [new file with mode: 0644]
src/Messaging/FoldersCallbackData.cpp [new file with mode: 0644]
src/Messaging/FoldersCallbackData.h [new file with mode: 0644]
src/Messaging/FoldersChangeCallback.cpp [new file with mode: 0644]
src/Messaging/FoldersChangeCallback.h [new file with mode: 0644]
src/Messaging/JSMessage.cpp [new file with mode: 0644]
src/Messaging/JSMessage.h [new file with mode: 0644]
src/Messaging/JSMessageAttachment.cpp [new file with mode: 0644]
src/Messaging/JSMessageAttachment.h [new file with mode: 0755]
src/Messaging/JSMessageBody.cpp [new file with mode: 0644]
src/Messaging/JSMessageBody.h [new file with mode: 0755]
src/Messaging/JSMessageConversation.cpp [new file with mode: 0644]
src/Messaging/JSMessageConversation.h [new file with mode: 0755]
src/Messaging/JSMessageFolder.cpp [new file with mode: 0644]
src/Messaging/JSMessageFolder.h [new file with mode: 0755]
src/Messaging/JSMessageService.cpp [new file with mode: 0644]
src/Messaging/JSMessageService.h [new file with mode: 0755]
src/Messaging/JSMessageStorage.cpp [new file with mode: 0644]
src/Messaging/JSMessageStorage.h [new file with mode: 0755]
src/Messaging/JSMessagingManager.cpp [new file with mode: 0755]
src/Messaging/JSMessagingManager.h [new file with mode: 0755]
src/Messaging/Message.cpp [new file with mode: 0644]
src/Messaging/Message.h [new file with mode: 0644]
src/Messaging/MessageAttachment.cpp [new file with mode: 0755]
src/Messaging/MessageAttachment.h [new file with mode: 0755]
src/Messaging/MessageBody.cpp [new file with mode: 0644]
src/Messaging/MessageBody.h [new file with mode: 0644]
src/Messaging/MessageCallbackUserData.cpp [new file with mode: 0644]
src/Messaging/MessageCallbackUserData.h [new file with mode: 0644]
src/Messaging/MessageConversation.cpp [new file with mode: 0644]
src/Messaging/MessageConversation.h [new file with mode: 0644]
src/Messaging/MessageEmail.cpp [new file with mode: 0644]
src/Messaging/MessageEmail.h [new file with mode: 0644]
src/Messaging/MessageFolder.cpp [new file with mode: 0644]
src/Messaging/MessageFolder.h [new file with mode: 0644]
src/Messaging/MessageMMS.cpp [new file with mode: 0644]
src/Messaging/MessageMMS.h [new file with mode: 0644]
src/Messaging/MessageSMS.cpp [new file with mode: 0644]
src/Messaging/MessageSMS.h [new file with mode: 0644]
src/Messaging/MessageService.cpp [new file with mode: 0644]
src/Messaging/MessageService.h [new file with mode: 0755]
src/Messaging/MessageServiceEmail.cpp [new file with mode: 0644]
src/Messaging/MessageServiceEmail.h [new file with mode: 0755]
src/Messaging/MessageServiceShortMsg.cpp [new file with mode: 0755]
src/Messaging/MessageServiceShortMsg.h [new file with mode: 0755]
src/Messaging/MessageStorage.cpp [new file with mode: 0644]
src/Messaging/MessageStorage.h [new file with mode: 0644]
src/Messaging/MessageStorageEmail.cpp [new file with mode: 0644]
src/Messaging/MessageStorageEmail.h [new file with mode: 0644]
src/Messaging/MessageStorageShortMsg.cpp [new file with mode: 0755]
src/Messaging/MessageStorageShortMsg.h [new file with mode: 0644]
src/Messaging/MessagesCallbackUserData.cpp [new file with mode: 0644]
src/Messaging/MessagesCallbackUserData.h [new file with mode: 0644]
src/Messaging/MessagesChangeCallback.cpp [new file with mode: 0644]
src/Messaging/MessagesChangeCallback.h [new file with mode: 0644]
src/Messaging/MessagingDatabaseManager.cpp [new file with mode: 0755]
src/Messaging/MessagingDatabaseManager.h [new file with mode: 0755]
src/Messaging/MessagingManager.cpp [new file with mode: 0755]
src/Messaging/MessagingManager.h [new file with mode: 0755]
src/Messaging/MessagingUtil.cpp [new file with mode: 0644]
src/Messaging/MessagingUtil.h [new file with mode: 0644]
src/Messaging/ShortMsgManager.cpp [new file with mode: 0644]
src/Messaging/ShortMsgManager.h [new file with mode: 0755]
src/Messaging/TestScripts/addConversationsChangeListener_01.js [new file with mode: 0644]
src/Messaging/TestScripts/addFoldersChangeListener_01.js [new file with mode: 0644]
src/Messaging/TestScripts/addMessagesChangeListener_01.js [new file with mode: 0644]
src/Messaging/TestScripts/allChangeListeners_01.js [new file with mode: 0644]
src/Messaging/TestScripts/loadMessageAttachment_01.js [new file with mode: 0644]
src/Messaging/TestScripts/loadMessageBody_01.js [new file with mode: 0644]
src/Messaging/config.xml [new file with mode: 0755]
src/Messaging/plugin_config.cpp [new file with mode: 0755]
src/Messaging/plugin_config.h [new file with mode: 0755]
src/Messaging/plugin_config_impl.h [new file with mode: 0755]
src/Messaging/plugin_initializer.cpp [new file with mode: 0644]
src/NFC/CMakeLists.txt [new file with mode: 0755]
src/NFC/JSNFCAdapter.cpp [new file with mode: 0755]
src/NFC/JSNFCAdapter.h [new file with mode: 0755]
src/NFC/JSNFCManager.cpp [new file with mode: 0755]
src/NFC/JSNFCManager.h [new file with mode: 0755]
src/NFC/JSNFCPeer.cpp [new file with mode: 0755]
src/NFC/JSNFCPeer.h [new file with mode: 0755]
src/NFC/JSNFCTag.cpp [new file with mode: 0755]
src/NFC/JSNFCTag.h [new file with mode: 0755]
src/NFC/JSNdefMessage.cpp [new file with mode: 0755]
src/NFC/JSNdefMessage.h [new file with mode: 0755]
src/NFC/JSNdefRecord.cpp [new file with mode: 0755]
src/NFC/JSNdefRecord.h [new file with mode: 0755]
src/NFC/JSNdefRecordMedia.cpp [new file with mode: 0755]
src/NFC/JSNdefRecordMedia.h [new file with mode: 0755]
src/NFC/JSNdefRecordText.cpp [new file with mode: 0755]
src/NFC/JSNdefRecordText.h [new file with mode: 0755]
src/NFC/JSNdefRecordURI.cpp [new file with mode: 0755]
src/NFC/JSNdefRecordURI.h [new file with mode: 0755]
src/NFC/JSNdefRecordVector.cpp [new file with mode: 0644]
src/NFC/JSNdefRecordVector.h [new file with mode: 0644]
src/NFC/NFCAdapter.cpp [new file with mode: 0755]
src/NFC/NFCAdapter.h [new file with mode: 0755]
src/NFC/NFCCallbackData.cpp [new file with mode: 0644]
src/NFC/NFCCallbackData.h [new file with mode: 0644]
src/NFC/NFCManager.cpp [new file with mode: 0644]
src/NFC/NFCManager.h [new file with mode: 0644]
src/NFC/NFCPeer.cpp [new file with mode: 0644]
src/NFC/NFCPeer.h [new file with mode: 0644]
src/NFC/NFCPeerDetectCallback.cpp [new file with mode: 0644]
src/NFC/NFCPeerDetectCallback.h [new file with mode: 0644]
src/NFC/NFCTag.cpp [new file with mode: 0755]
src/NFC/NFCTag.h [new file with mode: 0755]
src/NFC/NFCTagDetectCallback.cpp [new file with mode: 0644]
src/NFC/NFCTagDetectCallback.h [new file with mode: 0644]
src/NFC/NFCUtil.cpp [new file with mode: 0644]
src/NFC/NFCUtil.h [new file with mode: 0644]
src/NFC/NdefMessage.cpp [new file with mode: 0644]
src/NFC/NdefMessage.h [new file with mode: 0644]
src/NFC/NdefRecord.cpp [new file with mode: 0644]
src/NFC/NdefRecord.h [new file with mode: 0644]
src/NFC/NdefRecordMedia.cpp [new file with mode: 0644]
src/NFC/NdefRecordMedia.h [new file with mode: 0644]
src/NFC/NdefRecordText.cpp [new file with mode: 0755]
src/NFC/NdefRecordText.h [new file with mode: 0755]
src/NFC/NdefRecordURI.cpp [new file with mode: 0644]
src/NFC/NdefRecordURI.h [new file with mode: 0644]
src/NFC/config.xml [new file with mode: 0755]
src/NFC/plugin_config.cpp [new file with mode: 0755]
src/NFC/plugin_config.h [new file with mode: 0755]
src/NFC/plugin_config_impl.h [new file with mode: 0644]
src/NFC/plugin_initializer.cpp [new file with mode: 0644]
src/NetworkBearerSelection/CMakeLists.txt [new file with mode: 0755]
src/NetworkBearerSelection/EventNetworkBearerRelease.h [new file with mode: 0755]
src/NetworkBearerSelection/EventNetworkBearerSelection.h [new file with mode: 0755]
src/NetworkBearerSelection/INetworkBearerSelection.cpp [new file with mode: 0755]
src/NetworkBearerSelection/INetworkBearerSelection.h [new file with mode: 0755]
src/NetworkBearerSelection/JSNetworkBearerSelection.cpp [new file with mode: 0755]
src/NetworkBearerSelection/JSNetworkBearerSelection.h [new file with mode: 0755]
src/NetworkBearerSelection/JSNetworkBearerSelectionCallbackManager.cpp [new file with mode: 0644]
src/NetworkBearerSelection/JSNetworkBearerSelectionCallbackManager.h [new file with mode: 0755]
src/NetworkBearerSelection/NetworkBearerSelection.cpp [new file with mode: 0755]
src/NetworkBearerSelection/NetworkBearerSelection.h [new file with mode: 0755]
src/NetworkBearerSelection/NetworkBearerSelectionFactory.cpp [new file with mode: 0755]
src/NetworkBearerSelection/NetworkBearerSelectionFactory.h [new file with mode: 0755]
src/NetworkBearerSelection/NetworkBearerSelectionResponseDispatcher.cpp [new file with mode: 0755]
src/NetworkBearerSelection/NetworkBearerSelectionResponseDispatcher.h [new file with mode: 0755]
src/NetworkBearerSelection/NetworkBearerSelectionUtil.cpp [new file with mode: 0644]
src/NetworkBearerSelection/NetworkBearerSelectionUtil.h [new file with mode: 0644]
src/NetworkBearerSelection/OnNetworkBearerSelectionStateChanged.h [new file with mode: 0755]
src/NetworkBearerSelection/config.xml [new file with mode: 0755]
src/NetworkBearerSelection/plugin_config.cpp [new file with mode: 0755]
src/NetworkBearerSelection/plugin_config.h [new file with mode: 0755]
src/NetworkBearerSelection/plugin_initializer.cpp [new file with mode: 0755]
src/Notification/CMakeLists.txt [new file with mode: 0755]
src/Notification/JSNotificationDetailInfo.cpp [new file with mode: 0755]
src/Notification/JSNotificationDetailInfo.h [new file with mode: 0755]
src/Notification/JSNotificationManager.cpp [new file with mode: 0755]
src/Notification/JSNotificationManager.h [new file with mode: 0644]
src/Notification/JSStatusNotification.cpp [new file with mode: 0755]
src/Notification/JSStatusNotification.h [new file with mode: 0755]
src/Notification/NotificationDetailInfo.cpp [new file with mode: 0755]
src/Notification/NotificationDetailInfo.h [new file with mode: 0755]
src/Notification/NotificationLine.cpp [new file with mode: 0755]
src/Notification/NotificationManager.cpp [new file with mode: 0755]
src/Notification/NotificationManager.h [new file with mode: 0755]
src/Notification/NotificationTypes.h [new file with mode: 0755]
src/Notification/NotificationUtil.cpp [new file with mode: 0644]
src/Notification/NotificationUtil.h [new file with mode: 0644]
src/Notification/StatusNotification.cpp [new file with mode: 0755]
src/Notification/StatusNotification.h [new file with mode: 0755]
src/Notification/config.xml [new file with mode: 0644]
src/Notification/plugin_config.cpp [new file with mode: 0755]
src/Notification/plugin_config.h [new file with mode: 0755]
src/Notification/plugin_initializer.cpp [new file with mode: 0644]
src/Package/CMakeLists.txt [new file with mode: 0755]
src/Package/JSPackageInformation.cpp [new file with mode: 0755]
src/Package/JSPackageInformation.h [new file with mode: 0755]
src/Package/JSPackageManager.cpp [new file with mode: 0755]
src/Package/JSPackageManager.h [new file with mode: 0755]
src/Package/PackageInformation.cpp [new file with mode: 0755]
src/Package/PackageInformation.h [new file with mode: 0644]
src/Package/PackageManager.cpp [new file with mode: 0755]
src/Package/PackageManager.h [new file with mode: 0644]
src/Package/PackageUtil.cpp [new file with mode: 0755]
src/Package/PackageUtil.h [new file with mode: 0755]
src/Package/config.xml [new file with mode: 0755]
src/Package/plugin_config.cpp [new file with mode: 0755]
src/Package/plugin_config.h [new file with mode: 0755]
src/Package/plugin_initializer.cpp [new file with mode: 0755]
src/Power/CMakeLists.txt [new file with mode: 0755]
src/Power/JSPowerManager.cpp [new file with mode: 0755]
src/Power/JSPowerManager.h [new file with mode: 0755]
src/Power/PowerManager.cpp [new file with mode: 0755]
src/Power/PowerManager.h [new file with mode: 0755]
src/Power/PowerPlatformProxy.cpp [new file with mode: 0755]
src/Power/PowerPlatformProxy.h [new file with mode: 0755]
src/Power/PowerUtil.cpp [new file with mode: 0755]
src/Power/PowerUtil.h [new file with mode: 0755]
src/Power/config.xml [new file with mode: 0755]
src/Power/plugin_config.cpp [new file with mode: 0755]
src/Power/plugin_config.h [new file with mode: 0755]
src/Power/plugin_config_impl.h [new file with mode: 0755]
src/Power/plugin_initializer.cpp [new file with mode: 0755]
src/Push/CMakeLists.txt [new file with mode: 0644]
src/Push/JSPushManager.cpp [new file with mode: 0644]
src/Push/JSPushManager.h [new file with mode: 0644]
src/Push/JSPushMessage.cpp [new file with mode: 0644]
src/Push/JSPushMessage.h [new file with mode: 0644]
src/Push/PushManager.cpp [new file with mode: 0755]
src/Push/PushManager.h [new file with mode: 0755]
src/Push/PushMessage.cpp [new file with mode: 0644]
src/Push/PushMessage.h [new file with mode: 0644]
src/Push/PushTypes.h [new file with mode: 0644]
src/Push/PushUtil.cpp [new file with mode: 0644]
src/Push/PushUtil.h [new file with mode: 0644]
src/Push/config.xml [new file with mode: 0644]
src/Push/plugin_config.cpp [new file with mode: 0644]
src/Push/plugin_config.h [new file with mode: 0644]
src/Push/plugin_config_impl.h [new file with mode: 0644]
src/Push/plugin_initializer.cpp [new file with mode: 0755]
src/RefImpl/CMakeLists.txt [new file with mode: 0755]
src/RefImpl/JSNestedValue.cpp [new file with mode: 0755]
src/RefImpl/JSNestedValue.h [new file with mode: 0755]
src/RefImpl/JSRefImplManager.cpp [new file with mode: 0755]
src/RefImpl/JSRefImplManager.h [new file with mode: 0644]
src/RefImpl/JSSub.cpp [new file with mode: 0755]
src/RefImpl/JSSub.h [new file with mode: 0755]
src/RefImpl/JSSuper.cpp [new file with mode: 0755]
src/RefImpl/JSSuper.h [new file with mode: 0755]
src/RefImpl/NestedValue.cpp [new file with mode: 0755]
src/RefImpl/NestedValue.h [new file with mode: 0755]
src/RefImpl/RefImplManager.cpp [new file with mode: 0755]
src/RefImpl/RefImplManager.h [new file with mode: 0755]
src/RefImpl/Sub.cpp [new file with mode: 0755]
src/RefImpl/Sub.h [new file with mode: 0755]
src/RefImpl/Super.cpp [new file with mode: 0755]
src/RefImpl/Super.h [new file with mode: 0755]
src/RefImpl/config.xml [new file with mode: 0755]
src/RefImpl/mock.cpp [new file with mode: 0755]
src/RefImpl/mock.h [new file with mode: 0755]
src/RefImpl/plugin_initializer.cpp [new file with mode: 0644]
src/RefImpl/test/CMakeLists.txt [new file with mode: 0755]
src/RefImpl/test/main.cpp [new file with mode: 0755]
src/RefImpl/test/test.js [new file with mode: 0755]
src/SecureElement/CMakeLists.txt [new file with mode: 0755]
src/SecureElement/JSChannel.cpp [new file with mode: 0755]
src/SecureElement/JSChannel.h [new file with mode: 0755]
src/SecureElement/JSReader.cpp [new file with mode: 0755]
src/SecureElement/JSReader.h [new file with mode: 0755]
src/SecureElement/JSSEService.cpp [new file with mode: 0755]
src/SecureElement/JSSEService.h [new file with mode: 0755]
src/SecureElement/JSSession.cpp [new file with mode: 0755]
src/SecureElement/JSSession.h [new file with mode: 0755]
src/SecureElement/SECallbackData.cpp [new file with mode: 0644]
src/SecureElement/SECallbackData.h [new file with mode: 0644]
src/SecureElement/SEChangeListener.cpp [new file with mode: 0644]
src/SecureElement/SEChangeListener.h [new file with mode: 0644]
src/SecureElement/SEChannel.cpp [new file with mode: 0755]
src/SecureElement/SEChannel.h [new file with mode: 0755]
src/SecureElement/SEReader.cpp [new file with mode: 0644]
src/SecureElement/SEReader.h [new file with mode: 0644]
src/SecureElement/SEService.cpp [new file with mode: 0644]
src/SecureElement/SEService.h [new file with mode: 0644]
src/SecureElement/SEUtils.cpp [new file with mode: 0644]
src/SecureElement/SEUtils.h [new file with mode: 0644]
src/SecureElement/Session.cpp [new file with mode: 0755]
src/SecureElement/Session.h [new file with mode: 0755]
src/SecureElement/config.xml [new file with mode: 0755]
src/SecureElement/plugin_config.cpp [new file with mode: 0755]
src/SecureElement/plugin_config.h [new file with mode: 0755]
src/SecureElement/plugin_config_impl.h [new file with mode: 0644]
src/SecureElement/plugin_initializer.cpp [new file with mode: 0644]
src/Sensor/CMakeLists.txt [new file with mode: 0755]
src/Sensor/JSSensorData.cpp [new file with mode: 0755]
src/Sensor/JSSensorData.h [new file with mode: 0755]
src/Sensor/JSSensorService.cpp [new file with mode: 0755]
src/Sensor/JSSensorService.h [new file with mode: 0755]
src/Sensor/SensorData.cpp [new file with mode: 0755]
src/Sensor/SensorData.h [new file with mode: 0755]
src/Sensor/SensorService.cpp [new file with mode: 0755]
src/Sensor/SensorService.h [new file with mode: 0755]
src/Sensor/SensorUtil.cpp [new file with mode: 0755]
src/Sensor/SensorUtil.h [new file with mode: 0755]
src/Sensor/config.xml [new file with mode: 0755]
src/Sensor/plugin_config.cpp [new file with mode: 0755]
src/Sensor/plugin_config.h [new file with mode: 0755]
src/Sensor/plugin_initializer.cpp [new file with mode: 0755]
src/Sound/CMakeLists.txt [new file with mode: 0755]
src/Sound/JSSoundManager.cpp [new file with mode: 0755]
src/Sound/JSSoundManager.h [new file with mode: 0755]
src/Sound/SoundManager.cpp [new file with mode: 0755]
src/Sound/SoundManager.h [new file with mode: 0755]
src/Sound/SoundTypes.h [new file with mode: 0755]
src/Sound/SoundUtil.cpp [new file with mode: 0755]
src/Sound/SoundUtil.h [new file with mode: 0755]
src/Sound/VolumeChangeCallback.cpp [new file with mode: 0644]
src/Sound/VolumeChangeCallback.h [new file with mode: 0755]
src/Sound/config.xml [new file with mode: 0644]
src/Sound/plugin_config.cpp [new file with mode: 0755]
src/Sound/plugin_config.h [new file with mode: 0755]
src/Sound/plugin_initializer.cpp [new file with mode: 0755]
src/SystemSetting/CMakeLists.txt [new file with mode: 0755]
src/SystemSetting/ConverterSystemSetting.cpp [new file with mode: 0755]
src/SystemSetting/ConverterSystemSetting.h [new file with mode: 0755]
src/SystemSetting/EventGetSetting.h [new file with mode: 0755]
src/SystemSetting/EventSetRingtone.h [new file with mode: 0755]
src/SystemSetting/EventSetSetting.h [new file with mode: 0755]
src/SystemSetting/EventSetWallpaper.h [new file with mode: 0755]
src/SystemSetting/ISystemSetting.cpp [new file with mode: 0755]
src/SystemSetting/ISystemSetting.h [new file with mode: 0755]
src/SystemSetting/ISystemSettingType.h [new file with mode: 0755]
src/SystemSetting/JSSystemSetting.cpp [new file with mode: 0755]
src/SystemSetting/JSSystemSetting.h [new file with mode: 0755]
src/SystemSetting/SystemSetting.cpp [new file with mode: 0755]
src/SystemSetting/SystemSetting.h [new file with mode: 0755]
src/SystemSetting/SystemSettingAsyncCallbackManager.cpp [new file with mode: 0755]
src/SystemSetting/SystemSettingAsyncCallbackManager.h [new file with mode: 0755]
src/SystemSetting/SystemSettingFactory.cpp [new file with mode: 0755]
src/SystemSetting/SystemSettingFactory.h [new file with mode: 0755]
src/SystemSetting/SystemSettingResponseDispatcher.cpp [new file with mode: 0755]
src/SystemSetting/SystemSettingResponseDispatcher.h [new file with mode: 0755]
src/SystemSetting/config.xml [new file with mode: 0755]
src/SystemSetting/plugin_config.cpp [new file with mode: 0755]
src/SystemSetting/plugin_config.h [new file with mode: 0755]
src/SystemSetting/plugin_config_impl.h [new file with mode: 0755]
src/SystemSetting/plugin_initializer.cpp [new file with mode: 0755]
src/Systeminfo/CMakeLists.txt [new file with mode: 0755]
src/Systeminfo/JSSystemInfo.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfo.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoBattery.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoBattery.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoBuild.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoBuild.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoCellularNetwork.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoCellularNetwork.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoCpu.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoCpu.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoDeviceCapability.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoDeviceCapability.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoDeviceOrientation.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoDeviceOrientation.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoDisplay.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoDisplay.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoLocale.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoLocale.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoMemory.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoMemory.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoNetwork.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoNetwork.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoPeripheral.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoPeripheral.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoProperty.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoProperty.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoSIM.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoSIM.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoStorage.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoStorage.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoStorageUnit.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoStorageUnit.h [new file with mode: 0755]
src/Systeminfo/JSSystemInfoWifiNetwork.cpp [new file with mode: 0755]
src/Systeminfo/JSSystemInfoWifiNetwork.h [new file with mode: 0755]
src/Systeminfo/SystemInfo.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfo.h [new file with mode: 0755]
src/Systeminfo/SystemInfoBattery.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoBattery.h [new file with mode: 0755]
src/Systeminfo/SystemInfoBuild.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoBuild.h [new file with mode: 0755]
src/Systeminfo/SystemInfoCellularNetwork.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoCellularNetwork.h [new file with mode: 0755]
src/Systeminfo/SystemInfoCpu.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoCpu.h [new file with mode: 0755]
src/Systeminfo/SystemInfoDeviceCapability.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoDeviceCapability.h [new file with mode: 0755]
src/Systeminfo/SystemInfoDeviceOrientation.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoDeviceOrientation.h [new file with mode: 0755]
src/Systeminfo/SystemInfoDisplay.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoDisplay.h [new file with mode: 0755]
src/Systeminfo/SystemInfoLocale.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoLocale.h [new file with mode: 0755]
src/Systeminfo/SystemInfoMemory.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoMemory.h [new file with mode: 0755]
src/Systeminfo/SystemInfoNetwork.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoNetwork.h [new file with mode: 0755]
src/Systeminfo/SystemInfoPeripheral.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoPeripheral.h [new file with mode: 0755]
src/Systeminfo/SystemInfoProperty.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoProperty.h [new file with mode: 0755]
src/Systeminfo/SystemInfoPropertySuccessCallbackData.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoPropertySuccessCallbackData.h [new file with mode: 0755]
src/Systeminfo/SystemInfoSIM.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoSIM.h [new file with mode: 0755]
src/Systeminfo/SystemInfoStorage.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoStorage.h [new file with mode: 0755]
src/Systeminfo/SystemInfoStorageUnit.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoStorageUnit.h [new file with mode: 0755]
src/Systeminfo/SystemInfoUtil.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoUtil.h [new file with mode: 0755]
src/Systeminfo/SystemInfoWifiNetwork.cpp [new file with mode: 0755]
src/Systeminfo/SystemInfoWifiNetwork.h [new file with mode: 0755]
src/Systeminfo/SysteminfoDeviceCapabilityKeys.h [new file with mode: 0755]
src/Systeminfo/config.xml [new file with mode: 0755]
src/Systeminfo/plugin_config.cpp [new file with mode: 0755]
src/Systeminfo/plugin_config.h [new file with mode: 0755]
src/Systeminfo/plugin_config_impl.h [new file with mode: 0755]
src/Systeminfo/plugin_initializer.cpp [new file with mode: 0755]
src/TimeUtil/CMakeLists.txt [new file with mode: 0755]
src/TimeUtil/DurationProperties.h [new file with mode: 0755]
src/TimeUtil/JSTZDate.cpp [new file with mode: 0755]
src/TimeUtil/JSTZDate.h [new file with mode: 0755]
src/TimeUtil/JSTimeDuration.cpp [new file with mode: 0755]
src/TimeUtil/JSTimeDuration.h [new file with mode: 0755]
src/TimeUtil/JSTimeUtil.cpp [new file with mode: 0755]
src/TimeUtil/JSTimeUtil.h [new file with mode: 0755]
src/TimeUtil/TZDate.cpp [new file with mode: 0755]
src/TimeUtil/TZDate.h [new file with mode: 0755]
src/TimeUtil/TZDateProperties.h [new file with mode: 0755]
src/TimeUtil/TimeDuration.cpp [new file with mode: 0755]
src/TimeUtil/TimeDuration.h [new file with mode: 0755]
src/TimeUtil/TimeUtil.cpp [new file with mode: 0755]
src/TimeUtil/TimeUtil.h [new file with mode: 0755]
src/TimeUtil/TimeUtilConverter.cpp [new file with mode: 0755]
src/TimeUtil/TimeUtilConverter.h [new file with mode: 0755]
src/TimeUtil/TimeUtilTools.cpp [new file with mode: 0755]
src/TimeUtil/TimeUtilTools.h [new file with mode: 0755]
src/TimeUtil/config.xml [new file with mode: 0755]
src/TimeUtil/plugin_config_impl.h [new file with mode: 0755]
src/TimeUtil/plugin_initializer.cpp [new file with mode: 0755]
src/Tizen/AbstractFilter.cpp [new file with mode: 0644]
src/Tizen/AbstractFilter.h [new file with mode: 0644]
src/Tizen/Any.cpp [new file with mode: 0644]
src/Tizen/Any.h [new file with mode: 0644]
src/Tizen/AttributeFilter.cpp [new file with mode: 0644]
src/Tizen/AttributeFilter.h [new file with mode: 0644]
src/Tizen/AttributeRangeFilter.cpp [new file with mode: 0644]
src/Tizen/AttributeRangeFilter.h [new file with mode: 0644]
src/Tizen/CMakeLists.txt [new file with mode: 0644]
src/Tizen/CompositeFilter.cpp [new file with mode: 0644]
src/Tizen/CompositeFilter.h [new file with mode: 0644]
src/Tizen/FilterIterator.cpp [new file with mode: 0644]
src/Tizen/FilterIterator.h [new file with mode: 0644]
src/Tizen/JSAttributeFilter.cpp [new file with mode: 0644]
src/Tizen/JSAttributeFilter.h [new file with mode: 0644]
src/Tizen/JSAttributeRangeFilter.cpp [new file with mode: 0644]
src/Tizen/JSAttributeRangeFilter.h [new file with mode: 0644]
src/Tizen/JSCompositeFilter.cpp [new file with mode: 0644]
src/Tizen/JSCompositeFilter.h [new file with mode: 0644]
src/Tizen/JSSimpleCoordinates.cpp [new file with mode: 0644]
src/Tizen/JSSimpleCoordinates.h [new file with mode: 0644]
src/Tizen/JSSortMode.cpp [new file with mode: 0644]
src/Tizen/JSSortMode.h [new file with mode: 0644]
src/Tizen/JSTizen.cpp [new file with mode: 0644]
src/Tizen/JSTizen.h [new file with mode: 0644]
src/Tizen/PluginPriv.cpp [new file with mode: 0644]
src/Tizen/PluginPriv.h [new file with mode: 0644]
src/Tizen/SimpleCoordinates.cpp [new file with mode: 0644]
src/Tizen/SimpleCoordinates.h [new file with mode: 0644]
src/Tizen/SortMode.cpp [new file with mode: 0644]
src/Tizen/SortMode.h [new file with mode: 0644]
src/Tizen/config.xml [new file with mode: 0644]
src/Tizen/plugin_config.cpp [new file with mode: 0644]
src/Tizen/plugin_config.h [new file with mode: 0644]
src/Tizen/plugin_initializer.cpp [new file with mode: 0644]
src/WebSetting/CMakeLists.txt [new file with mode: 0755]
src/WebSetting/JSWebSettingManager.cpp [new file with mode: 0755]
src/WebSetting/JSWebSettingManager.h [new file with mode: 0755]
src/WebSetting/WebSettingManager.cpp [new file with mode: 0755]
src/WebSetting/WebSettingManager.h [new file with mode: 0755]
src/WebSetting/WebSettingTypes.h [new file with mode: 0755]
src/WebSetting/config.xml [new file with mode: 0644]
src/WebSetting/plugin_config.cpp [new file with mode: 0755]
src/WebSetting/plugin_config.h [new file with mode: 0755]
src/WebSetting/plugin_initializer.cpp [new file with mode: 0755]
wrt-plugins-tizen.manifest [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..d60cb8f
--- /dev/null
@@ -0,0 +1,18 @@
+.cproject
+.project
+.settings
+.gbs.conf
+*.wgt
+*.swp
+*.tpk
+*.exe
+CMakeCache.txt
+CMakeFiles
+Makefile
+cmake_install.cmake
+install_manifest.txt
+*.list
+*.so
+pkgconfigs/*.pc
+src/Power/test/wrt-plugins-tizen-power_test
+*~
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..cacd245
--- /dev/null
@@ -0,0 +1,399 @@
+CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
+PROJECT(wrt-plugins-tizen)
+
+# -----------------------------------------------------------------------------
+# Required platform modules
+# -----------------------------------------------------------------------------
+INCLUDE(FindPkgConfig)
+
+PKG_CHECK_MODULES(webkit2 REQUIRED ewebkit2)
+PKG_CHECK_MODULES(dpl REQUIRED dpl-efl)
+PKG_CHECK_MODULES(dpl-event REQUIRED dpl-event-efl)
+PKG_CHECK_MODULES(wrt-plugins-types REQUIRED wrt-plugins-types)
+PKG_CHECK_MODULES(wrt-deviceapis-commons REQUIRED wrt-plugins-commons)
+PKG_CHECK_MODULES(wrt-deviceapis-commons-javascript REQUIRED wrt-plugins-commons-javascript)
+PKG_CHECK_MODULES(wrt-plugins-widgetdb REQUIRED wrt-plugins-widgetdb)
+
+INCLUDE_DIRECTORIES(
+  ${webkit2_INCLUDE_DIRS}
+  ${dpl_INCLUDE_DIRS}
+  ${wrt-plugins-types_INCLUDE_DIRS}
+  ${wrt-deviceapis-commons_INCLUDE_DIRS}
+  ${wrt-deviceapis-commons-javascript_INCLUDE_DIRS}
+)
+
+# -----------------------------------------------------------------------------
+# Determine the log option
+# -----------------------------------------------------------------------------
+
+OPTION(DPL_LOG "DPL logs status" OFF)
+
+IF(DPL_LOG)
+    MESSAGE(STATUS "Logging enabled for DPL")
+    ADD_DEFINITIONS("-DDPL_LOGS_ENABLED")
+ELSE(DPL_LOG)
+    MESSAGE(STATUS "Logging disabled for DPL")
+ENDIF(DPL_LOG)
+
+# -----------------------------------------------------------------------------
+# Determine the time tracing option
+# -----------------------------------------------------------------------------
+
+OPTION(ENABLE_TIME_TRACER "TIME TRACING" OFF)
+
+IF(ENABLE_TIME_TRACER)
+    MESSAGE(STATUS "Time tracer enabled")
+    ADD_DEFINITIONS("-DENABLE_TIME_TRACER")
+ELSE(ENABLE_TIME_TRACER)
+    MESSAGE(STATUS "Time tracer disabled")
+ENDIF(ENABLE_TIME_TRACER)
+
+# -----------------------------------------------------------------------------
+# Determine ACE Access Check option
+# -----------------------------------------------------------------------------
+
+OPTION(DISABLE_ACE_ACCESS_CHECK "ACE ACCESS CHECK" OFF)
+
+IF(DISABLE_ACE_ACCESS_CHECK)
+    MESSAGE(STATUS "ACE Access checks - disabled")
+    ADD_DEFINITIONS("-DDISABLE_ACE_ACCESS_CHECK")
+ELSE(DISABLE_ACE_ACCESS_CHECK)
+    MESSAGE(STATUS "ACE Access checks - enabled")
+ENDIF(DISABLE_ACE_ACCESS_CHECK)
+
+# -----------------------------------------------------------------------------
+# Set build type (Release by default)
+# -----------------------------------------------------------------------------
+IF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+     SET(CMAKE_BUILD_TYPE Release)
+ENDIF("${CMAKE_BUILD_TYPE}" STREQUAL "")
+
+MESSAGE("Build type: ${CMAKE_BUILD_TYPE}")
+
+IF(ENABLE_TIZEN_MOBILE_PROFILE)
+    MESSAGE(STATUS "For Tizen Mobile Profile")
+    ADD_DEFINITIONS( -DPROFILE_MOBILE )
+ENDIF(ENABLE_TIZEN_MOBILE_PROFILE)
+
+IF(ENABLE_TIZEN_WEARABLE_PROFILE)
+    MESSAGE(STATUS "For Tizen Wearable Profile")
+    ADD_DEFINITIONS( -DPROFILE_WEARABLE )
+ENDIF(ENABLE_TIZEN_WEARABLE_PROFILE)
+
+IF(ENABLE_TIZEN_TV_PROFILE)
+    MESSAGE(STATUS "For Tizen TV Profile")
+    ADD_DEFINITIONS( -DPROFILE_TV )
+ENDIF(ENABLE_TIZEN_TV_PROFILE)
+
+IF(ENABLE_OPTIONAL_CORE_API)
+    MESSAGE(STATUS "Tizen Core API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_CORE_API )
+ENDIF(ENABLE_OPTIONAL_CORE_API)
+
+IF(ENABLE_TIZEN_APP_CONTROL_SETTING_SUPPORT)
+    MESSAGE(STATUS "Tizen AppControl Setting Support Enabled")
+    ADD_DEFINITIONS( -DAPP_CONTROL_SETTING_SUPPORT )
+ENDIF(ENABLE_TIZEN_APP_CONTROL_SETTING_SUPPORT)
+
+# -----------------------------------------------------------------------------
+# Determine the feature configuration for optional API
+# -----------------------------------------------------------------------------
+
+IF(ENABLE_OPTIONAL_ACCOUNT)
+    MESSAGE(STATUS " Account API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_ACCOUNT )
+ENDIF(ENABLE_OPTIONAL_ACCOUNT)
+
+IF(ENABLE_OPTIONAL_ARCHIVE)
+    MESSAGE(STATUS " Archive API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_ARCHIVE )
+ENDIF(ENABLE_OPTIONAL_ARCHIVE)
+
+IF(ENABLE_OPTIONAL_BADGE)
+    MESSAGE(STATUS " Badge API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_BADGE )
+ENDIF(ENABLE_OPTIONAL_BADGE)
+
+IF(ENABLE_OPTIONAL_MEDIAKEY)
+    MESSAGE(STATUS " MediaKey API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_MEIDAKEY )
+ENDIF(ENABLE_OPTIONAL_MEDIAKEY)
+
+IF(ENABLE_OPTIONAL_BT)
+    MESSAGE(STATUS "Bluetooth API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_BT )
+ENDIF(ENABLE_OPTIONAL_BT)
+
+IF(ENABLE_OPTIONAL_BT_HEALTH)
+    MESSAGE(STATUS " BT Health API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_BT_HEALTH )
+ENDIF(ENABLE_OPTIONAL_BT_HEALTH)
+
+IF(ENABLE_OPTIONAL_BT_ALWAYS_ON)
+    MESSAGE(STATUS "Bluetooth Always ON")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_BT_ALWAYS_ON )
+ENDIF(ENABLE_OPTIONAL_BT_ALWAYS_ON)
+
+IF(ENABLE_OPTIONAL_LOCATION_BATCH)
+    MESSAGE(STATUS " location batch Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_LOCATION_BATCH )
+ENDIF(ENABLE_OPTIONAL_LOCATION_BATCH)
+
+IF(ENABLE_OPTIONAL_BOOKMARK)
+    MESSAGE(STATUS " API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_BOOKMARK )
+ENDIF(ENABLE_OPTIONAL_BOOKMARK)
+
+IF(ENABLE_OPTIONAL_CALENDAR)
+    MESSAGE(STATUS " Calendar API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_CALENDAR )
+ENDIF(ENABLE_OPTIONAL_CALENDAR)
+
+IF(ENABLE_OPTIONAL_CALL_HISTORY)
+    MESSAGE(STATUS "Callhistory API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_CALL_HISTORY )
+ENDIF(ENABLE_OPTIONAL_CALL_HISTORY)
+
+IF(ENABLE_OPTIONAL_CONTACT)
+    MESSAGE(STATUS " Contact API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_CONTACT )
+ENDIF(ENABLE_OPTIONAL_CONTACT)
+
+IF(ENABLE_OPTIONAL_CONTENT)
+    MESSAGE(STATUS " Content API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_CONTENT )
+ENDIF(ENABLE_OPTIONAL_CONTENT)
+
+IF(ENABLE_OPTIONAL_DATA_CONTROL)
+    MESSAGE(STATUS " DataControl API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_DATACONTROL )
+ENDIF(ENABLE_OPTIONAL_DATA_CONTROL)
+
+IF(ENABLE_OPTIONAL_DATA_SYNC)
+    MESSAGE(STATUS " Datasync API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_DATASYNC )
+ENDIF(ENABLE_OPTIONAL_DATA_SYNC)
+
+IF(ENABLE_OPTIONAL_DOWNLOAD)
+    MESSAGE(STATUS " Download API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_DOWNLOAD )
+ENDIF(ENABLE_OPTIONAL_DOWNLOAD)
+
+IF(ENABLE_OPTIONAL_EXIF)
+    MESSAGE(STATUS " Exif API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_EXIF )
+ENDIF(ENABLE_OPTIONAL_EXIF)
+
+IF(ENABLE_OPTIONAL_FM_RADIO)
+    MESSAGE(STATUS " FM Radio API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_FM_RADIO )
+ENDIF(ENABLE_OPTIONAL_FM_RADIO)
+
+IF(ENABLE_OPTIONAL_HAM)
+    MESSAGE(STATUS " HumanActivityMonitor API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_HAM )
+ENDIF(ENABLE_OPTIONAL_HAM)
+
+IF(ENABLE_OPTIONAL_MESSAGING)
+    MESSAGE(STATUS " Messaging API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_MESSAGING )
+ENDIF(ENABLE_OPTIONAL_MESSAGING)
+
+IF(ENABLE_OPTIONAL_MESSAGING_EMAIL)
+    MESSAGE(STATUS " Messaging email API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_MESSAGING_EMAIL )
+ENDIF(ENABLE_OPTIONAL_MESSAGING_EMAIL)
+
+IF(ENABLE_OPTIONAL_NBS)
+    MESSAGE(STATUS "Network Bearer Selection API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_NBS )
+ENDIF(ENABLE_OPTIONAL_NBS)
+
+IF(ENABLE_OPTIONAL_NFC)
+    MESSAGE(STATUS "NFC API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_NFC )
+ENDIF(ENABLE_OPTIONAL_NFC)
+
+IF(ENABLE_OPTIONAL_NFC_EMULATION)
+    MESSAGE(STATUS " NFC Emulation API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_NFC_EMULATION )
+ENDIF(ENABLE_OPTIONAL_NFC_EMULATION)
+
+IF(ENABLE_OPTIONAL_NOTIFICATION)
+    MESSAGE(STATUS " Notification API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_NOTIFICATION )
+ENDIF(ENABLE_OPTIONAL_NOTIFICATION)
+
+IF(ENABLE_OPTIONAL_POWER)
+    MESSAGE(STATUS " Power API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_POWER )
+ENDIF(ENABLE_OPTIONAL_POWER)
+
+IF(ENABLE_OPTIONAL_PUSH)
+    MESSAGE(STATUS "Push API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_PUSH )
+ENDIF(ENABLE_OPTIONAL_PUSH)
+
+IF(ENABLE_OPTIONAL_SE)
+    MESSAGE(STATUS "Secure Element API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_SE )
+ENDIF(ENABLE_OPTIONAL_SE)
+
+IF(ENABLE_OPTIONAL_SENSOR)
+    MESSAGE(STATUS " Sensor API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_SENSOR )
+ENDIF(ENABLE_OPTIONAL_SENSOR)
+
+IF(ENABLE_OPTIONAL_SOUND)
+    MESSAGE(STATUS " Sound Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_SOUND )
+ENDIF(ENABLE_OPTIONAL_SOUND)
+
+IF(ENABLE_OPTIONAL_SYSTEM_SETTING)
+    MESSAGE(STATUS " System setting API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_SYSTEM_SETTING )
+ENDIF(ENABLE_OPTIONAL_SYSTEM_SETTING)
+
+IF(ENABLE_OPTIONAL_SYSTEM_SETTING_HOME_SCREEN)
+    MESSAGE(STATUS " System setting API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_SYSTEM_SETTING_HOME_SCREEN )
+ENDIF(ENABLE_OPTIONAL_SYSTEM_SETTING_HOME_SCREEN)
+
+IF(ENABLE_OPTIONAL_SYSTEM_SETTING_LOCK_SCREEN)
+    MESSAGE(STATUS " System setting API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_SYSTEM_SETTING_LOCK_SCREEN )
+ENDIF(ENABLE_OPTIONAL_SYSTEM_SETTING_LOCK_SCREEN)
+
+IF(ENABLE_OPTIONAL_SYSTEM_SETTING_INCOMING_CALL)
+    MESSAGE(STATUS " System setting API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_SYSTEM_SETTING_INCOMING_CALL )
+ENDIF(ENABLE_OPTIONAL_SYSTEM_SETTING_INCOMING_CALL)
+
+IF(ENABLE_OPTIONAL_SYSTEM_SETTING_EMAIL_SCREEN)
+    MESSAGE(STATUS " System setting API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_SYSTEM_SETTING_EMAIL_SCREEN )
+ENDIF(ENABLE_OPTIONAL_SYSTEM_SETTING_EMAIL_SCREEN)
+
+IF(ENABLE_OPTIONAL_TELEPHONY)
+    MESSAGE(STATUS " Telephony related API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_TELEPHONY )
+ENDIF(ENABLE_OPTIONAL_TELEPHONY)
+
+IF(ENABLE_OPTIONAL_WEB_SETTING)
+    MESSAGE(STATUS " Web setting API Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_WEB_SETTING )
+ENDIF(ENABLE_OPTIONAL_WEB_SETTING)
+
+IF(ENABLE_OPTIONAL_WI_FI)
+    MESSAGE(STATUS " Wi-Fi Enabled")
+    ADD_DEFINITIONS( -DFEATURE_OPTIONAL_WI_FI )
+ENDIF(ENABLE_OPTIONAL_WI_FI)
+
+IF(ENABLE_IMPL_BACKWARD_COMPATIBLE)
+    MESSAGE(STATUS " Implementation backward compatibility supported.")
+    ADD_DEFINITIONS( -DIMPL_BACKWARD_COMPATIBLE )
+ENDIF(ENABLE_IMPL_BACKWARD_COMPATIBLE)
+
+# -----------------------------------------------------------------------------
+# CFlags
+# -----------------------------------------------------------------------------
+SET(OPTIMIZATION_FLAGS         "-falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -ftree-vect-loop-version ")
+SET(GC_SECTIONS_FLAGS          "-fdata-sections -ffunction-sections -Wl,--gc-sections")
+SET(CMAKE_C_FLAGS_PROFILING    "-O0 -g -pg")
+SET(CMAKE_CXX_FLAGS_PROFILING  "-O0 -std=c++0x -g -pg")
+SET(CMAKE_C_FLAGS_DEBUG        "-O0 -g")
+SET(CMAKE_CXX_FLAGS_DEBUG      "-O0 -std=c++0x -g")
+SET(CMAKE_C_FLAGS_RELEASE      "-Os -g ${OPTIMIZATION_FLAGS} ${GC_SECTIONS_FLAGS}")
+SET(CMAKE_CXX_FLAGS_RELEASE    "-Os -std=c++0x -g ${OPTIMIZATION_FLAGS} ${GC_SECTIONS_FLAGS}")
+ADD_DEFINITIONS("-DCLIENT_IPC_THREAD")
+ADD_DEFINITIONS("-DEXPORT_API=")
+ADD_DEFINITIONS("-Wall")
+ADD_DEFINITIONS("-D_FILE_OFFSET_BITS=64")
+#ADD_DEFINITIONS("-Werror")
+#ADD_DEFINITIONS("-Wextra")
+ADD_DEFINITIONS("-DAPPLICATION_API_BACKWARD_COMPATIBILITY")
+
+# -----------------------------------------------------------------------------
+# License file
+# -----------------------------------------------------------------------------
+#SET(LICENSE_FILE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE)
+#SET(LICENSE_FILE_DST_PATH /usr/share/license)
+#SET(LICENSE_FILE_DST_NAME wrt-plugins-tizen)
+
+#INSTALL(
+#  FILES ${LICENSE_FILE}
+#  DESTINATION ${LICENSE_FILE_DST_PATH}
+#  RENAME ${LICENSE_FILE_DST_NAME}
+#)
+
+# -----------------------------------------------------------------------------
+# Schema of plugin's configuration file
+# -----------------------------------------------------------------------------
+SET(COMMON_CONFIG_DTD ${CMAKE_CURRENT_SOURCE_DIR}/config.dtd)
+SET(COMMON_CONFIG_DTD_DST /usr/etc/tizen-apis)
+INSTALL(FILES ${COMMON_CONFIG_DTD} DESTINATION ${COMMON_CONFIG_DTD_DST})
+
+# -----------------------------------------------------------------------------
+# Global variables
+# -----------------------------------------------------------------------------
+
+SET(DESTINATION_LIB_PREFIX lib/wrt-plugins)
+
+SET(DESTINATION_HEADER_PREFIX include/${PROJECT_NAME})
+
+SET(TOP ${CMAKE_SOURCE_DIR}/src)
+
+SET(INCLUDE_COMMON ${TOP}/Common ${TOP}/Common/TimeTracer)
+
+SET(LIBS_COMMON
+    ${dpl_LDFLAGS}
+    ${dpl-event_LDFLAGS}
+    ${webkit2_LDFLAGS}
+    ${wrt-deviceapis-commons_LDFLAGS}
+    ${wrt-deviceapis-commons-javascript_LDFLAGS}
+)
+
+SET(CMAKE_INSTALL_RPATH ${wrt-deviceapis-commons_LIBRARY_DIRS})
+
+SET(LIBS_WIDGETDB ${wrt-plugins-widgetdb_LIBRARIES})
+
+# -----------------------------------------------------------------------------
+# Macros for pkgconfig
+# -----------------------------------------------------------------------------
+SET(PKGCONFIG_DIR ${CMAKE_SOURCE_DIR}/pkgconfigs)
+
+MACRO(configure_and_install_pkg PKG_FILE)
+    CONFIGURE_FILE(${PKGCONFIG_DIR}/${PKG_FILE}.in
+               ${PKGCONFIG_DIR}/${PKG_FILE} @ONLY)
+    INSTALL(FILES ${PKGCONFIG_DIR}/${PKG_FILE} DESTINATION lib/pkgconfig)
+ENDMACRO(configure_and_install_pkg)
+
+# -----------------------------------------------------------------------------
+# Functions used for plugins
+# -----------------------------------------------------------------------------
+
+FUNCTION(set_target NAME)
+  STRING(TOLOWER ${NAME} LOWER_NAME)
+  SET(${LOWER_NAME}_dest tizen-${LOWER_NAME} PARENT_SCOPE)
+  SET(${LOWER_NAME}_target wrt-plugins-tizen-${LOWER_NAME} PARENT_SCOPE)
+  SET(${LOWER_NAME}_impl wrt-plugins-tizen-${LOWER_NAME}-impl PARENT_SCOPE)
+  SET(${LOWER_NAME}_config wrt-plugins-tizen-${LOWER_NAME}-config PARENT_SCOPE)
+  SET(${LOWER_NAME}_include ${TOP}/${NAME} PARENT_SCOPE)
+  configure_and_install_pkg(wrt-plugins-tizen-${LOWER_NAME}.pc)
+ENDFUNCTION()
+
+FUNCTION(add_subdir NAME)
+  MESSAGE(STATUS "Building: ${CMAKE_CURRENT_SOURCE_DIR}/${NAME}")
+  ADD_SUBDIRECTORY(${NAME})
+ENDFUNCTION()
+
+FUNCTION(add_plugin)
+  FOREACH(VALUE ${ARGN})
+    set_target(${VALUE})
+  ENDFOREACH(VALUE)
+  FOREACH(VALUE ${ARGN})
+    add_subdir(${VALUE})
+  ENDFOREACH(VALUE)
+ENDFUNCTION()
+
+ADD_SUBDIRECTORY(src)
diff --git a/Doxyfile b/Doxyfile
new file mode 100644 (file)
index 0000000..3ba4e68
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,1781 @@
+# Doxyfile 1.7.6.1
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project.
+#
+# All text after a hash (#) is considered a comment and will be ignored.
+# The format is:
+#       TAG = value [value, ...]
+# For lists items can also be appended using:
+#       TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ").
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING      = UTF-8
+
+# The PROJECT_NAME tag is a single word (or sequence of words) that should
+# identify the project. Note that if you do not use Doxywizard you need
+# to put quotes around the project name if it contains spaces.
+
+PROJECT_NAME           = "wrt-plugins-tizen"
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER         =
+
+# Using the PROJECT_BRIEF tag one can provide an optional one line description
+# for a project that appears at the top of each page and should give viewer
+# a quick idea about the purpose of the project. Keep the description short.
+
+PROJECT_BRIEF          =
+
+# With the PROJECT_LOGO tag one can specify an logo or icon that is
+# included in the documentation. The maximum height of the logo should not
+# exceed 55 pixels and the maximum width should not exceed 200 pixels.
+# Doxygen will copy the logo to the output directory.
+
+PROJECT_LOGO           =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY       = doxygen
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS         = YES
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE        = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC      = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF           = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF       =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC    = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB  = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES        = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH        =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH    =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful if your file system
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES            = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF      = NO
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF           = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS           = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES  = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE               = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES                =
+
+# This tag can be used to specify a number of word-keyword mappings (TCL only).
+# A mapping has the form "name=value". For example adding
+# "class=itcl::class" will allow you to use the command class in the
+# itcl::class meaning.
+
+TCL_SUBST              =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C  = NO
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA   = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN   = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL   = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it
+# parses. With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this
+# tag. The format is ext=language, where ext is a file extension, and language
+# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C,
+# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make
+# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C
+# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions
+# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING      =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also makes the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT    = YES
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT        = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT            = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT   = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC   = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING            = YES
+
+# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and
+# unions are shown inside the group in which they are included (e.g. using
+# @ingroup) instead of on a separate page (for HTML and Man pages) or
+# section (for LaTeX and RTF).
+
+INLINE_GROUPED_CLASSES = NO
+
+# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and
+# unions with only public data fields will be shown inline in the documentation
+# of the scope in which they are defined (i.e. file, namespace, or group
+# documentation), provided this scope is documented. If set to NO (the default),
+# structs, classes, and unions are shown on a separate page (for HTML and Man
+# pages) or section (for LaTeX and RTF).
+
+INLINE_SIMPLE_STRUCTS  = NO
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT   = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penalty.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will roughly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+SYMBOL_CACHE_SIZE      = 0
+
+# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be
+# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given
+# their name and scope. Since this can be an expensive process and often the
+# same symbol appear multiple times in the code, doxygen keeps a cache of
+# pre-resolved symbols. If the cache is too small doxygen will become slower.
+# If the cache is too large, memory is wasted. The cache size is given by this
+# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols.
+
+LOOKUP_CACHE_SIZE      = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL            = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE        = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC         = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES  = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS  = YES
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespaces are hidden.
+
+EXTRACT_ANON_NSPACES   = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS     = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES     = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS  = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS      = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS          = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES       = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES       = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES     = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES   = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO            = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS       = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS        = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
+# will sort the (brief and detailed) documentation of class members so that
+# constructors and destructors are listed first. If set to NO (the default)
+# the constructors will appear in the respective orders defined by
+# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
+# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
+# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES       = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME     = NO
+
+# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to
+# do proper type resolution of all parameters of a function it will reject a
+# match between the prototype and the implementation of a member function even
+# if there is only one candidate or it is obvious which candidate to choose
+# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen
+# will still accept a match between prototype and implementation in such cases.
+
+STRICT_PROTO_MATCHING  = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST      = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST      = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST       = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS       =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or macro consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and macros in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES  = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES        = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES       = YES
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES             = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES        = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER    =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
+# by doxygen. The layout file controls the global structure of the generated
+# output files in an output format independent way. The create the layout file
+# that represents doxygen's defaults, run doxygen with the -l option.
+# You can optionally specify a file name after the option, if omitted
+# DoxygenLayout.xml will be used as the name of the layout file.
+
+LAYOUT_FILE            =
+
+# The CITE_BIB_FILES tag can be used to specify one or more bib files
+# containing the references data. This must be a list of .bib files. The
+# .bib extension is automatically appended if omitted. Using this command
+# requires the bibtex tool to be installed. See also
+# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style
+# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this
+# feature you need bibtex and perl available in the search path.
+
+CITE_BIB_FILES         =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET                  = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS               = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED   = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR      = YES
+
+# The WARN_NO_PARAMDOC option can be enabled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC       = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT            = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE           =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT                  = src
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING         = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh
+# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py
+# *.f90 *.f *.for *.vhd *.vhdl
+
+FILE_PATTERNS          =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE              = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should be
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+# Note that relative paths are relative to the directory from which doxygen is
+# run.
+
+EXCLUDE                =
+
+# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
+# directories that are symbolic links (a Unix file system feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS       = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS       =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS        =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH           =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS       =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE      = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH             =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER           =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty or if
+# non of the patterns match the file name, INPUT_FILTER is applied.
+
+FILTER_PATTERNS        =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES    = NO
+
+# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
+# pattern. A pattern will override the setting for FILTER_PATTERN (if any)
+# and it is also possible to disable source filtering for a specific pattern
+# using *.ext= (so without naming a filter). This option only has effect when
+# FILTER_SOURCE_FILES is enabled.
+
+FILTER_SOURCE_PATTERNS =
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER         = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES         = YES
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS    = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION    = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS              = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS       = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX     = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX    = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX          =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML          = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT            = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION    = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header. Note that when using a custom header you are responsible
+#  for the proper inclusion of any scripts and style sheets that doxygen
+# needs, which is dependent on the configuration options used.
+# It is advised to generate a default header using "doxygen -w html
+# header.html footer.html stylesheet.css YourConfigFile" and then modify
+# that header. Note that the header is subject to change so you typically
+# have to redo this when upgrading to a newer version of doxygen or when
+# changing the value of configuration settings such as GENERATE_TREEVIEW!
+
+HTML_HEADER            =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER            =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# style sheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET        =
+
+# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
+# other source files which should be copied to the HTML output directory. Note
+# that these files will be copied to the base HTML output directory. Use the
+# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
+# files. In the HTML_STYLESHEET file, use the file name only. Also note that
+# the files will be copied as-is; there are no commands or markers available.
+
+HTML_EXTRA_FILES       =
+
+# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output.
+# Doxygen will adjust the colors in the style sheet and background images
+# according to this color. Hue is specified as an angle on a colorwheel,
+# see http://en.wikipedia.org/wiki/Hue for more information.
+# For instance the value 0 represents red, 60 is yellow, 120 is green,
+# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
+# The allowed range is 0 to 359.
+
+HTML_COLORSTYLE_HUE    = 220
+
+# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
+# the colors in the HTML output. For a value of 0 the output will use
+# grayscales only. A value of 255 will produce the most vivid colors.
+
+HTML_COLORSTYLE_SAT    = 100
+
+# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
+# the luminance component of the colors in the HTML output. Values below
+# 100 gradually make the output lighter, whereas values above 100 make
+# the output darker. The value divided by 100 is the actual gamma applied,
+# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
+# and 100 does not change the gamma.
+
+HTML_COLORSTYLE_GAMMA  = 80
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP         = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS     = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS  = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
+# for more information.
+
+GENERATE_DOCSET        = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME        = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID       = org.doxygen.Project
+
+# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify
+# the documentation publisher. This should be a reverse domain-name style
+# string, e.g. com.mycompany.MyDocSet.documentation.
+
+DOCSET_PUBLISHER_ID    = org.doxygen.Publisher
+
+# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher.
+
+DOCSET_PUBLISHER_NAME  = Publisher
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP      = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE               =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION           =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI           = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING     =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC             = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND             = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
+# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated
+# that can be used as input for Qt's qhelpgenerator to generate a
+# Qt Compressed Help (.qch) of the generated HTML documentation.
+
+GENERATE_QHP           = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE               =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE          = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER     = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to
+# add. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME   =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the
+# custom filter to add. For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">
+# Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS  =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
+# project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">
+# Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS  =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION           =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+#  will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
+# the help appears.
+
+GENERATE_ECLIPSEHELP   = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID         = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs)
+# at top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it. Since the tabs have the same information as the
+# navigation tree you can set this option to NO if you already set
+# GENERATE_TREEVIEW to YES.
+
+DISABLE_INDEX          = NO
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+# Since the tree basically has the same information as the tab index you
+# could consider to set DISABLE_INDEX to NO when enabling this option.
+
+GENERATE_TREEVIEW      = YES
+
+# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values
+# (range [0,1..20]) that doxygen will group on one line in the generated HTML
+# documentation. Note that a value of 0 will completely suppress the enum
+# values from appearing in the overview section.
+
+ENUM_VALUES_PER_LINE   = 4
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES       = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH         = 250
+
+# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open
+# links to external symbols imported via tag files in a separate window.
+
+EXT_LINKS_IN_WINDOW    = NO
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE       = 10
+
+# Use the FORMULA_TRANPARENT tag to determine whether or not the images
+# generated for formulas are transparent PNGs. Transparent PNGs are
+# not supported properly for IE 6.0, but are supported on all modern browsers.
+# Note that when changing this option you need to delete any form_*.png files
+# in the HTML output before the changes have effect.
+
+FORMULA_TRANSPARENT    = YES
+
+# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax
+# (see http://www.mathjax.org) which uses client side Javascript for the
+# rendering instead of using prerendered bitmaps. Use this if you do not
+# have LaTeX installed or if you want to formulas look prettier in the HTML
+# output. When enabled you also need to install MathJax separately and
+# configure the path to it using the MATHJAX_RELPATH option.
+
+USE_MATHJAX            = NO
+
+# When MathJax is enabled you need to specify the location relative to the
+# HTML output directory using the MATHJAX_RELPATH option. The destination
+# directory should contain the MathJax.js script. For instance, if the mathjax
+# directory is located at the same level as the HTML output directory, then
+# MATHJAX_RELPATH should be ../mathjax. The default value points to the
+# mathjax.org site, so you can quickly see the result without installing
+# MathJax, but it is strongly recommended to install a local copy of MathJax
+# before deployment.
+
+MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
+
+# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension
+# names that should be enabled during MathJax rendering.
+
+MATHJAX_EXTENSIONS     =
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box
+# for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using
+# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
+# (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE           = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
+# implemented using a PHP enabled web server instead of at the web client
+# using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server
+# based approach is that it scales better to large projects and allows
+# full text search. The disadvantages are that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH    = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX         = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT           = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME         = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME     = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX          = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE             = a4
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES         =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER           =
+
+# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for
+# the generated latex document. The footer should contain everything after
+# the last chapter. If it is left blank doxygen will generate a
+# standard footer. Notice: only use this tag if you know what you are doing!
+
+LATEX_FOOTER           =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS         = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX           = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE        = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES     = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include
+# source code with syntax highlighting in the LaTeX output.
+# Note that which sources are shown also depends on other settings
+# such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE      = NO
+
+# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
+# bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See
+# http://en.wikipedia.org/wiki/BibTeX for more info.
+
+LATEX_BIB_STYLE        = plain
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF           = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT             = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF            = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS         = NO
+
+# Load style sheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE    =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE    =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN           = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT             = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION          = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS              = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML           = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT             = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA             =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD                =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING     = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF   = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD       = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX          = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY         = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING   = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION        = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF     = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# pointed to by INCLUDE_PATH will be searched when a #include is found.
+
+SEARCH_INCLUDES        = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH           =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS  =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED             =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition that
+# overrules the definition found in the source code.
+
+EXPAND_AS_DEFINED      =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all references to function-like macros
+# that are alone on a line, have an all uppercase name, and do not end with a
+# semicolon, because these will confuse the parser if not removed.
+
+SKIP_FUNCTION_MACROS   = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES               =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE       =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS           = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS        = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH              = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option also works with HAVE_DOT disabled, but it is recommended to
+# install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS         = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH            =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS   = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT               = YES
+
+# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is
+# allowed to run in parallel. When set to 0 (the default) doxygen will
+# base this on the number of processors available in the system. You can set it
+# explicitly to a value larger than 0 to get control over the balance
+# between CPU load and processing speed.
+
+DOT_NUM_THREADS        = 0
+
+# By default doxygen will use the Helvetica font for all dot files that
+# doxygen generates. When you want a differently looking font you can specify
+# the font name using DOT_FONTNAME. You need to make sure dot is able to find
+# the font, which can be done by putting it in a standard location or by setting
+# the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font.
+
+DOT_FONTNAME           = Helvetica
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE           = 10
+
+# By default doxygen will tell dot to use the Helvetica font.
+# If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to
+# set the path where dot can find it.
+
+DOT_FONTPATH           =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH            = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH    = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS           = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK               = YES
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS     = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH          = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH      = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH             = YES
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH           = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will generate a graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY    = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH        = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are svg, png, jpg, or gif.
+# If left blank png will be used. If you choose svg you need to set
+# HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible in IE 9+ (other browsers do not have this requirement).
+
+DOT_IMAGE_FORMAT       = png
+
+# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
+# enable generation of interactive SVG images that allow zooming and panning.
+# Note that this requires a modern browser other than Internet Explorer.
+# Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you
+# need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files
+# visible. Older versions of IE do not have SVG support.
+
+INTERACTIVE_SVG        = YES
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH               =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS           =
+
+# The MSCFILE_DIRS tag can be used to specify one or more directories that
+# contain msc files that are included in the documentation (see the
+# \mscfile command).
+
+MSCFILE_DIRS           =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES    = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH    = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT        = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS      = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND        = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP            = YES
diff --git a/LICENSE b/LICENSE
new file mode 100755 (executable)
index 0000000..f94008a
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,206 @@
+Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+
diff --git a/clean.sh b/clean.sh
new file mode 100755 (executable)
index 0000000..06dff1f
--- /dev/null
+++ b/clean.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+echo Performing clean
+
+function clean {
+               rm -rf CMakeCache.txt
+               rm -rf CMakeFiles
+               rm -rf cmake_install.cmake
+               rm -rf Makefile
+               rm -rf install_manifest.txt                     
+               rm -rf *.so
+
+               for i in `ls`; do
+                       if [ -d $i ]; then
+                               cd $i;
+                               clean;
+                               cd ..
+                       fi
+               done    
+       }
+
+       clean
+
+
+
diff --git a/config.dtd b/config.dtd
new file mode 100644 (file)
index 0000000..f1a1de4
--- /dev/null
@@ -0,0 +1,32 @@
+<!ELEMENT plugin-properties (library-name, feature-install-uri?,
+  feature-key-cn?, feature-root-cn?,
+  feature-root-fingerprint?, feature-set*, api-feature+) >
+
+<!ELEMENT library-name (#PCDATA)>
+
+<!ELEMENT feature-set (api-feature-ref+)>
+<!ATTLIST feature-set name CDATA #REQUIRED >
+
+<!ELEMENT api-feature-ref EMPTY>
+<!ATTLIST api-feature-ref name CDATA #REQUIRED >
+
+<!ELEMENT api-feature (name, device-capability*, Object*, Function*, Property* )>
+
+<!ELEMENT name (#PCDATA) >
+<!ELEMENT device-capability (#PCDATA )>
+
+<!ELEMENT Object (Function*, Property*)>
+<!ATTLIST Object name CDATA #REQUIRED >
+
+<!ELEMENT Function (#PCDATA )>
+<!ATTLIST Function name CDATA #REQUIRED >
+<!ATTLIST Function restricted CDATA #IMPLIED >
+
+<!ELEMENT Property (#PCDATA )>
+
+
+<!ELEMENT feature-install-uri (#PCDATA)>
+<!ELEMENT feature-key-cn (#PCDATA)>
+<!ELEMENT feature-root-cn (#PCDATA)>
+<!ELEMENT feature-root-fingerprint (#PCDATA)>
+
diff --git a/packaging/wrt-plugins-tizen.spec b/packaging/wrt-plugins-tizen.spec
new file mode 100755 (executable)
index 0000000..231945f
--- /dev/null
@@ -0,0 +1,504 @@
+Name:       wrt-plugins-tizen
+Summary:    JavaScript plugins for WebRuntime
+Version:    0.6.10
+Release:    0
+Group:      Development/Libraries
+License:    Apache License, Version 2.0, Samsung Properietary
+Source0:    %{name}-%{version}.tar.gz
+
+%define    tizen_profile_mobile    1
+%define    tizen_profile_wearable    0
+%define    tizen_profile_tv    0
+
+%define    tizen_feature_core_api_support    1
+%define    tizen_feature_impl_backward_compatible_support    1
+
+%define    tizen_feature_app_control_setting_support    1
+
+# Tizen Web Device APIs
+# Account API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_account_support    1
+
+# Archive API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_archive_support    1
+
+# Badge API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_badge_support    1
+
+# Bluetooth API is optional in Tizen Mobile Profile.
+%ifarch %{arm}
+# ARM
+%define    tizen_feature_bluetooth_support    1
+%define    tizen_feature_bluetooth_health_support    1
+%define    tizen_feature_bluetooth_always_on    0
+%else
+# I586
+%define    tizen_feature_bluetooth_support    0
+%define    tizen_feature_bluetooth_health_support    0
+%define    tizen_feature_bluetooth_always_on    0
+%endif
+
+# Bookmark API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_bookmark_support    1
+
+# Calendar API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_calendar_support    1
+
+# Contact API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_contact_support    1
+
+# Content API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_content_support    1
+
+# DataControl API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_datacontrol_support    1
+
+# DataSynchronization API is optional in Tizen Mobile Profile.
+%define    tizen_feature_datasync_support    0
+
+# Download API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_download_support    1
+
+# Exif API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_exif_support    1
+
+# FM Radio API is optional in Tizen Mobile Profile.
+%ifarch %{arm}
+# ARM
+%define    tizen_feature_fm_radio_support    0
+%else
+# I586
+%define    tizen_feature_fm_radio_support    1
+%endif
+
+# HumanActivityMonitor(HAM) API is optional in Tizen Mobile Profile.
+%ifarch %{arm}
+# ARM
+%define    tizen_feature_ham_support    0
+%else
+# I586
+%define    tizen_feature_ham_support    1
+%endif
+
+# HumanActivityMonitor(HAM) - GPS type
+%define    tizen_feature_location_batch    0
+
+# MediayKey API is optional in Tizen Mobile Profile.
+# tizen.org/feature/network.bluetooth.audio.media is required for MediayKey API
+%ifarch %{arm}
+%define    tizen_feature_mediakey_support    1
+%else
+%define    tizen_feature_mediakey_support    0
+%endif
+
+# MessagePort API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_messageport_support    1
+
+# Messaging API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_messaging_support    1
+
+# Messaging(Email) API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_messaging_email_support    1
+
+# NFC API is optional in Tizen Mobile Profile.
+%ifarch %{arm}
+%define    tizen_feature_nfc_support    1
+%define    tizen_feature_nfc_emulation_support    1
+%else
+%define    tizen_feature_nfc_support    0
+%define    tizen_feature_nfc_emulation_support    0
+%endif
+
+# Notification API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_notification_support    1
+
+# Power API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_power_support    1
+
+# Push API is optional in Tizen Mobile Profile.
+%define    tizen_feature_push_support    1
+
+# Sensor API is optional in Tizen Mobile Profile.
+%define    tizen_feature_sensor_support    1
+
+# Secure Element API is optional in Tizen Mobile Profile.
+%ifarch %{arm}
+%define    tizen_feature_se_support    1
+%else
+%define    tizen_feature_se_support    0
+%endif
+
+# Sound API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_sound_support    1
+
+# SystemSetting API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_system_setting_support    1
+%define    tizen_feature_system_setting_home_screen_support    1
+%define    tizen_feature_system_setting_lock_screen_support    1
+%define    tizen_feature_system_setting_incoming_call_screen_support    1
+%define    tizen_feature_system_setting_notification_email_screen_support    1
+
+# Telephony feature is optional in Tizen Mobile Profile.
+%ifarch %{arm}
+%define    tizen_feature_telephony_support    1
+%else
+%define    tizen_feature_telephony_support    0
+%endif
+
+# WebSetting API is mandatory in Tizen Mobile Profile.
+%define    tizen_feature_web_setting_support    1
+
+# Wi-Fi feature is optional in Tizen Mobile Profile.
+%ifarch %{arm}
+%define    tizen_feature_wi_fi_support    1
+%else
+%define    tizen_feature_wi_fi_support    0
+%endif
+
+#- telephony related APIs
+# CallHistory API is optional in Tizen Mobile Profile.
+# NetworkBearerSelection API is optional in Tizen Mobile Profile.
+%if 0%{?tizen_feature_telephony_support}
+%define    tizen_feature_callhistory_support    1
+%define    tizen_feature_nbs_support    1
+%else
+%define    tizen_feature_callhistory_support    0
+%define    tizen_feature_nbs_support    0
+%endif
+
+BuildRequires:  pkgconfig(ewebkit2)
+BuildRequires:  pkgconfig(dpl-efl)
+BuildRequires:  pkgconfig(dpl-event-efl)
+BuildRequires:  pkgconfig(wrt-plugins-types)
+BuildRequires:  pkgconfig(wrt-plugins-commons)
+BuildRequires:  pkgconfig(wrt-plugins-commons-javascript)
+BuildRequires:  pkgconfig(wrt-plugins-plugin-manager)
+BuildRequires:  pkgconfig(wrt-plugins-ipc-message)
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(ecore)
+BuildRequires:  pkgconfig(dbus-1)
+BuildRequires:  pkgconfig(libpcrecpp)
+BuildRequires:  pkgconfig(capi-appfw-application)
+BuildRequires:  pkgconfig(capi-appfw-app-manager)
+BuildRequires:  pkgconfig(capi-appfw-alarm)
+BuildRequires:  pkgconfig(capi-appfw-package-manager)
+BuildRequires:  pkgconfig(storage)
+BuildRequires:  pkgconfig(pkgmgr)
+BuildRequires:  pkgconfig(pkgmgr-info)
+BuildRequires:  pkgconfig(capi-system-info)
+BuildRequires:  pkgconfig(capi-content-media-content)
+BuildRequires:  pkgconfig(capi-media-metadata-extractor)
+BuildRequires:  pkgconfig(appsvc)
+BuildRequires:  pkgconfig(msg-service)
+
+BuildRequires:  pkgconfig(capi-network-connection)
+BuildRequires:  pkgconfig(notification)
+BuildRequires:  pkgconfig(capi-system-runtime-info)
+BuildRequires:  pkgconfig(capi-system-sensor)
+BuildRequires:  pkgconfig(sensor)
+BuildRequires:  pkgconfig(capi-system-system-settings)
+BuildRequires:  pkgconfig(icu-i18n)
+BuildRequires:  pkgconfig(icu-io)
+BuildRequires:  pkgconfig(icu-le)
+BuildRequires:  pkgconfig(icu-lx)
+BuildRequires:  pkgconfig(icu-uc)
+
+BuildRequires:  pkgconfig(tapi)
+BuildRequires:  pkgconfig(capi-system-device)
+BuildRequires:  expat-devel
+BuildRequires:  cmake
+BuildRequires:  gettext-devel
+
+%if 0%{?tizen_feature_account_support}
+BuildRequires:  pkgconfig(accounts-svc)
+%endif
+
+%if 0%{?tizen_feature_archive_support}
+BuildRequires:  pkgconfig(minizip)
+%endif
+
+%if 0%{?tizen_feature_badge_support}
+BuildRequires:  pkgconfig(badge)
+%endif
+
+%if 0%{?tizen_feature_bluetooth_support}
+BuildRequires:  pkgconfig(capi-network-bluetooth)
+%endif
+
+%if 0%{?tizen_feature_bookmark_support}
+BuildRequires:  pkgconfig(capi-web-bookmark)
+%endif
+
+%if 0%{?tizen_feature_calendar_support}
+BuildRequires:  pkgconfig(calendar-service2)
+%endif
+
+%if 0%{?tizen_feature_contact_support}
+BuildRequires:  pkgconfig(contacts-service2)
+%endif
+
+%if 0%{?tizen_feature_datacontrol_support}
+BuildRequires:  pkgconfig(capi-data-control)
+%endif
+
+%if 0%{?tizen_feature_datasync_support}
+BuildRequires:  pkgconfig(sync-agent)
+%endif
+
+%if 0%{?tizen_feature_download_support}
+BuildRequires:  pkgconfig(capi-web-url-download)
+%endif
+
+%if 0%{?tizen_feature_exif_support}
+BuildRequires:  pkgconfig(libexif)
+%endif
+
+%if 0%{?tizen_feature_fm_radio_support}
+BuildRequires:  pkgconfig(capi-media-radio)
+%endif
+
+%if 0%{?tizen_feature_ham_support}
+BuildRequires:  pkgconfig(sensor)
+BuildRequires:  pkgconfig(glib-2.0)
+BuildRequires:  pkgconfig(libcore-context-manager)
+%endif
+
+%if 0%{?tizen_feature_mediakey_support}
+BuildRequires:  pkgconfig(capi-system-media-key)
+%endif
+
+%if 0%{?tizen_feature_messageport_support}
+BuildRequires:  pkgconfig(message-port)
+%endif
+
+%if 0%{?tizen_feature_messaging_email_support}
+BuildRequires:  pkgconfig(email-service)
+%endif
+
+%if 0%{?tizen_feature_nfc_support}
+BuildRequires:  pkgconfig(capi-network-nfc)
+%endif
+
+%if 0%{?tizen_feature_power_support}
+BuildRequires:  pkgconfig(deviced)
+%endif
+
+%if 0%{?tizen_feature_push_support}
+BuildRequires:  pkgconfig(push)
+%endif
+
+%if 0%{?tizen_feature_se_support}
+BuildRequires:  pkgconfig(smartcard-service-common)
+BuildRequires:  pkgconfig(smartcard-service)
+%endif
+
+%if 0%{?tizen_feature_sensor_support}
+BuildRequires:  pkgconfig(sensor)
+BuildRequires:  pkgconfig(capi-system-sensor)
+%endif
+
+%if 0%{?tizen_feature_sound_support}
+BuildRequires:  pkgconfig(capi-media-sound-manager)
+BuildRequires:  pkgconfig(vconf)
+%endif
+
+%if 0%{?tizen_feature_wi_fi_support}
+BuildRequires:  pkgconfig(capi-network-wifi)
+%endif
+
+Requires:  wrt-plugins-common
+
+%description
+JavaScript plugins for WebRuntime
+
+%package devel
+Summary:    Wrt-plugin-tizen development headers
+Group:      Development/Libraries
+Requires:   %{name} = %{version}
+
+%description devel
+Wrt-plugin-tizen development headers
+
+%prep
+%setup -q
+
+%build
+
+%define PREFIX "%{_libdir}/wrt-plugins"
+
+export LDFLAGS+="-Wl,--rpath=%{PREFIX} -Wl,--as-needed"
+
+# enable debugging
+export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
+export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
+
+cmake \
+%if 0%{?tizen_profile_mobile}
+-DENABLE_TIZEN_MOBILE_PROFILE=YES \
+%endif
+%if 0%{?tizen_profile_wearable}
+-DENABLE_TIZEN_WEARABLE_PROFILE=YES \
+%endif
+%if 0%{?tizen_profile_tv}
+-DENABLE_TIZEN_TV_PROFILE=YES \
+%endif
+%if 0%{?tizen_feature_impl_backward_compatible_support}
+-DENABLE_IMPL_BACKWARD_COMPATIBLE=YES \
+%endif
+%if 0%{?tizen_feature_core_api_support}
+-DENABLE_OPTIONAL_CORE_API=YES \
+%endif
+%if 0%{?tizen_feature_app_control_setting_support}
+-DENABLE_TIZEN_APP_CONTROL_SETTING_SUPPORT=YES \
+%endif
+%if 0%{?tizen_feature_account_support}
+-DENABLE_OPTIONAL_ACCOUNT=YES \
+%endif
+%if 0%{?tizen_feature_archive_support}
+-DENABLE_OPTIONAL_ARCHIVE=YES \
+%endif
+%if 0%{?tizen_feature_badge_support}
+-DENABLE_OPTIONAL_BADGE=YES \
+%endif
+%if 0%{?tizen_feature_bluetooth_support}
+-DENABLE_OPTIONAL_BT=YES \
+%endif
+%if 0%{?tizen_feature_bluetooth_health_support}
+-DENABLE_OPTIONAL_BT_HEALTH=YES \
+%endif
+%if 0%{?tizen_feature_bluetooth_always_on}
+-DENABLE_OPTIONAL_BT_ALWAYS_ON=YES \
+%endif
+%if 0%{?tizen_feature_bookmark_support}
+-DENABLE_OPTIONAL_BOOKMARK=YES \
+%endif
+%if 0%{?tizen_feature_calendar_support}
+-DENABLE_OPTIONAL_CALENDAR=YES \
+%endif
+%if 0%{?tizen_feature_callhistory_support}
+-DENABLE_OPTIONAL_CALL_HISTORY=YES \
+%endif
+%if 0%{?tizen_feature_contact_support}
+-DENABLE_OPTIONAL_CONTACT=YES \
+%endif
+%if 0%{?tizen_feature_content_support}
+-DENABLE_OPTIONAL_CONTENT=YES \
+%endif
+%if 0%{?tizen_feature_datacontrol_support}
+-DENABLE_OPTIONAL_DATA_CONTROL=YES \
+%endif
+%if 0%{?tizen_feature_datasync_support}
+-DENABLE_OPTIONAL_DATA_SYNC=YES \
+%endif
+%if 0%{?tizen_feature_download_support}
+-DENABLE_OPTIONAL_DOWNLOAD=YES \
+%endif
+%if 0%{?tizen_feature_exif_support}
+-DENABLE_OPTIONAL_EXIF=YES \
+%endif
+%if 0%{?tizen_feature_fm_radio_support}
+-DENABLE_OPTIONAL_FM_RADIO=YES \
+%endif
+%if 0%{?tizen_feature_ham_support}
+-DENABLE_OPTIONAL_HAM=YES \
+%endif
+%if 0%{?tizen_feature_location_batch}
+-DENABLE_OPTIONAL_LOCATION_BATCH=YES \
+%endif
+%if 0%{?tizen_feature_mediakey_support}
+-DENABLE_OPTIONAL_MEDIAKEY=YES \
+%endif
+%if 0%{?tizen_feature_messageport_support}
+-DENABLE_OPTIONAL_MESSAGE_PORT=YES \
+%endif
+%if 0%{?tizen_feature_messaging_support}
+-DENABLE_OPTIONAL_MESSAGING=YES \
+%endif
+%if 0%{?tizen_feature_messaging_email_support}
+-DENABLE_OPTIONAL_MESSAGING_EMAIL=YES \
+%endif
+%if 0%{?tizen_feature_nbs_support}
+-DENABLE_OPTIONAL_NBS=YES \
+%endif
+%if 0%{?tizen_feature_nfc_support}
+-DENABLE_OPTIONAL_NFC=YES \
+%endif
+%if 0%{?tizen_feature_nfc_emulation_support}
+-DENABLE_OPTIONAL_NFC_EMULATION=YES \
+%endif
+%if 0%{?tizen_feature_notification_support}
+-DENABLE_OPTIONAL_NOTIFICATION=YES \
+%endif
+%if 0%{?tizen_feature_power_support}
+-DENABLE_OPTIONAL_POWER=YES \
+%endif
+%if 0%{?tizen_feature_push_support}
+-DENABLE_OPTIONAL_PUSH=YES \
+%endif
+%if 0%{?tizen_feature_se_support}
+-DENABLE_OPTIONAL_SE=YES \
+%endif
+%if 0%{?tizen_feature_sensor_support}
+-DENABLE_OPTIONAL_SENSOR=YES \
+%endif
+%if 0%{?tizen_feature_sound_support}
+-DENABLE_OPTIONAL_SOUND=YES \
+%endif
+%if 0%{?tizen_feature_system_setting_support}
+-DENABLE_OPTIONAL_SYSTEM_SETTING=YES \
+%endif
+%if 0%{?tizen_feature_system_setting_home_screen_support}
+-DENABLE_OPTIONAL_SYSTEM_SETTING_HOME_SCREEN=YES \
+%endif
+%if 0%{?define tizen_feature_system_setting_lock_screen_support}
+-DENABLE_OPTIONAL_SYSTEM_SETTING_LOCK_SCREEN=YES \
+%endif
+%if 0%{?ttizen_feature_system_setting_incoming_call_screen_support}
+-DENABLE_OPTIONAL_SYSTEM_SETTING_INCOMING_CALL=YES \
+%endif
+%if 0%{?ttizen_feature_system_setting_notification_email_screen_support}
+-DENABLE_OPTIONAL_SYSTEM_SETTING_EMAIL_SCREEN=YES \
+%endif
+%if 0%{?tizen_feature_telephony_support}
+-DENABLE_OPTIONAL_TELEPHONY=YES \
+%endif
+%if 0%{?tizen_feature_web_setting_support}
+-DENABLE_OPTIONAL_WEB_SETTING=YES \
+%endif
+%if 0%{?tizen_feature_wi_fi_support}
+-DENABLE_OPTIONAL_WI_FI=YES \
+%endif
+-DCMAKE_INSTALL_PREFIX=%{_prefix} -DDPL_LOG="OFF" -DENABLE_TIME_TRACER="OFF" -DDISABLE_ACE_ACCESS_CHECK="OFF"
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+%make_install
+mkdir -p %{buildroot}/usr/share/license
+cp LICENSE %{buildroot}/usr/share/license/%{name}
+
+%post
+#update plugins
+if [ -x /usr/bin/wrt-plugins-installer ]
+then
+    echo "Now, update plugins by wrt-plugins-installer."
+    /usr/bin/wrt-plugins-installer
+    echo "done."
+else
+    echo "Cannot find executable: /usr/bin/wrt-plugins-installer!"
+fi
+
+%postun
+
+
+%files
+%manifest wrt-plugins-tizen.manifest
+%{_libdir}/wrt-plugins/*
+/usr/etc/tizen-apis/*
+/usr/share/license/%{name}
+
+%files devel
+%{_includedir}/*
+%{_libdir}/pkgconfig/*
diff --git a/pkgconfigs/wrt-plugins-tizen-account.pc.in b/pkgconfigs/wrt-plugins-tizen-account.pc.in
new file mode 100755 (executable)
index 0000000..0dd4390
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=account
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: accounts-svc
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-alarm.pc.in b/pkgconfigs/wrt-plugins-tizen-alarm.pc.in
new file mode 100755 (executable)
index 0000000..f51b318
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=alarm
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-appfw-application capi-appfw-alarm
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-application.pc.in b/pkgconfigs/wrt-plugins-tizen-application.pc.in
new file mode 100644 (file)
index 0000000..4558d9b
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=application
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-appfw-app-manager capi-appfw-application capi-appfw-package-manager pkgmgr pkgmgr-info
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-archive.pc.in b/pkgconfigs/wrt-plugins-tizen-archive.pc.in
new file mode 100644 (file)
index 0000000..fd7fabe
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=archive
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires:
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl -lwrt-plugins-tizen-${module_name}-config
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-badge.pc.in b/pkgconfigs/wrt-plugins-tizen-badge.pc.in
new file mode 100755 (executable)
index 0000000..767dcc2
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=badge
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: badge
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-bluetooth.pc.in b/pkgconfigs/wrt-plugins-tizen-bluetooth.pc.in
new file mode 100644 (file)
index 0000000..7b03f29
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=bluetooth
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-network-bluetooth
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-bookmark.pc.in b/pkgconfigs/wrt-plugins-tizen-bookmark.pc.in
new file mode 100644 (file)
index 0000000..f8109d2
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=bookmark
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-web-favorites
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-calendar.pc.in b/pkgconfigs/wrt-plugins-tizen-calendar.pc.in
new file mode 100644 (file)
index 0000000..0590345
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=calendar
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: calendar-service2 icu-i18n
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-callhistory.pc.in b/pkgconfigs/wrt-plugins-tizen-callhistory.pc.in
new file mode 100755 (executable)
index 0000000..4c18371
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=callhistory
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: contacts-service2 glib-2.0 libpcrecpp
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-common.pc.in b/pkgconfigs/wrt-plugins-tizen-common.pc.in
new file mode 100755 (executable)
index 0000000..7880649
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=common
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-tizen
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires:
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-contact.pc.in b/pkgconfigs/wrt-plugins-tizen-contact.pc.in
new file mode 100755 (executable)
index 0000000..2612c20
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=contact
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: contacts-service2 libpcrecpp
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-content.pc.in b/pkgconfigs/wrt-plugins-tizen-content.pc.in
new file mode 100644 (file)
index 0000000..69c4601
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=content
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-content-media-content  capi-media-metadata-extractor
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-datacontrol.pc.in b/pkgconfigs/wrt-plugins-tizen-datacontrol.pc.in
new file mode 100644 (file)
index 0000000..cb10aa0
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=datacontrol
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-appfw-application appsvc pkgmgr
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-datasync.pc.in b/pkgconfigs/wrt-plugins-tizen-datasync.pc.in
new file mode 100644 (file)
index 0000000..49ca8bc
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=datasync
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: sync-agent
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-download.pc.in b/pkgconfigs/wrt-plugins-tizen-download.pc.in
new file mode 100644 (file)
index 0000000..a703343
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=download
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-web-url-download
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-exif.pc.in b/pkgconfigs/wrt-plugins-tizen-exif.pc.in
new file mode 100644 (file)
index 0000000..5c1e3a7
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=exif
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: libexif
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-filesystem.pc.in b/pkgconfigs/wrt-plugins-tizen-filesystem.pc.in
new file mode 100755 (executable)
index 0000000..0db60de
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=filesystem
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires:
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-filesystem_new.pc.in b/pkgconfigs/wrt-plugins-tizen-filesystem_new.pc.in
new file mode 100755 (executable)
index 0000000..3deb9e4
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=filesystem
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires:
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl -lwrt-plugins-tizen-${module_name}-config
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-fmradio.pc.in b/pkgconfigs/wrt-plugins-tizen-fmradio.pc.in
new file mode 100755 (executable)
index 0000000..3fe6106
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=fmradio
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-media-radio
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-humanactivitymonitor.pc.in b/pkgconfigs/wrt-plugins-tizen-humanactivitymonitor.pc.in
new file mode 100755 (executable)
index 0000000..e35cdf1
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=humanactivitymonitor
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-context-manager glib-2.0 capi-system-info
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-log.pc.in b/pkgconfigs/wrt-plugins-tizen-log.pc.in
new file mode 100644 (file)
index 0000000..d9b5e9c
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=application
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-appfw-app-manager capi-appfw-application capi-appfw-package-manager wrt-deviceapis-commons wrt-deviceapis-commons-javascript pkgmgr pkgmgr-info
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name} -lwrt-plugins-tizen-${module_name}-impl -lwrt-plugins-tizen-${module_name}-config
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-mediakey.pc.in b/pkgconfigs/wrt-plugins-tizen-mediakey.pc.in
new file mode 100644 (file)
index 0000000..a8e8e62
--- /dev/null
@@ -0,0 +1,12 @@
+me=@CMAKE_PROJECT_NAME@
+module_name=MediaKey
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-system-media-key
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-messageport.pc.in b/pkgconfigs/wrt-plugins-tizen-messageport.pc.in
new file mode 100755 (executable)
index 0000000..2ec6fc5
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=messageport
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: message-port capi-appfw-app-manager
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-messaging.pc.in b/pkgconfigs/wrt-plugins-tizen-messaging.pc.in
new file mode 100644 (file)
index 0000000..b186586
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=messaging
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: msg-service email-service dbus-1
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-networkbearerselection.pc.in b/pkgconfigs/wrt-plugins-tizen-networkbearerselection.pc.in
new file mode 100644 (file)
index 0000000..421f6ee
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=networkbearerselection
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-network-connection
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-nfc.pc.in b/pkgconfigs/wrt-plugins-tizen-nfc.pc.in
new file mode 100644 (file)
index 0000000..187e0a1
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=nfc
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-network-nfc
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-notification.pc.in b/pkgconfigs/wrt-plugins-tizen-notification.pc.in
new file mode 100644 (file)
index 0000000..8795fe0
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=notification
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-appfw-application
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-package.pc.in b/pkgconfigs/wrt-plugins-tizen-package.pc.in
new file mode 100644 (file)
index 0000000..5f80e24
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=package
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-appfw-app-manager capi-appfw-package-manager wrt-deviceapis-commons wrt-deviceapis-commons-javascript pkgmgr pkgmgr-info
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-power.pc.in b/pkgconfigs/wrt-plugins-tizen-power.pc.in
new file mode 100644 (file)
index 0000000..976bc8d
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=power
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-system-device
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-push.pc.in b/pkgconfigs/wrt-plugins-tizen-push.pc.in
new file mode 100644 (file)
index 0000000..a73a959
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=push
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: push capi-appfw-application
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-secureelement.pc.in b/pkgconfigs/wrt-plugins-tizen-secureelement.pc.in
new file mode 100644 (file)
index 0000000..25dce1b
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=secureelement
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: smartcard-service smartcard-service-common 
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-sensor.pc.in b/pkgconfigs/wrt-plugins-tizen-sensor.pc.in
new file mode 100755 (executable)
index 0000000..89305d4
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=sensor
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-system-sensor
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-sound.pc.in b/pkgconfigs/wrt-plugins-tizen-sound.pc.in
new file mode 100644 (file)
index 0000000..3b290d7
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=wrt-plugins-tizen
+module_name=audio
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version:
+Requires: capi-media-sound-manager
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-systeminfo.pc.in b/pkgconfigs/wrt-plugins-tizen-systeminfo.pc.in
new file mode 100755 (executable)
index 0000000..67af637
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=systeminfo
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-network-connection capi-system-info capi-system-runtime-info capi-system-sensor sensor
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
diff --git a/pkgconfigs/wrt-plugins-tizen-systemsetting.pc.in b/pkgconfigs/wrt-plugins-tizen-systemsetting.pc.in
new file mode 100755 (executable)
index 0000000..74fc8c5
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=systemsetting
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: capi-system-system-settings
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-timeutil.pc.in b/pkgconfigs/wrt-plugins-tizen-timeutil.pc.in
new file mode 100644 (file)
index 0000000..a6bbc6b
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=timeutil
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: icu-i18n icu-io icu-le icu-lx icu-uc 
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-tizen.pc.in b/pkgconfigs/wrt-plugins-tizen-tizen.pc.in
new file mode 100644 (file)
index 0000000..8b86ec4
--- /dev/null
@@ -0,0 +1,13 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=tizen
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Requires: wrt-plugins-plugin-manager
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}-impl -lwrt-plugins-tizen-${module_name}-config
+Cflags: -I${includedir}/${module_name}
\ No newline at end of file
diff --git a/pkgconfigs/wrt-plugins-tizen-websetting.pc.in b/pkgconfigs/wrt-plugins-tizen-websetting.pc.in
new file mode 100755 (executable)
index 0000000..e7346e1
--- /dev/null
@@ -0,0 +1,12 @@
+prefix=/usr
+project_name=@CMAKE_PROJECT_NAME@
+module_name=websetting
+exec_prefix=${prefix}
+libdir=${prefix}/lib/wrt-plugins/tizen-${module_name}
+includedir=${prefix}/include/${project_name}
+
+Name: wrt-plugins-tizen-${module_name}
+Description: wrt-plugins-tizen-${module_name}
+Version: @CMAKE_PROJECT_VERSION@
+Libs: -L${libdir} -lwrt-plugins-tizen-${module_name}
+Cflags: -I${includedir}/${module_name}
diff --git a/src/Account/Account.cpp b/src/Account/Account.cpp
new file mode 100755 (executable)
index 0000000..2db230f
--- /dev/null
@@ -0,0 +1,274 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "Account.h"
+#include "AccountManager.h"
+#include "AccountExtendedDataCallback.h"
+#include "AccountUtil.h"
+
+#include <sstream>
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Account {
+
+Account::Account():
+    SecurityAccessor(),
+    m_id(-1),
+    m_is_id_set(false),
+    m_userName(""),
+    m_iconUri(""),
+    m_handle(NULL)
+{
+    int ret = account_create(&m_handle);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "account create failed");
+    }
+}
+
+Account::Account(account_h handle):
+    SecurityAccessor(),
+    m_id(-1),
+    m_is_id_set(false),
+    m_userName(""),
+    m_iconUri(""),
+    m_handle(NULL)
+{
+    LOGD("Enter");
+
+    setHandle(handle);
+}
+
+Account::~Account()
+{
+    freeHandle();
+}
+
+unsigned long Account::getId() const
+{
+    return m_id;
+}
+
+void Account::setId(unsigned long id)
+{
+    m_is_id_set = true;
+    m_id = id;
+}
+
+bool Account::isIdSet()
+{
+    return m_is_id_set;
+}
+
+std::string Account::getUserName() const
+{
+    return m_userName;
+}
+
+void Account::setUserName(std::string userName)
+{
+    m_userName = userName;
+}
+
+std::string Account::getIconUri() const
+{
+    return m_iconUri;
+}
+
+void Account::setIconUri(std::string iconUri)
+{
+    m_iconUri = iconUri;
+}
+
+AccountProviderPtr Account::getProvider() const
+{
+    return m_provider;
+}
+
+void Account::setProvider(AccountProviderPtr provider)
+{
+    m_provider = provider;
+}
+
+account_h Account::getHandle()
+{
+    return m_handle;
+}
+
+void Account::setHandle(account_h handle)
+{
+    LOGD("Enter");
+
+    if(!handle) {
+        LOGE("Invalid account handle");
+        throw UnknownException("Invalid account handle");
+    }
+
+    freeHandle();
+
+    m_handle = handle;
+
+    int accountId;
+    char *tmp = NULL;
+    int ret = account_get_account_id(handle, &accountId);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to get account id");
+    }
+    m_id = static_cast<unsigned long>(accountId);
+    m_is_id_set = true;
+
+    ret = account_get_user_name(handle, &tmp);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to get userName");
+    }
+    if(NULL != tmp) {
+        m_userName = tmp;
+        free(tmp);
+        tmp = NULL;
+    }
+
+    ret = account_get_icon_path(handle, &tmp);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to get iconPath");
+    }
+    if(NULL != tmp) {
+        m_iconUri = tmp;
+        free(tmp);
+        tmp = NULL;
+    }
+
+    ret = account_get_package_name(handle, &tmp);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to get packageName");
+    }
+
+    if (NULL != tmp) {
+        AccountProviderPtr provider =
+            AccountManager::getInstance().getProvider(std::string(tmp));
+        free(tmp);
+        tmp = NULL;
+
+        m_provider = provider;
+    }
+}
+
+void Account::syncHandle()
+{
+    int ret = account_set_user_name(m_handle, m_userName.c_str());
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to set userName");
+    }
+
+    ret = account_set_icon_path(m_handle, m_iconUri.c_str());
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to set iconPath");
+    }
+
+    std::string packageName = m_provider->getApplicationId();
+    ret = account_set_package_name(m_handle, packageName.c_str());
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to set packageName");
+    }
+}
+
+void Account::freeHandle()
+{
+    LOGD("Enter");
+
+    if(m_handle) {
+        int ret = account_destroy(m_handle);
+        if (ACCOUNT_ERROR_NONE != ret) {
+            LOGE("%d", ret);
+            AccountUtil::throwAccountException(ret, "Failed to account destroy");
+        }
+
+        m_handle = NULL;
+    }
+}
+
+void Account::setExtendedData(const std::string &key, const std::string &value)
+{
+    LOGD("Enter");
+
+    LOGD("key: %s, value: %s", key.c_str(), value.c_str());
+    int ret = account_set_custom(m_handle, key.c_str(), value.c_str());
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+
+        std::stringstream ss;
+
+        ss << "account set custom failed, "
+           << "key - " << key << ", value - " << value;
+        AccountUtil::throwAccountException(ret, ss.str());
+    }
+}
+
+std::string Account::getExtendedData(const std::string &key)
+{
+    LOGD("Enter");
+
+    char *v = NULL;
+    int ret = account_get_custom(m_handle, key.c_str(), &v);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+
+        if (ACCOUNT_ERROR_RECORD_NOT_FOUND == ret) {
+            LOGE("There is no extended data value for %s", key.c_str());
+            throw NotFoundException("There is no extended data value for specified key");
+        }
+
+        std::stringstream ss;
+        ss << "account get custom failed, key - " << key;
+        AccountUtil::throwAccountException(ret, ss.str());
+    }
+
+    std::string value = v;
+    free(v);
+    return value;
+}
+
+void Account::getExtendedData(AccountExtendedDataCallback *extendedDataCallback)
+{
+    LOGD("Enter");
+
+    extendedDataCallback->setHandle(m_handle);
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, AccountExtendedDataCallback::thread,
+            static_cast<void *>(extendedDataCallback))) {
+        delete extendedDataCallback;
+        LOGE("Failed to create pthread for getExtendedData()");
+        throw UnknownException("Failed to create pthread for getExtendedData()");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for getExtendedData()");
+    }
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/Account.h b/src/Account/Account.h
new file mode 100755 (executable)
index 0000000..053b5d2
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_H__
+#define __TIZEN_ACCOUNT_H__
+
+#include <account.h>
+#include <SecurityAccessor.h>
+
+#include "AccountTypes.h"
+#include "AccountProvider.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+class Account;
+class AccountExtendedDataCallback;
+
+typedef std::shared_ptr<Account> AccountPtr;
+
+struct AccountHolder {
+    AccountPtr ptr;
+};
+
+class Account : public Common::SecurityAccessor
+{
+public:
+    Account();
+    Account(account_h handle);
+    virtual ~Account();
+
+    unsigned long getId() const;
+    void setId(unsigned long id);
+    bool isIdSet();
+
+    std::string getUserName() const;
+    void setUserName(std::string userName);
+
+    std::string getIconUri() const;
+    void setIconUri(std::string iconUri);
+
+    AccountProviderPtr getProvider() const;
+    void setProvider(AccountProviderPtr provider);
+
+    void setExtendedData(const std::string &key, const std::string &value);
+    std::string getExtendedData(const std::string &key);
+    void getExtendedData(AccountExtendedDataCallback* extendedDataCallback);
+
+    account_h getHandle();
+    void syncHandle();
+
+private:
+    unsigned long m_id;
+    bool m_is_id_set;
+    std::string m_userName;
+    std::string m_iconUri;
+    AccountProviderPtr m_provider;
+
+    account_h m_handle;
+
+    void setHandle(account_h handle);
+    void freeHandle();
+};
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_H__
diff --git a/src/Account/AccountArrayCallback.cpp b/src/Account/AccountArrayCallback.cpp
new file mode 100755 (executable)
index 0000000..2e3a03d
--- /dev/null
@@ -0,0 +1,177 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AccountArrayCallback.h"
+#include "AccountManager.h"
+#include "AccountArrayCallback.h"
+#include "AccountUtil.h"
+
+#include <sstream>
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+AccountArrayCallback::AccountArrayCallback(JSContextRef globalCtx):
+    OperationCallback(globalCtx),
+    m_applicationId("")
+{
+}
+
+AccountArrayCallback::~AccountArrayCallback()
+{
+    m_accountArray.clear();
+}
+
+std::vector<AccountPtr> AccountArrayCallback::getAccountArray()
+{
+    return m_accountArray;
+}
+
+void AccountArrayCallback::addAccount(AccountPtr account)
+{
+    LOGD("Enter");
+
+    m_accountArray.push_back(account);
+}
+
+std::string AccountArrayCallback::getApplicationId()
+{
+    return m_applicationId;
+}
+
+void AccountArrayCallback::setApplicationId(std::string applicationId)
+{
+    m_applicationId = applicationId;
+}
+
+void AccountArrayCallback::onSuccess()
+{
+    LOGD("Enter");
+
+    int size = m_accountArray.size();
+    JSContextRef context = getContext();
+    JSValueRef rows[size];
+    JSValueRef exception = NULL;
+    for(auto it = m_accountArray.begin(); it != m_accountArray.end(); it++) {
+        JSObjectRef account = JSAccount::makeJSObject(context, *it);
+        rows[std::distance(m_accountArray.begin(), it)] = account;
+    }
+    JSObjectRef resultArray = JSObjectMakeArray(context, size, rows, &exception);
+    if(exception != NULL) {
+        LOGE("Failed to create JSArray");
+        throw UnknownException("Failed to create JSArray");
+    }
+
+    callSuccessCallback(resultArray);
+}
+
+bool AccountArrayCallback::_account_cb(account_h handle, void *data)
+{
+    LOGD("Enter");
+    AccountArrayCallback* cb = static_cast<AccountArrayCallback *>(data);
+
+    try {
+        AccountManager &manager = AccountManager::getInstance();
+
+        int accountId;
+        int ret = account_get_account_id(handle, &accountId);
+        if (ret != ACCOUNT_ERROR_NONE) {
+            LOGE("%d", ret);
+            AccountUtil::throwAccountException(ret, "Failed to get account id");
+        }
+
+        AccountPtr account = manager.getAccount(accountId);
+        cb->addAccount(account);
+    } catch (BasePlatformException& err) {
+        cb->setError(err.getName(), err.getMessage());
+        return false;
+    }
+    return true;
+}
+
+void *AccountArrayCallback::thread(void *data)
+{
+    LOGD("Enter");
+    AccountArrayCallback* cb = static_cast<AccountArrayCallback *>(data);
+    std::string packageName = cb->getApplicationId();
+
+    int ret;
+    if ("" == packageName) {
+        ret = account_foreach_account_from_db(_account_cb, data);
+    } else {
+        LOGD("packageName: %s", packageName.c_str());
+        ret = account_query_account_by_package_name(_account_cb,
+            packageName.c_str(), data);
+    }
+
+    /* if any account is not found, empty array will be returned. */
+    if(ACCOUNT_ERROR_NONE != ret && ACCOUNT_ERROR_RECORD_NOT_FOUND != ret) {
+        std::stringstream ss;
+
+        ss << "Failed to query accounts : "
+           << AccountUtil::getAccountErrorMessage(ret);
+        LOGE("%s", ss.str().c_str());
+        cb->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, ss.str());
+    }
+
+    if(!g_idle_add(_complete, data)) {
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+gboolean AccountArrayCallback::_complete(void *data)
+{
+    LOGD("Enter");
+    AccountArrayCallback *cb = static_cast<AccountArrayCallback *>(data);
+
+    if(cb->hasError()) {
+        cb->onError();
+    } else {
+        try {
+            JSContextRef context = cb->getContext();
+            if(!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+                LOGE("context was closed");
+                throw UnknownException("context was closed");
+            }
+
+            cb->onSuccess();
+        } catch (BasePlatformException &err) {
+            cb->setError(err.getName(), err.getMessage());
+            cb->onError();
+        } catch (...) {
+            cb->setError(
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Accounts failed");
+            cb->onError();
+        }
+    }
+
+    delete cb;
+    return false;
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/AccountArrayCallback.h b/src/Account/AccountArrayCallback.h
new file mode 100755 (executable)
index 0000000..c160e08
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_ARRAY_CALLBACK_H__
+#define __TIZEN_ACCOUNT_ARRAY_CALLBACK_H__
+
+#include <vector>
+#include <account.h>
+#include <glib.h>
+
+#include "OperationCallback.h"
+#include "JSAccount.h"
+
+namespace DeviceAPI {
+namespace Account {
+
+class AccountArrayCallback : public OperationCallback
+{
+public:
+    AccountArrayCallback(JSContextRef globalCtx);
+    virtual ~AccountArrayCallback();
+
+    std::vector<AccountPtr> getAccountArray();
+    void addAccount(AccountPtr account);
+
+    std::string getApplicationId();
+    void setApplicationId(std::string applicationId);
+
+    static void* thread(void *data);
+    virtual void onSuccess();
+
+private:
+    std::vector<AccountPtr> m_accountArray;
+    std::string m_applicationId;
+
+    static bool _account_cb(account_h handle, void *data);
+    static gboolean _complete(void *data);
+};
+
+typedef std::shared_ptr<AccountArrayCallback> AccountArrayCallbackPtr;
+
+} // Account
+} // DeviceAPI
+
+
+#endif // __TIZEN_ACCOUNT_ARRAY_CALLBACK_H__
diff --git a/src/Account/AccountChangeCallback.cpp b/src/Account/AccountChangeCallback.cpp
new file mode 100755 (executable)
index 0000000..6d33453
--- /dev/null
@@ -0,0 +1,139 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AccountChangeCallback.h"
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+
+namespace DeviceAPI {
+namespace Account {
+
+AccountChangeCallback::AccountChangeCallback(JSContextRef globalCtx,
+                                             JSObjectRef addedCallback,
+                                             JSObjectRef removedCallback,
+                                             JSObjectRef updatedCallback)
+    : MultiCallbackUserData(globalCtx)
+{
+    setCallback("onadded", addedCallback);
+    setCallback("onremoved", removedCallback);
+    setCallback("onupdated", updatedCallback);
+}
+
+AccountChangeCallback::~AccountChangeCallback()
+{
+}
+
+unsigned long AccountChangeCallback::getAccountId()
+{
+    return m_accountId;
+}
+
+void AccountChangeCallback::setAccountId(unsigned long accountId)
+{
+    m_accountId = accountId;
+}
+
+AccountPtr AccountChangeCallback::getAccount()
+{
+    return m_account;
+}
+
+void AccountChangeCallback::setAccount(AccountPtr account)
+{
+    m_account = account;
+}
+
+AccountEventType AccountChangeCallback::getAccountEventType()
+{
+    return m_accountEventType;
+}
+
+void AccountChangeCallback::setAccountEventType(AccountEventType accountEventType)
+{
+    m_accountEventType = accountEventType;
+}
+
+
+void AccountChangeCallback::onadded(AccountPtr account)
+{
+    LOGD("Enter");
+
+    JSContextRef context = getContext();
+
+    JSObjectRef result = JSAccount::makeJSObject(context, account);
+    invokeCallback("onadded", result);
+}
+
+void AccountChangeCallback::onremoved(unsigned long accountId)
+{
+    LOGD("Enter");
+
+    JSContextRef context = getContext();
+
+    invokeCallback("onremoved", JSUtil::toJSValueRef(context, accountId));
+}
+
+void AccountChangeCallback::onupdated(AccountPtr account)
+{
+    LOGD("Enter");
+
+    JSContextRef context = getContext();
+
+    JSObjectRef result = JSAccount::makeJSObject(context, account);
+    invokeCallback("onupdated", result);
+}
+
+gboolean AccountChangeCallback::complete(void *data)
+{
+    LOGD("Enter");
+    AccountChangeCallbackPtr *holder = static_cast<AccountChangeCallbackPtr *>(data);
+    AccountChangeCallbackPtr cb = *holder;
+
+    try {
+        JSContextRef context = cb->getContext();
+        if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            throw UnknownException("context was closed");
+        }
+
+        switch (cb->m_accountEventType) {
+            case INSERT:
+                cb->onadded(cb->m_account);
+            break;
+            case DELETE:
+                cb->onremoved(cb->m_accountId);
+            break;
+            case UPDATE:
+                cb->onupdated(cb->m_account);
+            break;
+        }
+    } catch (BasePlatformException &err) {
+        LOGE("%s : %s", (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Something strange happened");
+    }
+
+    delete holder;
+    return false;
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/AccountChangeCallback.h b/src/Account/AccountChangeCallback.h
new file mode 100755 (executable)
index 0000000..471b124
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_CHANGE_CALLBACK_H__
+#define __TIZEN_ACCOUNT_CHANGE_CALLBACK_H__
+
+#include <string>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <glib.h>
+
+#include "JSAccount.h"
+
+namespace DeviceAPI {
+namespace Account {
+
+enum AccountEventType {
+    INSERT = 0,
+    DELETE,
+    UPDATE
+};
+
+class AccountChangeCallback : MultiCallbackUserData
+{
+public:
+    AccountChangeCallback(JSContextRef globalCtx,
+                          JSObjectRef addedCallback,
+                          JSObjectRef removedCallback,
+                          JSObjectRef updatedCallback);
+    virtual ~AccountChangeCallback();
+
+    void onadded(AccountPtr account);
+    void onremoved(unsigned long accountId);
+    void onupdated(AccountPtr account);
+
+    static gboolean complete(void *data);
+
+    unsigned long getAccountId();
+    void setAccountId(unsigned long accountId);
+    AccountPtr getAccount();
+    void setAccount(AccountPtr account);
+    AccountEventType getAccountEventType();
+    void setAccountEventType(AccountEventType accountEventType);
+
+private:
+    unsigned long m_accountId;
+    AccountPtr m_account;
+    AccountEventType m_accountEventType;
+};
+
+typedef std::shared_ptr<AccountChangeCallback> AccountChangeCallbackPtr;
+
+} // Account
+} // DeviceAPI
+
+
+
+#endif // __TIZEN_ACCOUNT_CHANGE_CALLBACK_H__
diff --git a/src/Account/AccountExtendedData.cpp b/src/Account/AccountExtendedData.cpp
new file mode 100755 (executable)
index 0000000..0941840
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AccountExtendedData.h"
+
+namespace DeviceAPI {
+namespace Account {
+
+AccountExtendedData::AccountExtendedData():
+    m_key(""),
+    m_value("")
+{
+}
+
+AccountExtendedData::AccountExtendedData(std::string key, std::string value):
+    m_key(key),
+    m_value(value)
+{
+}
+
+AccountExtendedData::~AccountExtendedData()
+{
+}
+
+std::string AccountExtendedData::getKey()
+{
+    return m_key;
+}
+
+void AccountExtendedData::setKey(std::string key)
+{
+    m_key = key;
+}
+
+std::string AccountExtendedData::getValue()
+{
+    return m_value;
+}
+
+void AccountExtendedData::setValue(std::string value)
+{
+    m_value = value;
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/AccountExtendedData.h b/src/Account/AccountExtendedData.h
new file mode 100755 (executable)
index 0000000..c1be8b4
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_EXTENDED_DATA_H__
+#define __TIZEN_ACCOUNT_EXTENDED_DATA_H__
+
+#include <string>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Account {
+
+class AccountExtendedData
+{
+public:
+    AccountExtendedData();
+    AccountExtendedData(std::string key, std::string value);
+    virtual ~AccountExtendedData();
+
+    std::string getKey();
+    void setKey(std::string key);
+
+    std::string getValue();
+    void setValue(std::string value);
+
+private:
+    std::string m_key;
+    std::string m_value;
+
+};
+
+typedef std::shared_ptr<AccountExtendedData> AccountExtendedDataPtr;
+
+struct AccountExtendedDataHolder {
+    AccountExtendedDataPtr ptr;
+};
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_EXTENDED_DATA_H__
diff --git a/src/Account/AccountExtendedDataCallback.cpp b/src/Account/AccountExtendedDataCallback.cpp
new file mode 100755 (executable)
index 0000000..4222d8d
--- /dev/null
@@ -0,0 +1,171 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AccountExtendedDataCallback.h"
+#include "AccountUtil.h"
+#include "JSAccountExtendedData.h"
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+AccountExtendedDataCallback::AccountExtendedDataCallback(JSContextRef globalCtx):
+    OperationCallback(globalCtx)
+{
+}
+
+AccountExtendedDataCallback::~AccountExtendedDataCallback()
+{
+    m_dataMap.clear();
+}
+
+void AccountExtendedDataCallback::onSuccess()
+{
+    LOGD("Enter");
+
+    int size = m_dataMap.size();
+    JSContextRef context = getContext();
+    LOGD("%d", size);
+
+    JSValueRef rows[size];
+    JSValueRef exception = NULL;
+    for (auto it = m_dataMap.begin(); it != m_dataMap.end(); it++) {
+        std::string key = (*it).first;
+        std::string value = (*it).second;
+        LOGD("%s, %s", key.c_str(), value.c_str());
+
+        AccountExtendedDataPtr extendedData =
+            AccountExtendedDataPtr(new AccountExtendedData(key, value));
+        JSObjectRef obj =
+            JSObjectMake(context, JSAccountExtendedData::getClassRef(), NULL);
+        JSAccountExtendedData::setPrivateObject(obj, extendedData);
+
+        int index = std::distance(m_dataMap.begin(), it);
+        rows[index] = obj;
+    }
+
+    JSObjectRef resultArray = JSObjectMakeArray(context, size, rows, &exception);
+    if (exception != NULL) {
+        LOGE("Failed to create JSArray");
+        throw UnknownException("Failed to create Array");
+    }
+    callSuccessCallback(resultArray);
+}
+
+std::map<std::string, std::string> AccountExtendedDataCallback::getData()
+{
+    return m_dataMap;
+}
+
+void AccountExtendedDataCallback::addData(const std::string &key,
+                                          const std::string &value)
+{
+    LOGD("Enter");
+    m_dataMap.insert(std::pair<std::string, std::string>(key, value));
+}
+
+account_h AccountExtendedDataCallback::getHandle()
+{
+    return m_handle;
+}
+
+void AccountExtendedDataCallback::setHandle(account_h handle)
+{
+    m_handle = handle;
+}
+
+bool AccountExtendedDataCallback::_custom_cb(char *key, char *value, void *data)
+{
+    LOGD("Enter");
+
+    AccountExtendedDataCallback* cb =
+        static_cast<AccountExtendedDataCallback *>(data);
+    try {
+        LOGD("key: %s, value: %s", key, value);
+        cb->addData(key, value);
+    } catch (BasePlatformException& err) {
+        cb->setError(err.getName(), err.getMessage());
+        return false;
+    }
+
+    return true;
+}
+
+void *AccountExtendedDataCallback::thread(void *data)
+{
+    LOGD("Enter");
+    AccountExtendedDataCallback *cb =
+        static_cast<AccountExtendedDataCallback *>(data);
+
+    try {
+        int ret = account_get_custom_all(cb->getHandle(), _custom_cb, data);
+        if (ACCOUNT_ERROR_NONE != ret) {
+            LOGE("%d", ret);
+            AccountUtil::throwAccountException(ret,
+                "Failed to get all custom data");
+        }
+
+        if (!g_idle_add(_complete, data)) {
+            LOGE("g_idle addtion failed");
+        }
+    } catch (BasePlatformException& err) {
+        cb->setError(err.getName(), err.getMessage());
+    }
+
+    return NULL;
+}
+
+gboolean AccountExtendedDataCallback::_complete(void *data)
+{
+    LOGD("Enter");
+    AccountExtendedDataCallback *cb =
+        static_cast<AccountExtendedDataCallback *>(data);
+
+    if (cb->hasError()) {
+        cb->onError();
+    } else {
+        try {
+            JSContextRef context = cb->getContext();
+            if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+                LOGE("context was closed");
+                throw UnknownException("context was closed");
+            }
+
+            cb->onSuccess();
+        } catch (BasePlatformException &err) {
+            cb->setError(err.getName(), err.getMessage());
+            cb->onError();
+        } catch (...) {
+            cb->setError(
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Accounts failed");
+            cb->onError();
+        }
+    }
+
+    delete cb;
+    return false;
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/AccountExtendedDataCallback.h b/src/Account/AccountExtendedDataCallback.h
new file mode 100755 (executable)
index 0000000..1ab31ff
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_EXTENDED_DATA_CALLBACK_H__
+#define __TIZEN_ACCOUNT_EXTENDED_DATA_CALLBACK_H__
+
+#include <account.h>
+#include <map>
+#include <glib.h>
+#include <memory>
+
+#include "OperationCallback.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+class AccountExtendedDataCallback;
+
+typedef std::shared_ptr<AccountExtendedDataCallback> AccountExtendedDataCallbackPtr;
+
+class AccountExtendedDataCallback : public OperationCallback
+{
+public:
+    AccountExtendedDataCallback(JSContextRef globalCtx);
+    virtual ~AccountExtendedDataCallback();
+
+    void addData(const std::string &key, const std::string &value);
+    std::map<std::string, std::string> getData();
+
+    account_h getHandle();
+    void setHandle(account_h handle);
+
+    static void* thread(void *data);
+    virtual void onSuccess();
+
+private:
+    std::map<std::string, std::string> m_dataMap;
+    account_h m_handle;
+
+    static bool _custom_cb(char *key, char *value, void *data);
+    static gboolean _complete(void *data);
+};
+
+} // Account
+} // DeviceAPI
+
+#endif
diff --git a/src/Account/AccountManager.cpp b/src/Account/AccountManager.cpp
new file mode 100755 (executable)
index 0000000..5a419cb
--- /dev/null
@@ -0,0 +1,361 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AccountManager.h"
+#include "AccountUtil.h"
+
+#include <sstream>
+
+#include <PlatformException.h>
+#include <glib.h>
+#include <unistd.h>
+#include <app_manager.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Account {
+
+AccountManager::AccountManager():
+    SecurityAccessor(),
+    m_eventListenerCount(0),
+    m_eventListenerHandle(NULL)
+{
+    LOGD("Connect to the account DB.");
+    try {
+        int ret = account_connect();
+        if (ACCOUNT_ERROR_NONE != ret) {
+            LOGE("%d", ret);
+            AccountUtil::throwAccountException(ret, "DB connection failed");
+        }
+    }  catch (BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("Something strange happened");
+    }
+}
+
+AccountManager::~AccountManager()
+{
+    LOGD("Disconnect account DB.");
+    int ret = account_disconnect();
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        LOGE("Failed to disconnect %s",
+            AccountUtil::getAccountErrorMessage(ret).c_str());
+    }
+}
+
+AccountManager& AccountManager::getInstance()
+{
+    static AccountManager manager;
+    return manager;
+}
+
+void AccountManager::add(AccountPtr account)
+{
+    LOGD("Enter");
+
+    std::string packageName = account->getProvider()->getApplicationId();
+    if (!isValidPackage(packageName)) {
+        std::stringstream ss;
+        ss << "The caller application expected to belong to " << packageName;
+        LOGE("%s", ss.str().c_str());
+        throw InvalidAccessException(ss.str().c_str());
+    }
+
+    account->syncHandle();
+    account_h handle = account->getHandle();
+
+    int account_id;
+    int ret = account_insert_to_db(handle, &account_id);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to insert account");
+    }
+
+    account->setId(static_cast<unsigned long>(account_id));
+}
+
+void AccountManager::remove(unsigned long accountId)
+{
+    LOGD("Enter");
+
+    AccountPtr account = getAccount(accountId);
+    std::string packageName = account->getProvider()->getApplicationId();
+    if (!isValidPackage(packageName)) {
+        std::stringstream ss;
+        ss << "The caller application expected to belong to " << packageName;
+        LOGE("%s", ss.str().c_str());
+        throw InvalidAccessException(ss.str().c_str());
+    }
+
+    int ret = account_delete_from_db_by_id(static_cast<int>(accountId));
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to delete account");
+    }
+}
+
+void AccountManager::update(AccountPtr account)
+{
+    LOGD("Enter");
+
+    std::string packageName = account->getProvider()->getApplicationId();
+    if (!isValidPackage(packageName)) {
+        std::stringstream ss;
+        ss << "The caller application expected to belong to " << packageName;
+        LOGE("%s", ss.str().c_str());
+        throw InvalidAccessException(ss.str().c_str());
+    }
+
+    account->syncHandle();
+    account_h handle = account->getHandle();
+
+    int ret = account_update_to_db_by_id(handle, account->getId());
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to update account");
+    }
+}
+
+AccountPtr AccountManager::getAccount(unsigned long accountId)
+{
+    LOGD("Enter");
+
+    account_h handle;
+
+    int ret = account_create(&handle);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to create account handle");
+    }
+
+    ret = account_query_account_by_account_id(static_cast<int>(accountId), &handle);
+    if (ACCOUNT_ERROR_RECORD_NOT_FOUND == ret) {
+        account_destroy(handle);
+
+        std::stringstream ss;
+        ss << "There is no account whose id is " << accountId;
+        AccountUtil::throwAccountException(ret, ss.str());
+    } else if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+
+        account_destroy(handle);
+
+        std::stringstream ss;
+        ss << "Failed to query account by accountId : " << accountId;
+        AccountUtil::throwAccountException(ret, ss.str());
+    }
+
+    AccountPtr account = AccountPtr(new Account(handle));
+    return account;
+}
+
+void AccountManager::getAccounts(std::string applicationId,
+                                 AccountArrayCallback* accountArrayCallback)
+{
+    LOGD("Enter");
+
+    accountArrayCallback->setApplicationId(applicationId);
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, AccountArrayCallback::thread,
+            static_cast<void *>(accountArrayCallback))) {
+        delete accountArrayCallback;
+        LOGE("Failed to create pthread for getAccounts()");
+        throw UnknownException("Failed to create pthread for getAccounts()");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for getAccounts()");
+    }
+}
+
+AccountProviderPtr AccountManager::getProvider(std::string applicationId)
+{
+    LOGD("Enter");
+
+    account_type_h handle;
+    int ret = account_type_create(&handle);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        AccountUtil::throwAccountException(ret, "Failed to create handle");
+    }
+
+    ret = account_type_query_by_app_id(applicationId.c_str(), &handle);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+
+        std::stringstream ss;
+        ss << "Failed to query provider by appId : " << applicationId;
+        AccountUtil::throwAccountException(ret, ss.str());
+    }
+
+    AccountProviderPtr provider =
+        AccountProviderPtr(new AccountProvider(handle));
+
+    ret = account_type_destroy(handle);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to destroy handle");
+    }
+    return provider;
+}
+
+
+void AccountManager::getProviders(
+    AccountProviderArrayCallback* providerArrayCallback,
+    std::string capability)
+{
+    LOGD("Enter");
+
+    providerArrayCallback->setCapability(capability);
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, AccountProviderArrayCallback::thread,
+            static_cast<void *>(providerArrayCallback))) {
+        delete providerArrayCallback;
+        LOGE("Failed to create pthread for getProviders()");
+        throw UnknownException("Failed to create pthread for getProviders()");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for getProviders()");
+    }
+}
+
+unsigned long AccountManager::addAccountListener(
+    AccountChangeCallback* changeCallback)
+{
+    LOGD("Enter");
+
+    int ret;
+    unsigned long listenerId = ++m_eventListenerCount;
+    AccountChangeCallbackPtr cb(changeCallback);
+    std::pair<unsigned long, AccountChangeCallbackPtr> row(listenerId, cb);
+    m_eventListeners.insert(row);
+
+    if (!m_eventListenerHandle) {
+        ret = account_subscribe_create(&m_eventListenerHandle);
+        if (ACCOUNT_ERROR_NONE != ret) {
+            AccountUtil::throwAccountException(ret,
+                "account subscribe create failed");
+        }
+    }
+
+    if (m_eventListeners.size() == 1) {
+        ret = account_subscribe_notification(m_eventListenerHandle,
+            AccountManager::accountChangeCallback, NULL);
+        if (ACCOUNT_ERROR_NONE != ret) {
+            AccountUtil::throwAccountException(ret,
+                "account event subscribe failed");
+        }
+    }
+    return listenerId;
+}
+
+void AccountManager::removeAccountListener(unsigned long listenerId)
+{
+    LOGD("Enter");
+
+    auto it = m_eventListeners.find(listenerId);
+    if (it != m_eventListeners.end()) {
+        m_eventListeners.erase(it);
+
+        if (m_eventListeners.empty()) {
+            int ret = account_unsubscribe_notification(m_eventListenerHandle);
+            m_eventListenerHandle = NULL;
+
+            if (ACCOUNT_ERROR_NONE != ret) {
+                AccountUtil::throwAccountException(ret, "account unsubscribe failed");
+            }
+        }
+    }
+}
+
+bool AccountManager::accountChangeCallback(const char* eventType,
+    int accountId, void *userData)
+{
+    LOGD("Enter %s, %d", eventType, accountId);
+    getInstance().broadcastEvent(eventType, accountId);
+
+    return false;
+}
+
+void AccountManager::broadcastEvent(const char *eventType, int accountId)
+{
+    try {
+        AccountPtr account;
+        AccountEventType t;
+        if (0 == strcmp(ACCOUNT_NOTI_NAME_INSERT, eventType)) {
+            t = INSERT;
+            account = getAccount(static_cast<unsigned long>(accountId));
+        }
+        else if (0 == strcmp(ACCOUNT_NOTI_NAME_DELETE, eventType)) {
+            t = DELETE;
+        }
+        else if (0 == strcmp(ACCOUNT_NOTI_NAME_UPDATE, eventType)) {
+            t = UPDATE;
+            account = getAccount(static_cast<unsigned long>(accountId));
+        } else {
+            LOGW("EventType not found: %s", eventType);
+            return;
+        }
+
+        for (auto it = m_eventListeners.begin(); it != m_eventListeners.end();
+            ++it) {
+            AccountChangeCallbackPtr cb = it->second;
+            cb->setAccount(account);
+            cb->setAccountEventType(t);
+            cb->setAccountId(accountId);
+
+            AccountChangeCallbackPtr* data = new AccountChangeCallbackPtr(cb);
+            if (!g_idle_add(AccountChangeCallback::complete, data)) {
+                LOGE("g_idle addition failed");
+                throw UnknownException("g_idle addition failed");
+            }
+        }
+    } catch (BasePlatformException &err) {
+        LOGE("%s : %s", (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Something strange happened");
+    }
+}
+
+bool AccountManager::isValidPackage(std::string packageName)
+{
+    int pid = getpid();
+    char *app_id = NULL;
+    int ret = app_manager_get_app_id(pid, &app_id);
+    bool isValidPackage = false;
+
+    if (APP_MANAGER_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        free(app_id);
+
+        LOGE("Failed to get appId : %x", ret);
+        throw UnknownException("Failed to get appid");
+    }
+
+    LOGD("provider: %s, caller: %s", packageName.c_str(), app_id);
+    isValidPackage = strcmp(packageName.c_str(), app_id) == 0;
+    free(app_id);
+
+    return isValidPackage;
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/AccountManager.h b/src/Account/AccountManager.h
new file mode 100755 (executable)
index 0000000..81ab79d
--- /dev/null
@@ -0,0 +1,86 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_MANAGER_H__
+#define __TIZEN_ACCOUNT_MANAGER_H__
+
+#include <map>
+#include <mutex>
+
+#include <MultiCallbackUserData.h>
+#include <SecurityAccessor.h>
+#include <account.h>
+
+#include "AccountTypes.h"
+#include "Account.h"
+#include "AccountProvider.h"
+#include "AccountArrayCallback.h"
+#include "AccountProviderArrayCallback.h"
+#include "AccountChangeCallback.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+class AccountManager : public Common::SecurityAccessor
+{
+private:
+    AccountManager();
+    virtual ~AccountManager();
+
+    AccountManager(AccountManager const&) = delete;
+    AccountManager& operator=(AccountManager const&) = delete;
+
+    std::map<unsigned long, AccountChangeCallbackPtr> m_eventListeners;
+    unsigned long m_eventListenerCount;
+    account_subscribe_h m_eventListenerHandle;
+
+    static bool accountChangeCallback(const char* eventType, int accountId, void* userData);
+
+    void broadcastEvent(const char* eventType, int accountId);
+
+    bool isValidPackage(std::string packageName);
+
+public:
+    static AccountManager& getInstance();
+
+    void add(AccountPtr account);
+
+    void remove(unsigned long accountId);
+
+    void update(AccountPtr account);
+
+    AccountPtr getAccount(unsigned long accountId);
+
+    void getAccounts(std::string applicationId,
+                     AccountArrayCallback* accountArrayCallback);
+
+    AccountProviderPtr getProvider(std::string applicationId);
+
+    void getProviders(AccountProviderArrayCallback* providerArrayCallback,
+                      std::string capability);
+
+    unsigned long addAccountListener(AccountChangeCallback* changeCallback);
+
+    void removeAccountListener(unsigned long listenerId);
+};
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_MANAGER_H__
diff --git a/src/Account/AccountProvider.cpp b/src/Account/AccountProvider.cpp
new file mode 100755 (executable)
index 0000000..3f1f727
--- /dev/null
@@ -0,0 +1,179 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AccountProvider.h"
+#include "AccountUtil.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Account {
+
+AccountProvider::AccountProvider():
+    m_applicationId(""),
+    m_displayName(""),
+    m_iconUri(""),
+    m_smallIconUri(""),
+    m_isMultipleAccountSupported(false)
+{
+}
+
+AccountProvider::AccountProvider(account_type_h handle)
+{
+    if(!handle) {
+        LOGE("Invalid provider handle");
+        throw UnknownException("Invalid provider handle");
+    }
+
+    char *tmp = NULL;
+    int ret = account_type_get_app_id(handle, &tmp);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to get appId");
+    }
+    if(NULL != tmp) {
+        m_applicationId = tmp;
+        free(tmp);
+        tmp = NULL;
+    }
+
+    ret = account_type_get_label_by_locale(handle, "default", &tmp);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to get displayName");
+    }
+    if(NULL != tmp) {
+        m_displayName = tmp;
+        free(tmp);
+        tmp = NULL;
+    }
+
+    ret = account_type_get_icon_path(handle, &tmp);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to get iconPath");
+    }
+    if(NULL != tmp) {
+        m_iconUri = tmp;
+        free(tmp);
+        tmp = NULL;
+    }
+
+    ret = account_type_get_small_icon_path(handle, &tmp);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to get smallIconPath");
+    }
+    if(NULL != tmp) {
+        m_smallIconUri = tmp;
+        free(tmp);
+        tmp = NULL;
+    }
+
+    int multipleAccountSupported;
+    ret = account_type_get_multiple_account_support(handle,
+        &multipleAccountSupported);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret,
+            "Failed to get multiple account support");
+    }
+    m_isMultipleAccountSupported = static_cast<bool>(multipleAccountSupported);
+
+    ret = account_type_get_provider_feature_all(handle, featureCb, this);
+    if(ACCOUNT_ERROR_NONE != ret) {
+        LOGE("%d", ret);
+        AccountUtil::throwAccountException(ret, "Failed to get capabilities");
+    }
+}
+
+AccountProvider::~AccountProvider()
+{
+}
+
+std::string AccountProvider::getApplicationId() const
+{
+    return m_applicationId;
+}
+
+void AccountProvider::setApplicationId(std::string applicationId)
+{
+    m_applicationId = applicationId;
+}
+
+std::string AccountProvider::getDisplayName() const
+{
+    return m_displayName;
+}
+
+void AccountProvider::setDisplayName(std::string displayName)
+{
+    m_displayName = displayName;
+}
+
+std::string AccountProvider::getIconUri() const
+{
+    return m_iconUri;
+}
+
+void AccountProvider::setIconUri(std::string iconUri)
+{
+    m_iconUri = iconUri;
+}
+
+std::string AccountProvider::getSmallIconUri() const
+{
+    return m_smallIconUri;
+}
+
+void AccountProvider::setSmallIconUri(std::string smallIconUri)
+{
+    m_smallIconUri = smallIconUri;
+}
+
+std::vector<std::string> AccountProvider::getCapabilities() const
+{
+    return m_capabilities;
+}
+
+void AccountProvider::setCapabilities(std::vector<std::string> capabilities)
+{
+    m_capabilities = capabilities;
+}
+
+bool AccountProvider::getIsMultipleAccountSupported() const
+{
+    return m_isMultipleAccountSupported;
+}
+
+void AccountProvider::setIsMultipleAccountSupported(bool isMultipleAccountSupported)
+{
+    m_isMultipleAccountSupported = isMultipleAccountSupported;
+}
+
+bool AccountProvider::featureCb(char *appId, char *key, void *data)
+{
+    AccountProvider* _this = (AccountProvider *)data;
+    _this->m_capabilities.push_back(std::string(key));
+
+    return true;
+}
+
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/AccountProvider.h b/src/Account/AccountProvider.h
new file mode 100755 (executable)
index 0000000..7c477f5
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_PROVIDER_H__
+#define __TIZEN_ACCOUNT_PROVIDER_H__
+
+#include <MultiCallbackUserData.h>
+#include <account.h>
+
+#include "AccountTypes.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+
+class AccountProvider
+{
+public:
+    AccountProvider();
+    AccountProvider(account_type_h handle);
+    virtual ~AccountProvider();
+
+    std::string getApplicationId() const;
+    void setApplicationId(std::string applicationId);
+
+    std::string getDisplayName() const;
+    void setDisplayName(std::string displayName);
+
+    std::string getIconUri() const;
+    void setIconUri(std::string iconUri);
+
+    std::string getSmallIconUri() const;
+    void setSmallIconUri(std::string smallIconUri);
+
+    std::vector<std::string> getCapabilities() const;
+    void setCapabilities(std::vector<std::string> capabilities);
+
+    bool getIsMultipleAccountSupported() const;
+    void setIsMultipleAccountSupported(bool isMultipleAccountSupported);
+
+private:
+    std::string m_applicationId;
+    std::string m_displayName;
+    std::string m_iconUri;
+    std::string m_smallIconUri;
+    std::vector<std::string> m_capabilities;
+    bool m_isMultipleAccountSupported;
+
+    static bool featureCb(char *appId, char *key, void *data);
+};
+
+typedef std::shared_ptr<AccountProvider> AccountProviderPtr;
+
+struct AccountProviderHolder {
+    AccountProviderPtr ptr;
+};
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_PROVIDER_H__
diff --git a/src/Account/AccountProviderArrayCallback.cpp b/src/Account/AccountProviderArrayCallback.cpp
new file mode 100755 (executable)
index 0000000..7307ea7
--- /dev/null
@@ -0,0 +1,168 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AccountProviderArrayCallback.h"
+#include "AccountUtil.h"
+
+#include <sstream>
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+AccountProviderArrayCallback::AccountProviderArrayCallback(
+    JSContextRef globalCtx):
+    OperationCallback(globalCtx)
+{
+}
+
+AccountProviderArrayCallback::~AccountProviderArrayCallback()
+{
+    m_providerArray.clear();
+}
+
+void AccountProviderArrayCallback::onSuccess()
+{
+    int size = m_providerArray.size();
+    JSContextRef context = getContext();
+
+    JSValueRef rows[size];
+    JSValueRef exception = NULL;
+    for(auto it = m_providerArray.begin(); it != m_providerArray.end(); it++) {
+        JSObjectRef provider = JSObjectMake(context,
+            JSAccountProvider::getClassRef(), NULL);
+        JSAccountProvider::setPrivateObject(provider, *it);
+        rows[std::distance(m_providerArray.begin(), it)] = provider;
+    }
+    JSObjectRef resultArray = JSObjectMakeArray(context, size, rows, &exception);
+    if(exception != NULL) {
+        LOGE("Failed to create JSArray");
+        throw UnknownException("Failed to create JSArray");
+    }
+
+    callSuccessCallback(resultArray);
+}
+
+std::vector<AccountProviderPtr> AccountProviderArrayCallback::getProviderArray()
+{
+    return m_providerArray;
+}
+
+void AccountProviderArrayCallback::addProvider(AccountProviderPtr provider)
+{
+    m_providerArray.push_back(provider);
+}
+
+std::string AccountProviderArrayCallback::getCapability()
+{
+    return m_capability;
+}
+
+void AccountProviderArrayCallback::setCapability(std::string capability)
+{
+    m_capability = capability;
+}
+
+bool AccountProviderArrayCallback::_provider_cb(account_type_h handle,
+                                                       void *data)
+{
+    LOGD("Enter");
+    AccountProviderArrayCallback* cb =
+        static_cast<AccountProviderArrayCallback *>(data);
+    try {
+        AccountProviderPtr provider =
+            AccountProviderPtr(new AccountProvider(handle));
+        cb->addProvider(provider);
+    } catch (BasePlatformException& err) {
+        cb->setError(err.getName(), err.getMessage());
+        return false;
+    }
+    return true;
+}
+
+void *AccountProviderArrayCallback::thread(void *data)
+{
+    LOGD("Enter");
+    AccountProviderArrayCallback* cb =
+        static_cast<AccountProviderArrayCallback *>(data);
+    std::string capability = cb->getCapability();
+    int ret;
+
+    if("" == capability) {
+        ret = account_type_foreach_account_type_from_db(_provider_cb, data);
+    } else {
+        LOGD("capability: %s", capability.c_str());
+        ret = account_type_query_by_provider_feature(_provider_cb,
+            capability.c_str(), data);
+    }
+
+    /* if any account_type is not found, empty array will be returned. */
+    if(ACCOUNT_ERROR_NONE != ret && ACCOUNT_ERROR_RECORD_NOT_FOUND != ret) {
+        std::stringstream ss;
+
+        ss << "Failed to query provider : "
+           << AccountUtil::getAccountErrorMessage(ret);
+        LOGE("%s", ss.str().c_str());
+        cb->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, ss.str());
+    }
+
+    if(!g_idle_add(_complete, data)) {
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+gboolean AccountProviderArrayCallback::_complete(void *data)
+{
+    LOGD("Enter");
+    AccountProviderArrayCallback* cb =
+        static_cast<AccountProviderArrayCallback *>(data);
+
+    if(cb->hasError()) {
+        cb->onError();
+    } else {
+        try {
+            JSContextRef context = cb->getContext();
+            if(!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+                LOGE("context was closed");
+                throw UnknownException("context was closed");
+            }
+
+            cb->onSuccess();
+        } catch (BasePlatformException &err) {
+            cb->setError(err.getName(), err.getMessage());
+            cb->onError();
+        } catch (...) {
+            cb->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Providers failed");
+            cb->onError();
+        }
+    }
+
+    delete cb;
+    return false;
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/AccountProviderArrayCallback.h b/src/Account/AccountProviderArrayCallback.h
new file mode 100755 (executable)
index 0000000..cb7d64b
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_PROVIDER_ARRAY_CALLBACK_H__
+#define __TIZEN_ACCOUNT_PROVIDER_ARRAY_CALLBACK_H__
+
+#include <vector>
+#include <account.h>
+#include <glib.h>
+
+#include "OperationCallback.h"
+#include "JSAccountProvider.h"
+
+namespace DeviceAPI {
+namespace Account {
+
+class AccountProviderArrayCallback : public OperationCallback
+{
+public:
+    AccountProviderArrayCallback(JSContextRef globalCtx);
+    virtual ~AccountProviderArrayCallback();
+
+    std::vector<AccountProviderPtr> getProviderArray();
+    void addProvider(AccountProviderPtr provider);
+
+    std::string getCapability();
+    void setCapability(std::string capability);
+
+    static void *thread(void *data);
+    virtual void onSuccess();
+
+private:
+    std::vector<AccountProviderPtr> m_providerArray;
+    std::string m_capability;
+
+    static bool _provider_cb(account_type_h handle, void *data);
+    static gboolean _complete(void *data);
+};
+
+typedef std::shared_ptr<AccountProviderArrayCallback> AccountProviderArrayCallbackPtr;
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_PROVIDER_ARRAY_CALLBACK_H__
diff --git a/src/Account/AccountTypes.h b/src/Account/AccountTypes.h
new file mode 100755 (executable)
index 0000000..eae288f
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _ACCOUNT_TYPES_H_
+#define _ACCOUNT_TYPES_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace DeviceAPI {
+namespace Account {
+
+// typedef AccountId
+typedef unsigned long AccountId;
+
+} // Account
+} // DeviceAPI
+
+#endif // _ACCOUNT_TYPES_H_
diff --git a/src/Account/AccountUtil.cpp b/src/Account/AccountUtil.cpp
new file mode 100755 (executable)
index 0000000..057c6ab
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AccountUtil.h"
+
+#include <sstream>
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Account {
+
+using namespace DeviceAPI::Common;
+
+void AccountUtil::throwAccountException(const int errorCode,
+                                        const std::string &hint)
+{
+    LOGD("Enter");
+
+    std::stringstream ss;
+    ss << hint << " : " << getAccountErrorMessage(errorCode);
+    LOGE("%s", ss.str().c_str());
+
+    switch(errorCode) {
+        case ACCOUNT_ERROR_RECORD_NOT_FOUND:
+            throw NotFoundException(ss.str().c_str());
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+std::string AccountUtil::getAccountErrorMessage(const int errorCode)
+{
+    switch(errorCode) {
+        case ACCOUNT_ERROR_OUT_OF_MEMORY:
+            return "Out of Memory";
+        case ACCOUNT_ERROR_INVALID_PARAMETER:
+            return "Invalid Parameter";
+        case ACCOUNT_ERROR_DUPLICATED:
+            return "Same user name exists in your application";
+        case ACCOUNT_ERROR_NO_DATA:
+            return "Empty data";
+        case ACCOUNT_ERROR_RECORD_NOT_FOUND:
+            return "Related record does not exist";
+        case ACCOUNT_ERROR_DB_FAILED:
+            return "DB operation failed";
+        case ACCOUNT_ERROR_DB_NOT_OPENED:
+            return "DB is not connected";
+        case ACCOUNT_ERROR_QUERY_SYNTAX_ERROR:
+            return "DB query syntax error";
+        case ACCOUNT_ERROR_ITERATOR_END:
+            return "Iterator has reached the end";
+        case ACCOUNT_ERROR_NOTI_FAILED:
+            return "Notification failed";
+        case ACCOUNT_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case ACCOUNT_ERROR_XML_PARSE_FAILED:
+            return "XML parse failed";
+        case ACCOUNT_ERROR_XML_FILE_NOT_FOUND:
+            return "XML file does not exist";
+        case ACCOUNT_ERROR_EVENT_SUBSCRIPTION_FAIL:
+            return "Subscription failed";
+        case ACCOUNT_ERROR_NOT_REGISTERED_PROVIDER:
+            return "Account provider is not registered";
+        case ACCOUNT_ERROR_NOT_ALLOW_MULTIPLE:
+            return "Multiple accounts are not supported";
+        case ACCOUNT_ERROR_DATABASE_BUSY:
+            return "SQLite busy handler expired";
+        default:
+            return "Unknown Error";
+    }
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/AccountUtil.h b/src/Account/AccountUtil.h
new file mode 100755 (executable)
index 0000000..6b1777a
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_ACCOUNT_UTIL_H_
+#define __TIZEN_ACCOUNT_ACCOUNT_UTIL_H_
+
+#include <string>
+#include <account.h>
+
+namespace DeviceAPI {
+namespace Account {
+
+class AccountUtil {
+public:
+    static void throwAccountException(const int errorCode, const std::string &hint);
+    static std::string getAccountErrorMessage(const int errorCode);
+};
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_ACCOUNT_UTIL_H_
diff --git a/src/Account/CMakeLists.txt b/src/Account/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..ec6bcf6
--- /dev/null
@@ -0,0 +1,61 @@
+SET(TARGET_NAME ${account_target})
+SET(DESTINATION_NAME ${account_dest})
+SET(TARGET_IMPL_NAME ${account_impl})
+
+PKG_CHECK_MODULES(account REQUIRED accounts-svc capi-appfw-application)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${account_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${timeutil_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSAccountProvider.cpp
+    JSAccount.cpp
+    JSAccountManager.cpp
+    JSAccountExtendedData.cpp
+    AccountProvider.cpp
+    Account.cpp
+    AccountExtendedData.cpp
+    AccountManager.cpp
+    AccountArrayCallback.cpp
+    AccountProviderArrayCallback.cpp
+    AccountChangeCallback.cpp
+    AccountExtendedDataCallback.cpp
+    OperationCallback.cpp
+    AccountUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${timeutil_impl}
+    ${account_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/account
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Account/JSAccount.cpp b/src/Account/JSAccount.cpp
new file mode 100755 (executable)
index 0000000..e4a4587
--- /dev/null
@@ -0,0 +1,413 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+
+#include "JSAccount.h"
+#include "JSAccountProvider.h"
+#include "AccountExtendedDataCallback.h"
+#include "AccountManager.h"
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+JSClassDefinition JSAccount::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "Account",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSAccount::m_property[] ={
+    {
+        ACCOUNT_ID,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        ACCOUNT_USER_NAME,
+        getProperty,
+        setProperty,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_ICON_URI,
+        getProperty,
+        setProperty,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_PROVIDER,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    { 0, 0, 0, 0 },
+};
+
+JSStaticFunction JSAccount::m_function[] = {
+    {
+        ACCOUNT_API_GET_EXTENDED_DATA,
+        getExtendedData,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_API_SET_EXTENDED_DATA,
+        setExtendedData,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSAccount::m_jsClassRef = JSClassCreate(JSAccount::getClassInfo());
+
+const JSClassRef JSAccount::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAccount::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSAccount::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        AccountHolder* holder = new AccountHolder();
+        if (!JSObjectSetPrivate(object, static_cast<void*>(holder))) {
+            delete holder;
+        }
+    }
+}
+
+void JSAccount::finalize(JSObjectRef object)
+{
+    AccountHolder *holder = static_cast<AccountHolder*>(JSObjectGetPrivate(object));
+    if (holder) {
+        JSObjectSetPrivate(object, NULL);
+        delete holder;
+        holder = NULL;
+    }
+}
+
+JSObjectRef JSAccount::constructor(JSContextRef context,
+    JSObjectRef constructor,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    AccountPtr priv = AccountPtr(new Account());
+    JSObjectRef obj = JSObjectMake(context, JSAccount::getClassRef(), NULL);
+
+    try {
+        JSObjectRef providerObj =
+            validator.toObject(0, JSAccountProvider::getClassRef());
+        AccountProviderPtr provider =
+            JSAccountProvider::getPrivateObject(context, providerObj);
+        if (!provider) {
+            throw TypeMismatchException("AccountProvider's private object is NULL");
+        }
+        priv->setProvider(provider);
+
+        std::string userName;
+        std::string iconUri;
+
+        if (!validator.isOmitted(1)) {
+            JSObjectRef dict = validator.toObject(1);
+            JSValueRef jsUserName = JSUtil::getProperty(context, dict, "userName");
+            JSValueRef jsIconUri = JSUtil::getProperty(context, dict, "iconUri");
+
+            if(!JSValueIsUndefined(context, jsUserName)) {
+                userName = JSUtil::JSValueToString(context, jsUserName);
+            }
+
+            if(!JSValueIsUndefined(context, jsIconUri)) {
+                iconUri = JSUtil::JSValueToString(context, jsIconUri);
+            }
+        }
+
+        priv->setUserName(userName);
+        priv->setIconUri(iconUri);
+        priv->copyAceCheckAccessFunction(AccountManager::getInstance());
+
+        setPrivateObject(obj, priv);
+    } catch (const BasePlatformException& err) {
+        priv.reset();
+        LOGE("%s, %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        priv.reset();
+        LOGE("Constructor failed");
+    }
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, obj, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    return obj;
+}
+
+AccountPtr JSAccount::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if(!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        throw TypeMismatchException("No proper object");
+    }
+
+    JSValueRef exception = NULL;
+    JSObjectRef object = JSValueToObject(context, value, &exception);
+    if (!object || exception) {
+        throw TypeMismatchException("Wrong object");
+    }
+
+    AccountHolder *holder = static_cast<AccountHolder*>(JSObjectGetPrivate(object));
+    if (!holder) {
+        LOGE("No holder data exist");
+        throw TypeMismatchException("No holder data exist");
+    }
+
+    if (!holder->ptr) {
+        LOGE("No private data exist");
+        throw TypeMismatchException("No private data exist");
+    }
+
+    return holder->ptr;
+}
+
+void JSAccount::setPrivateObject(JSObjectRef object, AccountPtr value)
+{
+    LOGD("Enter");
+    if(!value) {
+        LOGE("Private object is NULL");
+        throw TypeMismatchException("Private object is NULL");
+    }
+
+    AccountHolder *holder = static_cast<AccountHolder *>(JSObjectGetPrivate(object));
+    if(!holder) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    holder->ptr = value;
+    if (!holder->ptr) {
+        throw TypeMismatchException("Account's private object is NULL.");
+    }
+
+    JSObjectSetPrivate(object, static_cast<void*>(holder));
+}
+
+JSObjectRef JSAccount::makeJSObject(JSContextRef context, AccountPtr native)
+{
+    LOGD("Enter");
+
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    AccountHolder *holder = new (std::nothrow) AccountHolder();
+    if (!holder) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    holder->ptr = native;
+    holder->ptr->copyAceCheckAccessFunction(AccountManager::getInstance());
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void *>(holder));
+    if (!obj) {
+        LOGE("Object creation failed");
+        throw UnknownException("Object creation failed");
+    }
+    return obj;
+}
+
+JSValueRef JSAccount::getProperty(JSContextRef context,
+                                  JSObjectRef object,
+                                  JSStringRef propertyName,
+                                  JSValueRef* exception)
+{
+    try {
+        AccountPtr priv = JSAccount::getPrivateObject(context, object);
+        if (JSStringIsEqualToUTF8CString(propertyName, ACCOUNT_ID)) {
+            if (priv->isIdSet()) {
+                return JSUtil::toJSValueRef(context, priv->getId());
+            } else {
+                return JSValueMakeNull(context);
+            }
+        } else if (JSStringIsEqualToUTF8CString(propertyName, ACCOUNT_USER_NAME)) {
+            return JSUtil::toJSValueRef(context, priv->getUserName());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, ACCOUNT_ICON_URI)) {
+            return JSUtil::toJSValueRef(context, priv->getIconUri());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, ACCOUNT_PROVIDER)) {
+            return JSAccountProvider::createJSObject(context, priv->getProvider());
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Getting property is failed %s", err.getMessage().c_str());
+    }
+    return NULL;
+}
+
+bool JSAccount::setProperty(JSContextRef context,
+                            JSObjectRef object,
+                            JSStringRef propertyName,
+                            JSValueRef value,
+                            JSValueRef* exception)
+{
+    try {
+        AccountPtr priv = JSAccount::getPrivateObject(context, object);
+        if(!priv) {
+            LOGE("Private object is not set.");
+            return false;
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, ACCOUNT_USER_NAME)) {
+            std::string userName = JSUtil::JSValueToString(context, value);
+            priv->setUserName(userName);
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, ACCOUNT_ICON_URI)) {
+            std::string iconUri = JSUtil::JSValueToString(context, value);
+            priv->setIconUri(iconUri);
+            return true;
+        }
+    } catch (const DeviceAPI::Common::BasePlatformException& err) {
+        LOGW("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+
+    return false;
+}
+
+JSValueRef JSAccount::setExtendedData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        // Private Object
+        AccountPtr priv = JSAccount::getPrivateObject(context, thisObject);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), ACCOUNT_API_SET_EXTENDED_DATA);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // key
+        std::string key = validator.toString(0);
+
+        // value
+        std::string value = validator.toString(1);
+
+        priv->setExtendedData(key, value);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in Account.setExtendedData().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSAccount::getExtendedData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+
+    try {
+        // Private Object
+        AccountPtr priv = JSAccount::getPrivateObject(context, thisObject);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), ACCOUNT_API_GET_EXTENDED_DATA);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        if (!validator.isOmitted(0) && JSValueIsObject(context, arguments[0])) {
+            JSObjectRef successCallback = validator.toFunction(0);
+            JSObjectRef errorCallback = validator.toFunction(1, true);
+
+            AccountExtendedDataCallback *extendedDataCallback =
+                new AccountExtendedDataCallback(
+                    GlobalContextManager::getInstance()->getGlobalContext(context));
+            extendedDataCallback->setSuccessCallback(successCallback);
+            extendedDataCallback->setErrorCallback(errorCallback);
+            priv->getExtendedData(extendedDataCallback);
+
+            return JSValueMakeUndefined(context);
+        } else {
+            std::string key = validator.toString(0, false);
+            std::string value;
+            try {
+                value = priv->getExtendedData(key);
+            } catch (NotFoundException &err) {
+                return JSValueMakeNull(context);
+            }
+            return JSUtil::toJSValueRef(context, value);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in Account.getExtendedData().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/JSAccount.h b/src/Account/JSAccount.h
new file mode 100755 (executable)
index 0000000..acb9501
--- /dev/null
@@ -0,0 +1,111 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_ACCOUNT_H__
+#define __TIZEN_JS_ACCOUNT_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "Account.h"
+
+namespace DeviceAPI {
+namespace Account {
+
+class JSAccount
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static AccountPtr getPrivateObject(JSContextRef context, JSValueRef value);
+    static void setPrivateObject(JSObjectRef object, AccountPtr priv);
+    static JSObjectRef makeJSObject(JSContextRef context, AccountPtr native);
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef setExtendedData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getExtendedData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+       /**
+       * The callback invoked when getting a property's value.
+       */
+       static JSValueRef getProperty(JSContextRef context,
+               JSObjectRef object,
+               JSStringRef propertyName,
+               JSValueRef* exception);
+
+       /**
+       * The callback invoked when setting a property's value.
+       */
+       static bool setProperty(JSContextRef context,
+               JSObjectRef object,
+               JSStringRef propertyName,
+               JSValueRef value,
+               JSValueRef* exception);
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_JS_ACCOUNT_H__
diff --git a/src/Account/JSAccountExtendedData.cpp b/src/Account/JSAccountExtendedData.cpp
new file mode 100755 (executable)
index 0000000..a831ceb
--- /dev/null
@@ -0,0 +1,177 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+#include "JSAccountExtendedData.h"
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+JSClassDefinition JSAccountExtendedData::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "AccountExtendedData",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSAccountExtendedData::m_property[] = {
+    {
+        ACCOUNT_EXTENDED_DATA_KEY,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        ACCOUNT_EXTENDED_DATA_VALUE,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSAccountExtendedData::m_jsClassRef =
+    JSClassCreate(JSAccountExtendedData::getClassInfo());
+
+const JSClassRef JSAccountExtendedData::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAccountExtendedData::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSAccountExtendedData::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        AccountExtendedDataPtr priv =
+            AccountExtendedDataPtr(new AccountExtendedData());
+        AccountExtendedDataHolder *holder = new AccountExtendedDataHolder();
+        holder->ptr = priv;
+        if (!JSObjectSetPrivate(object, static_cast<void *>(holder))) {
+            delete holder;
+            holder = NULL;
+        }
+    }
+}
+
+void JSAccountExtendedData::finalize(JSObjectRef object)
+{
+    AccountExtendedDataHolder *holder =
+        static_cast<AccountExtendedDataHolder *>(JSObjectGetPrivate(object));
+    if (holder) {
+        JSObjectSetPrivate(object, NULL);
+        delete holder;
+        holder = NULL;
+    }
+}
+
+AccountExtendedDataPtr JSAccountExtendedData::getPrivateObject(
+    JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+    }
+
+    JSValueRef exception = NULL;
+    JSObjectRef object = JSValueToObject(context, value, &exception);
+    if (!object || exception) {
+        throw TypeMismatchException("Wrong object");
+    }
+
+    AccountExtendedDataHolder *holder =
+        static_cast<AccountExtendedDataHolder *>(JSObjectGetPrivate(object));
+    if (!holder) {
+        LOGE("No holder data exist");
+        throw TypeMismatchException("No holder data exist");
+    }
+
+    if (!holder->ptr) {
+        LOGE("No private data exist");
+        throw TypeMismatchException("No private data exist");
+    }
+    return holder->ptr;
+}
+
+void JSAccountExtendedData::setPrivateObject(
+    JSObjectRef object, AccountExtendedDataPtr value)
+{
+    LOGD("Enter");
+
+    AccountExtendedDataHolder *holder = static_cast<AccountExtendedDataHolder *>
+        (JSObjectGetPrivate(object));
+    if (!holder) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+
+    holder->ptr = value;
+    JSObjectSetPrivate(object, static_cast<void *>(holder));
+}
+
+JSValueRef JSAccountExtendedData::getProperty(JSContextRef context,
+                                              JSObjectRef object,
+                                              JSStringRef propertyName,
+                                              JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    try {
+        AccountExtendedDataPtr priv =
+            JSAccountExtendedData::getPrivateObject(context, object);
+        if (JSStringIsEqualToUTF8CString(propertyName,
+                                         ACCOUNT_EXTENDED_DATA_KEY)) {
+            return JSUtil::toJSValueRef(context, priv->getKey());
+        } else if (JSStringIsEqualToUTF8CString(propertyName,
+                                                ACCOUNT_EXTENDED_DATA_VALUE)) {
+            return JSUtil::toJSValueRef(context, priv->getValue());
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Getting property is failed %s", err.getMessage().c_str());
+    }
+    return NULL;
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/JSAccountExtendedData.h b/src/Account/JSAccountExtendedData.h
new file mode 100755 (executable)
index 0000000..6bdbc2b
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_ACCOUNT_EXTENDED_DATA_H__
+#define __TIZEN_JS_ACCOUNT_EXTENDED_DATA_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "AccountExtendedData.h"
+
+namespace DeviceAPI {
+namespace Account {
+
+class JSAccountExtendedData
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static AccountExtendedDataPtr getPrivateObject(JSContextRef context, JSValueRef value);
+    static void setPrivateObject(JSObjectRef object, AccountExtendedDataPtr priv);
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+       /**
+       * The callback invoked when getting a property's value.
+       */
+       static JSValueRef getProperty(JSContextRef context,
+               JSObjectRef object,
+               JSStringRef propertyName,
+               JSValueRef* exception);
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+} // Account
+} // DeviceAPI
+
+#endif
diff --git a/src/Account/JSAccountManager.cpp b/src/Account/JSAccountManager.cpp
new file mode 100755 (executable)
index 0000000..fbc7514
--- /dev/null
@@ -0,0 +1,548 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+#include "JSAccountManager.h"
+#include "JSAccount.h"
+#include "JSAccountProvider.h"
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+JSClassDefinition JSAccountManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "AccountManager",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSAccountManager::m_function[] = {
+    {
+        ACCOUNT_MANAGER_API_ADD,
+        add,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_MANAGER_API_REMOVE,
+        remove,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_MANAGER_API_UPDATE,
+        update,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_MANAGER_API_GET_ACCOUNT,
+        getAccount,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_MANAGER_API_GET_ACCOUNTS,
+        getAccounts,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_MANAGER_API_GET_PROVIDER,
+        getProvider,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_MANAGER_API_GET_PROVIDERS,
+        getProviders,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_MANAGER_API_ADD_ACCOUNT_LISTENER,
+        addAccountListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        ACCOUNT_MANAGER_API_REMOVE_ACCOUNT_LISTENER,
+        removeAccountListener,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSAccountManager::m_jsClassRef =
+    JSClassCreate(JSAccountManager::getClassInfo());
+
+const JSClassRef JSAccountManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAccountManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSAccountManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+    JSObjectSetPrivate(object, static_cast<void *>(&AccountManager::getInstance()));
+}
+
+void JSAccountManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+JSValueRef JSAccountManager::add(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &AccountManager::getInstance(),
+            ACCOUNT_MANAGER_API_ADD);
+
+        // Private Object
+        AccountManager *priv = static_cast<AccountManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // account
+        JSObjectRef accountObj = validator.toObject(0, JSAccount::getClassRef());
+        AccountPtr account = JSAccount::getPrivateObject(context, accountObj);
+        if (!account) {
+            throw TypeMismatchException("Account's private object is NULL.");
+        }
+
+        // perform
+        priv->add(account);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in AccountManager.add().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSAccountManager::remove(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &AccountManager::getInstance(),
+            ACCOUNT_MANAGER_API_REMOVE);
+
+        // Private Object
+        AccountManager *priv = static_cast<AccountManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // accountId
+        unsigned long accountId = validator.toULong(0);
+
+        // perform
+        try {
+            priv->remove(accountId);
+        } catch (BasePlatformException &err) {
+            LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        }
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in AccountManager.remove().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSAccountManager::update(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &AccountManager::getInstance(),
+            ACCOUNT_MANAGER_API_UPDATE);
+
+        // Private Object
+        AccountManager *priv = static_cast<AccountManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // account
+        JSObjectRef accountObj = validator.toObject(0, JSAccount::getClassRef());
+        AccountPtr account = JSAccount::getPrivateObject(context, accountObj);
+        if (!account) {
+            throw TypeMismatchException("Account's private object is NULL.");
+        }
+
+        // perform
+        priv->update(account);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in AccountManager.update().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSAccountManager::getAccount(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &AccountManager::getInstance(),
+            ACCOUNT_MANAGER_API_GET_ACCOUNT);
+
+        // Private Object
+        AccountManager *priv = static_cast<AccountManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // accountId
+        unsigned long accountId = validator.toULong(0, false);
+
+        // perform
+        try {
+            AccountPtr ret = priv->getAccount(accountId);
+            return JSAccount::makeJSObject(context, ret);
+        } catch (...) {
+            LOGE("Error during get account, so return null");
+            return JSValueMakeNull(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in AccountManager.get().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSAccountManager::getAccounts(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &AccountManager::getInstance(),
+            ACCOUNT_MANAGER_API_GET_ACCOUNTS);
+
+        // Private Object
+        AccountManager *priv = static_cast<AccountManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(0);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);
+
+        // applicationId
+        std::string applicationId = validator.toString(2, true);
+
+        AccountArrayCallback *accountArrayCallback =
+            new AccountArrayCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        accountArrayCallback->setSuccessCallback(successCallback);
+        accountArrayCallback->setErrorCallback(errorCallback);
+
+        // perform
+        priv->getAccounts(applicationId, accountArrayCallback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in AccountManager.getAccounts().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSAccountManager::getProvider(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &AccountManager::getInstance(),
+            ACCOUNT_MANAGER_API_GET_PROVIDER);
+
+        // Private Object
+        AccountManager *priv = static_cast<AccountManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // applicationId
+        std::string applicationId = validator.toString(0);
+
+        // perform
+        try {
+            AccountProviderPtr ret = priv->getProvider(applicationId);
+            return JSAccountProvider::createJSObject(context, ret);
+        } catch (...) {
+            LOGE("Error during get provider, so return null");
+            return JSValueMakeNull(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in AccountManager.getProvider().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSAccountManager::getProviders(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &AccountManager::getInstance(),
+            ACCOUNT_MANAGER_API_GET_PROVIDERS);
+
+        // Private Object
+        AccountManager *priv = static_cast<AccountManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(0);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);
+
+        // capability
+        std::string capability = validator.toString(2, true);
+
+        AccountProviderArrayCallback *providerArrayCallback =
+            new AccountProviderArrayCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        providerArrayCallback->setSuccessCallback(successCallback);
+        providerArrayCallback->setErrorCallback(errorCallback);
+
+        // perform
+        priv->getProviders(providerArrayCallback, capability);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in AccountManager.getProviders().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSAccountManager::addAccountListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &AccountManager::getInstance(),
+            ACCOUNT_MANAGER_API_ADD_ACCOUNT_LISTENER);
+
+        // Private Object
+        AccountManager *priv = static_cast<AccountManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // callback
+        JSObjectRef callbackObj = validator.toCallbackObject(0, false, "onadded",
+            "onremoved", "onupdated", NULL);
+        JSValueRef onadded = JSUtil::getProperty(context, callbackObj, "onadded");
+        JSValueRef onremoved = JSUtil::getProperty(context, callbackObj, "onremoved");
+        JSValueRef onupdated = JSUtil::getProperty(context, callbackObj, "onupdated");
+
+        JSObjectRef addedCallback = NULL;
+        if(!JSValueIsUndefined(context, onadded)) {
+            addedCallback = JSUtil::JSValueToObject(context, onadded);
+        }
+
+        JSObjectRef removedCallback = NULL;
+        if(!JSValueIsUndefined(context, onremoved)) {
+            removedCallback = JSUtil::JSValueToObject(context, onremoved);
+        }
+
+        JSObjectRef updatedCallback = NULL;
+        if(!JSValueIsUndefined(context, onupdated)) {
+            updatedCallback = JSUtil::JSValueToObject(context, onupdated);
+        }
+
+        AccountChangeCallback *changeCallback =
+            new AccountChangeCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context),
+                addedCallback,
+                removedCallback,
+                updatedCallback);
+
+        // perform
+        unsigned long ret = priv->addAccountListener(changeCallback);
+
+        return JSUtil::toJSValueRef(context, ret);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in AccountManager.addAccountListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSAccountManager::removeAccountListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &AccountManager::getInstance(),
+            ACCOUNT_MANAGER_API_REMOVE_ACCOUNT_LISTENER);
+
+        // Private Object
+        AccountManager *priv = static_cast<AccountManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // accountListenerId
+        unsigned long accountListenerId = validator.toULong(0);
+
+        // perform
+        priv->removeAccountListener(accountListenerId);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in AccountManager.removeAccountListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/JSAccountManager.h b/src/Account/JSAccountManager.h
new file mode 100755 (executable)
index 0000000..335caba
--- /dev/null
@@ -0,0 +1,135 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_ACCOUNT_MANAGER_H__
+#define __TIZEN_JS_ACCOUNT_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "AccountManager.h"
+
+namespace DeviceAPI {
+namespace Account {
+
+class JSAccountManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef add(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef remove(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef update(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getAccount(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getAccounts(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getProvider(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getProviders(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addAccountListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeAccountListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_JS_ACCOUNT_MANAGER_H__
diff --git a/src/Account/JSAccountProvider.cpp b/src/Account/JSAccountProvider.cpp
new file mode 100755 (executable)
index 0000000..2ccd61d
--- /dev/null
@@ -0,0 +1,233 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+#include "JSAccountProvider.h"
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+JSClassDefinition JSAccountProvider::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "AccountProvider",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSAccountProvider::m_property[] = {
+    {
+        ACCOUNT_PROVIDER_APPLICATION_ID,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        ACCOUNT_PROVIDER_DISPLAY_NAME,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        ACCOUNT_PROVIDER_ICON_URI,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        ACCOUNT_PROVIDER_SMALL_ICON_URI,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        ACCOUNT_PROVIDER_CAPABILITIES,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        ACCOUNT_PROVIDER_IS_MULTIPLE_ACCOUNT_SUPPORTED,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {0, 0, 0, 0}
+};
+
+JSClassRef JSAccountProvider::m_jsClassRef =
+    JSClassCreate(JSAccountProvider::getClassInfo());
+
+const JSClassRef JSAccountProvider::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAccountProvider::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSAccountProvider::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        AccountProviderHolder* holder = new AccountProviderHolder();
+        if (!JSObjectSetPrivate(object, static_cast<void*>(holder))) {
+            delete holder;
+        }
+    }
+}
+
+void JSAccountProvider::finalize(JSObjectRef object)
+{
+    AccountProviderHolder *holder =
+        static_cast<AccountProviderHolder*>(JSObjectGetPrivate(object));
+    if (holder) {
+        JSObjectSetPrivate(object, NULL);
+        delete holder;
+    }
+}
+
+JSValueRef JSAccountProvider::createJSObject(JSContextRef ctx,
+                                             const AccountProviderPtr value)
+{
+    if(!value) {
+        LOGE("Private object is NULL.");
+        throw TypeMismatchException("Private object is NULL.");
+    }
+    JSObjectRef target = JSObjectMake(ctx, getClassRef(), NULL);
+
+    AccountProviderHolder *holder = new AccountProviderHolder();
+    if (!holder) {
+        LOGE("Can not allocate memory.");
+        throw UnknownException("Can not allocate memory");
+    }
+    holder->ptr = value;
+    JSObjectSetPrivate(target, static_cast<void*>(holder));
+
+    return target;
+}
+
+AccountProviderPtr JSAccountProvider::getPrivateObject(
+    JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        throw TypeMismatchException("No proper object");
+    }
+
+    JSValueRef exception = NULL;
+    JSObjectRef object = JSValueToObject(context, value, &exception);
+    if (!object || exception) {
+        throw TypeMismatchException("Wrong object");
+    }
+
+    AccountProviderHolder *priv =
+        static_cast<AccountProviderHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("No holder data exist");
+        throw TypeMismatchException("No holder data exist");
+    }
+
+    if (!priv->ptr) {
+        LOGE("No private data exist");
+        throw TypeMismatchException("No private data exist");
+    }
+
+    return priv->ptr;
+}
+
+void JSAccountProvider::setPrivateObject(JSObjectRef object,
+                                                AccountProviderPtr value)
+{
+    LOGD("Enter");
+    AccountProviderHolder *holder =
+        static_cast<AccountProviderHolder *>(JSObjectGetPrivate(object));
+    if(!holder) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    };
+    holder->ptr = value;
+}
+
+JSValueRef JSAccountProvider::getProperty(JSContextRef context,
+                                                 JSObjectRef object,
+                                                 JSStringRef propertyName,
+                                                 JSValueRef* exception)
+{
+    try {
+        AccountProviderPtr priv =
+            JSAccountProvider::getPrivateObject(context, object);
+
+        if (JSStringIsEqualToUTF8CString(propertyName,
+                                         ACCOUNT_PROVIDER_APPLICATION_ID)) {
+            return JSUtil::toJSValueRef(context, priv->getApplicationId());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+                                              ACCOUNT_PROVIDER_DISPLAY_NAME)) {
+            return JSUtil::toJSValueRef(context, priv->getDisplayName());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+                                              ACCOUNT_PROVIDER_ICON_URI)) {
+            return JSUtil::toJSValueRef(context, priv->getIconUri());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+                                              ACCOUNT_PROVIDER_SMALL_ICON_URI)) {
+            return JSUtil::toJSValueRef(context, priv->getSmallIconUri());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+                                              ACCOUNT_PROVIDER_CAPABILITIES)) {
+            return JSUtil::toJSValueRef(context, priv->getCapabilities());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+                                              ACCOUNT_PROVIDER_IS_MULTIPLE_ACCOUNT_SUPPORTED)) {
+            return JSUtil::toJSValueRef(context, priv->getIsMultipleAccountSupported());
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Getting property is failed %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/JSAccountProvider.h b/src/Account/JSAccountProvider.h
new file mode 100755 (executable)
index 0000000..afe777a
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_ACCOUNT_PROVIDER_H__
+#define __TIZEN_JS_ACCOUNT_PROVIDER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "AccountProvider.h"
+
+namespace DeviceAPI {
+namespace Account {
+
+class JSAccountProvider
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static JSValueRef createJSObject(JSContextRef context,
+                                     const AccountProviderPtr value);
+    static AccountProviderPtr getPrivateObject(JSContextRef context,
+                                                      JSValueRef value);
+    static void setPrivateObject(JSObjectRef object,
+                                 AccountProviderPtr value);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    static JSValueRef getProperty(JSContextRef context,
+                                  JSObjectRef object,
+                                  JSStringRef propertyName,
+                                  JSValueRef* exception);
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_JS_ACCOUNT_PROVIDER_H__
diff --git a/src/Account/OperationCallback.cpp b/src/Account/OperationCallback.cpp
new file mode 100755 (executable)
index 0000000..b5834d8
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "OperationCallback.h"
+
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+OperationCallback::OperationCallback(JSContextRef global_ctx):
+    CallbackUserData(global_ctx),
+    m_isError(false),
+    m_errorName(""),
+    m_errorMessage("")
+{
+}
+
+OperationCallback::~OperationCallback()
+{
+}
+
+bool OperationCallback::hasError()
+{
+    return m_isError;
+}
+
+void OperationCallback::setError(const std::string &name, const std::string &msg)
+{
+    m_isError = true;
+    m_errorName = name;
+    m_errorMessage = msg;
+}
+
+void OperationCallback::onSuccess()
+{
+    LOGD("Enter");
+
+    callSuccessCallback();
+}
+
+void OperationCallback::onError()
+{
+    LOGD("Enter");
+
+    JSContextRef context = getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context,
+        m_errorName, m_errorMessage);
+    callErrorCallback(error);
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/OperationCallback.h b/src/Account/OperationCallback.h
new file mode 100755 (executable)
index 0000000..48b7255
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_OPERATION_CALLBACK_H__
+#define __TIZEN_ACCOUNT_OPERATION_CALLBACK_H__
+
+#include <string>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CallbackUserData.h>
+#include <JSWebAPIError.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+class OperationCallback: public CallbackUserData
+{
+public:
+    OperationCallback(JSContextRef global_ctx);
+    virtual ~OperationCallback();
+
+    bool hasError();
+    void setError(const std::string &name, const std::string &msg);
+
+    virtual void onSuccess();
+    virtual void onError();
+private:
+    bool m_isError;
+    std::string m_errorName;
+    std::string m_errorMessage;
+};
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_OPERATION_CALLBACK_H__
diff --git a/src/Account/config.xml b/src/Account/config.xml
new file mode 100755 (executable)
index 0000000..6ff763b
--- /dev/null
@@ -0,0 +1,20 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-account.so</library-name>
+    <feature-install-uri>account.install.uri</feature-install-uri>
+    <feature-key-cn>SAMSUNG plugin group</feature-key-cn>
+    <feature-root-cn>SAMSUNG certificate authority</feature-root-cn>
+    <feature-root-fingerprint>AAAABBBBCCCCDDDEEEE0000</feature-root-fingerprint>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/account.write</name>
+        <device-capability>account.write</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/account.read</name>
+        <device-capability>account.read</device-capability>
+    </api-feature>
+
+</plugin-properties>
\ No newline at end of file
diff --git a/src/Account/plugin_config.cpp b/src/Account/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..1473a92
--- /dev/null
@@ -0,0 +1,196 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+
+#include <map>
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <Logger.h>
+
+#define ACCOUNT_FEATURE_API_READ    "http://tizen.org/privilege/account.read"
+#define ACCOUNT_FEATURE_API_WRITE   "http://tizen.org/privilege/account.write"
+
+#define ACCOUNT_DEVICE_CAP_READ     "account.read"
+#define ACCOUNT_DEVICE_CAP_WRITE    "account.write"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Account {
+
+static FunctionMapping createAccountFunctions();
+static FunctionMapping AccountFunctions = createAccountFunctions();
+
+DEFINE_FUNCTION_GETTER(Account, AccountFunctions);
+
+static FunctionMapping createAccountFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_ACCOUNT_READ, ACCOUNT_DEVICE_CAP_READ);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_ACCOUNT_WRITE, ACCOUNT_DEVICE_CAP_WRITE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_ACCOUNT_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_ACCOUNT_READ, DEVICE_CAP_ACCOUNT_READ);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_ACCOUNT_WRITE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_ACCOUNT_WRITE, DEVICE_CAP_ACCOUNT_WRITE);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_ACCOUNT_READ, ACCOUNT_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_ACCOUNT_WRITE, ACCOUNT_FEATURE_API_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(ACCOUNT_FEATURES_ACCOUNT_READ);
+    ACE_ADD_API_FEATURE(ACCOUNT_FEATURES_ACCOUNT_READ, FEATURE_ACCOUNT_READ);
+
+    ACE_CREATE_FEATURE_LIST(ACCOUNT_FEATURES_ACCOUNT_WRITE);
+    ACE_ADD_API_FEATURE(ACCOUNT_FEATURES_ACCOUNT_WRITE, FEATURE_ACCOUNT_WRITE);
+
+    FunctionMapping accountMapping;
+
+    // Account.setExtendedData
+    AceFunction accountSetExtendedDataFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_SET_EXTENDED_DATA,
+        ACCOUNT_API_SET_EXTENDED_DATA,
+        ACCOUNT_FEATURES_ACCOUNT_WRITE,
+        DEVICE_LIST_ACCOUNT_WRITE);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_API_SET_EXTENDED_DATA,
+        accountSetExtendedDataFunc));
+
+    // Account.getExtendedData
+    AceFunction accountGetExtendedDataFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_GET_EXTENDED_DATA,
+        ACCOUNT_API_GET_EXTENDED_DATA,
+        ACCOUNT_FEATURES_ACCOUNT_READ,
+        DEVICE_LIST_ACCOUNT_READ);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_API_GET_EXTENDED_DATA,
+        accountGetExtendedDataFunc));
+
+    // AccountManager.add
+    AceFunction accountManagerAddFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_MANAGER_ADD,
+        ACCOUNT_MANAGER_API_ADD,
+        ACCOUNT_FEATURES_ACCOUNT_WRITE,
+        DEVICE_LIST_ACCOUNT_WRITE);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_MANAGER_API_ADD,
+        accountManagerAddFunc));
+
+    // AccountManager.remove
+    AceFunction accountManagerRemoveFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_MANAGER_REMOVE,
+        ACCOUNT_MANAGER_API_REMOVE,
+        ACCOUNT_FEATURES_ACCOUNT_WRITE,
+        DEVICE_LIST_ACCOUNT_WRITE);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_MANAGER_API_REMOVE,
+        accountManagerRemoveFunc));
+
+    // AccountManager.update
+    AceFunction accountManagerUpdateFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_MANAGER_UPDATE,
+        ACCOUNT_MANAGER_API_UPDATE,
+        ACCOUNT_FEATURES_ACCOUNT_WRITE,
+        DEVICE_LIST_ACCOUNT_WRITE);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_MANAGER_API_UPDATE,
+        accountManagerUpdateFunc));
+
+    // AccountManager.getAccount
+    AceFunction accountManagerGetAccountFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_MANAGER_GET_ACCOUNT,
+        ACCOUNT_MANAGER_API_GET_ACCOUNT,
+        ACCOUNT_FEATURES_ACCOUNT_READ,
+        DEVICE_LIST_ACCOUNT_READ);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_MANAGER_API_GET_ACCOUNT,
+        accountManagerGetAccountFunc));
+
+    // AccountManager.getAccounts
+    AceFunction accountManagerGetAccountsFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_MANAGER_GET_ACCOUNTS,
+        ACCOUNT_MANAGER_API_GET_ACCOUNTS,
+        ACCOUNT_FEATURES_ACCOUNT_READ,
+        DEVICE_LIST_ACCOUNT_READ);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_MANAGER_API_GET_ACCOUNTS,
+        accountManagerGetAccountsFunc));
+
+    // AccountManager.getProvider
+    AceFunction accountManagerGetProviderFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_MANAGER_GET_PROVIDER,
+        ACCOUNT_MANAGER_API_GET_PROVIDER,
+        ACCOUNT_FEATURES_ACCOUNT_READ,
+        DEVICE_LIST_ACCOUNT_READ);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_MANAGER_API_GET_PROVIDER,
+        accountManagerGetProviderFunc));
+
+    // AccountManager.getProviders
+    AceFunction accountManagerGetProvidersFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_MANAGER_GET_PROVIDERS,
+        ACCOUNT_MANAGER_API_GET_PROVIDERS,
+        ACCOUNT_FEATURES_ACCOUNT_READ,
+        DEVICE_LIST_ACCOUNT_READ);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_MANAGER_API_GET_PROVIDERS,
+        accountManagerGetProvidersFunc));
+
+    // AccountManager.addAccountListener
+    AceFunction accountManagerAddAccountListenerFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_MANAGER_ADD_ACCOUNT_LISTENER,
+        ACCOUNT_MANAGER_API_ADD_ACCOUNT_LISTENER,
+        ACCOUNT_FEATURES_ACCOUNT_READ,
+        DEVICE_LIST_ACCOUNT_READ);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_MANAGER_API_ADD_ACCOUNT_LISTENER,
+        accountManagerAddAccountListenerFunc));
+
+    // AccountManager.removeAccountListener
+    AceFunction accountManagerRemoveAccountListenerFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_ACCOUNT_MANAGER_REMOVE_ACCOUNT_LISTENER,
+        ACCOUNT_MANAGER_API_REMOVE_ACCOUNT_LISTENER,
+        ACCOUNT_FEATURES_ACCOUNT_READ,
+        DEVICE_LIST_ACCOUNT_READ);
+
+    accountMapping.insert(std::make_pair(
+        ACCOUNT_MANAGER_API_REMOVE_ACCOUNT_LISTENER,
+        accountManagerRemoveAccountListenerFunc));
+
+    return accountMapping;
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Account/plugin_config.h b/src/Account/plugin_config.h
new file mode 100755 (executable)
index 0000000..8b73ea3
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ACCOUNT_PLUGIN_CONFIG_H_
+#define _ACCOUNT_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Account {
+
+// attributes
+#define ACCOUNT_PROVIDER_APPLICATION_ID "applicationId"
+#define ACCOUNT_PROVIDER_DISPLAY_NAME "displayName"
+#define ACCOUNT_PROVIDER_ICON_URI "iconUri"
+#define ACCOUNT_PROVIDER_SMALL_ICON_URI "smallIconUri"
+#define ACCOUNT_PROVIDER_CAPABILITIES "capabilities"
+#define ACCOUNT_PROVIDER_IS_MULTIPLE_ACCOUNT_SUPPORTED "isMultipleAccountSupported"
+#define ACCOUNT_ID "id"
+#define ACCOUNT_USER_NAME "userName"
+#define ACCOUNT_ICON_URI "iconUri"
+#define ACCOUNT_PROVIDER "provider"
+#define ACCOUNT_EXTENDED_DATA_KEY "key"
+#define ACCOUNT_EXTENDED_DATA_VALUE "value"
+
+// functions
+#define ACCOUNT_API_SET_EXTENDED_DATA "setExtendedData"
+#define ACCOUNT_API_GET_EXTENDED_DATA "getExtendedData"
+#define ACCOUNT_MANAGER_API_ADD "add"
+#define ACCOUNT_MANAGER_API_REMOVE "remove"
+#define ACCOUNT_MANAGER_API_UPDATE "update"
+#define ACCOUNT_MANAGER_API_GET_ACCOUNT "getAccount"
+#define ACCOUNT_MANAGER_API_GET_ACCOUNTS "getAccounts"
+#define ACCOUNT_MANAGER_API_GET_PROVIDER "getProvider"
+#define ACCOUNT_MANAGER_API_GET_PROVIDERS "getProviders"
+#define ACCOUNT_MANAGER_API_ADD_ACCOUNT_LISTENER "addAccountListener"
+#define ACCOUNT_MANAGER_API_REMOVE_ACCOUNT_LISTENER "removeAccountListener"
+
+DECLARE_FUNCTION_GETTER(Account);
+
+#define ACCOUNT_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getAccountFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _ACCOUNT_PLUGIN_CONFIG_H_
diff --git a/src/Account/plugin_initializer.cpp b/src/Account/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..34d4dc5
--- /dev/null
@@ -0,0 +1,124 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSAccount.h"
+#include "JSAccountManager.h"
+#include "plugin_config.h"
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Account {
+
+AceSecurityStatus accountAceCheckAccessFunction(const char* functionName)
+{
+    return ACCOUNT_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerAccountSetter,
+        SecurityAccessor,
+        gSecurityAccessor);
+
+class_definition_options_t ConstructorClassOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL,
+    NULL,
+    NULL
+};
+
+class_definition_options_t ClassOptions =
+{
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerAccountSetter,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Account] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, accountAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Account] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "Account";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char *>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Account] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Account] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "Account",
+        (js_class_template_getter)JSAccount::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSAccount::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "account",
+        (js_class_template_getter)JSAccountManager::getClassRef,
+        &ClassOptions)
+PLUGIN_CLASS_MAP_END
+
+} // Account
+} // DeviceAPI
diff --git a/src/Alarm/AlarmAbsolute.cpp b/src/Alarm/AlarmAbsolute.cpp
new file mode 100755 (executable)
index 0000000..a42a794
--- /dev/null
@@ -0,0 +1,181 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <Logger.h>
+
+#include "AlarmAbsolute.h"
+#include "AlarmUtil.h"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+AlarmAbsolute::AlarmAbsolute()
+{
+    LOGD("Entered");
+
+    int ret = 0;
+    m_isRecurrence = false;
+
+    ret = app_control_create(&m_app_control_handle);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to create app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    ret = app_control_add_extra_data(m_app_control_handle, ALARM_TYPE_KEY, ALARM_TYPE_ABSOLUTE_VALUE);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to add extra data, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    ret = app_control_add_extra_data(m_app_control_handle, ALARM_ALSOLUTE_RECURRENCE_TYPE_KEY, ALARM_ALSOLUTE_RECURRENCE_TYPE_NONE);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to add extra data, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    m_recurrenceType = AbsoluteRecurrence::NoRecurrence;
+    m_id = -1;
+    m_interval = -1;
+    is_registered = false;
+}
+
+AlarmAbsolute::AlarmAbsolute(app_control_h handle)
+{
+    LOGD("Entered");
+
+    int ret = app_control_clone(&m_app_control_handle, handle);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to copy app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    m_id = -1;
+    m_interval = -1;
+    is_registered = false;
+}
+
+AlarmAbsolute::~AlarmAbsolute()
+{
+    LOGD("Entered");
+
+    int ret = app_control_destroy(m_app_control_handle);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to destory app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+}
+
+int AlarmAbsolute::getId() const
+{
+    return m_id;
+}
+
+void AlarmAbsolute::setId(const int id)
+{
+    m_id = id;
+    is_registered = true;
+}
+
+bool AlarmAbsolute::isRecurrence()
+{
+    return m_isRecurrence;
+}
+
+void AlarmAbsolute::setIsRecurrence(bool value)
+{
+    m_isRecurrence = value;
+}
+
+void AlarmAbsolute::setDate(struct tm date)
+{
+    LOGD("Entered");
+
+    char strDate[19];
+    int ret = 0;
+    m_date = date;
+
+    snprintf(strDate, sizeof(strDate),  "%d %d %d %d %d %d %d",m_date.tm_year, m_date.tm_mon,
+                m_date.tm_mday,  m_date.tm_hour, m_date.tm_min,  m_date.tm_sec, m_date.tm_isdst);
+
+    LOGI("strDate : %s", strDate);
+    ret = app_control_add_extra_data(m_app_control_handle, ALARM_ALSOLUTE_DATE_KEY, strDate);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to add extra data, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    LOGI("AlarmAbsolute Date  = Sec : %d, Min : %d, Hour : %d, Day : %d, MON : %d, Year : %d, Is DST? %d",
+            m_date.tm_sec, m_date.tm_min, m_date.tm_hour, m_date.tm_mday, m_date.tm_mon, m_date.tm_year, m_date.tm_isdst);
+
+
+}
+
+struct tm AlarmAbsolute::getDate()
+{
+    return m_date;
+}
+
+void AlarmAbsolute::setInterval(int interval)
+{
+    LOGD("Entered");
+
+    int ret = 0;
+    m_interval = interval;
+    m_recurrenceType = AbsoluteRecurrence::Interval;
+
+    ret = app_control_add_extra_data(m_app_control_handle, ALARM_ALSOLUTE_RECURRENCE_TYPE_KEY, ALARM_ALSOLUTE_RECURRENCE_TYPE_INTERVAL);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to add extra data, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+}
+
+int AlarmAbsolute::getInterval()
+{
+    return m_interval;
+}
+
+void AlarmAbsolute::setByDayRecurrence(std::vector<std::string> &daysOfTheWeek)
+{
+    LOGD("Entered");
+
+    int ret = 0;
+    m_recurrenceType = AbsoluteRecurrence::ByDayValue;
+    m_daysOfTheWeek = daysOfTheWeek;
+
+    ret = app_control_add_extra_data(m_app_control_handle, ALARM_ALSOLUTE_RECURRENCE_TYPE_KEY, ALARM_ALSOLUTE_RECURRENCE_TYPE_BYDAYVALUE);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to add extra data, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+}
+
+std::vector<std::string> AlarmAbsolute::getByDayRecurrence()
+{
+    return m_daysOfTheWeek;
+}
+
+AbsoluteRecurrence::Type AlarmAbsolute::getRecurrenceType()
+{
+    return m_recurrenceType;
+}
+
+app_control_h AlarmAbsolute::getService()
+{
+    return m_app_control_handle;
+}
+
+} //Alarm
+} //DeviceAPI
+
diff --git a/src/Alarm/AlarmAbsolute.h b/src/Alarm/AlarmAbsolute.h
new file mode 100755 (executable)
index 0000000..570d17a
--- /dev/null
@@ -0,0 +1,74 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_API_ALARMABSOLUTE_H_
+#define TIZENAPIS_API_ALARMABSOLUTE_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <time.h>
+#include <app.h>
+
+#include "alarm_common.h"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+class AlarmAbsolute;
+typedef std::shared_ptr<AlarmAbsolute> AlarmAbsolutePtr;
+
+typedef std::vector<AlarmAbsolutePtr> AlarmAbsoluteArrayPtr;
+
+class AlarmAbsolute
+{
+  public:
+    AlarmAbsolute();
+    AlarmAbsolute(app_control_h handle);
+    ~AlarmAbsolute();
+    int getId() const;
+    void setId(const int id);
+    void setDate(struct tm date);
+    struct tm getDate();
+    void setInterval(int interval);
+    int getInterval();
+    bool isRecurrence();
+    void setIsRecurrence(bool value);
+    void setByDayRecurrence(std::vector<std::string> &daysOfTheWeek);
+    std::vector<std::string> getByDayRecurrence();
+    AbsoluteRecurrence::Type getRecurrenceType();
+    app_control_h getService();
+
+  public:
+    bool is_registered;
+
+  private:
+    int m_id;
+    struct tm m_date;
+    bool m_isRecurrence;
+    int m_interval;
+    app_control_h m_app_control_handle;
+    std::vector<std::string> m_daysOfTheWeek;
+    AbsoluteRecurrence::Type m_recurrenceType;
+
+};
+
+}
+}
+
+#endif
diff --git a/src/Alarm/AlarmConverter.cpp b/src/Alarm/AlarmConverter.cpp
new file mode 100755 (executable)
index 0000000..a9eb6d6
--- /dev/null
@@ -0,0 +1,312 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <vector>
+#include <time.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/JSDOMExceptionFactory.h>
+#include <Logger.h>
+#include <app_alarm.h>
+
+#include "AlarmConverter.h"
+#include "JSAlarmAbsolute.h"
+#include "AlarmAbsolute.h"
+#include "JSAlarmRelative.h"
+#include "AlarmRelative.h"
+#include "AlarmUtil.h"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+AlarmConverter::AlarmConverter(JSContextRef context) : WrtDeviceApis::CommonsJavaScript::Converter(context)
+{
+    LOGD("Entered");
+}
+
+AlarmConverter::~AlarmConverter()
+{
+    LOGD("Entered");
+}
+
+int AlarmConverter::toNativeAlarmValue(std::vector<std::string> daysOfTheWeek)
+{
+    LOGD("Entered");
+
+    int nativeValue = 0;
+
+    for (unsigned int i=0; i<daysOfTheWeek.size(); i++ ) {
+        if (daysOfTheWeek[i]=="SU")
+            nativeValue = nativeValue | ALARM_WEEK_FLAG_SUNDAY;
+        else if (daysOfTheWeek[i]=="MO")
+            nativeValue = nativeValue | ALARM_WEEK_FLAG_MONDAY ;
+        else if (daysOfTheWeek[i]=="TU")
+            nativeValue = nativeValue | ALARM_WEEK_FLAG_TUESDAY ;
+        else if (daysOfTheWeek[i]=="WE")
+            nativeValue = nativeValue | ALARM_WEEK_FLAG_WEDNESDAY;
+        else if (daysOfTheWeek[i]=="TH")
+            nativeValue = nativeValue | ALARM_WEEK_FLAG_THURSDAY ;
+        else if (daysOfTheWeek[i]=="FR")
+            nativeValue = nativeValue | ALARM_WEEK_FLAG_FRIDAY ;
+        else if (daysOfTheWeek[i]=="SA")
+            nativeValue = nativeValue | ALARM_WEEK_FLAG_SATURDAY ;
+    }
+    return nativeValue;
+}
+
+std::vector<std::string> AlarmConverter::convertFlagToDaysOfTheWeek(int byDayValue)
+{
+    LOGD("Entered");
+
+    std::vector<std::string> daysOfTheWeek;
+
+    if (byDayValue & ALARM_WEEK_FLAG_SUNDAY)
+        daysOfTheWeek.push_back("SU");
+    if (byDayValue & ALARM_WEEK_FLAG_MONDAY)
+        daysOfTheWeek.push_back("MO");
+    if (byDayValue & ALARM_WEEK_FLAG_TUESDAY)
+        daysOfTheWeek.push_back("TU");
+    if (byDayValue & ALARM_WEEK_FLAG_WEDNESDAY)
+        daysOfTheWeek.push_back("WE");
+    if (byDayValue & ALARM_WEEK_FLAG_THURSDAY)
+        daysOfTheWeek.push_back("TH");
+    if (byDayValue & ALARM_WEEK_FLAG_FRIDAY)
+        daysOfTheWeek.push_back("FR");
+    if (byDayValue & ALARM_WEEK_FLAG_SATURDAY)
+        daysOfTheWeek.push_back("SA");
+
+    return daysOfTheWeek;
+}
+
+app_control_h AlarmConverter::toService(std::string id)
+{
+    LOGD("Entered");
+
+    app_control_h service;
+    int ret = 0;
+
+    ret = app_control_create(&service);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to create app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    ret = app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to create app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    ret = app_control_set_app_id(service, id.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to create app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    return service;
+}
+app_control_h AlarmConverter::toService(std::string id, std::string page)
+{
+    LOGD("Entered");
+
+    app_control_h service;
+    int ret = 0;
+
+    ret = app_control_create(&service);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to create app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    ret = app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to create app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    ret = app_control_set_app_id(service, id.c_str());
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to create app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    return service;
+}
+
+bool AlarmConverter::toAlarmAbsolutePtr(int id, app_control_h handle, AlarmAbsolutePtr privateData)
+{
+    LOGD("Entered");
+
+    char* dateString = NULL;
+    char* alarmType = NULL;
+    struct tm date;
+    memset(&date, 0, sizeof(tm));
+    int ret = ALARM_ERROR_NONE;
+
+    ret = app_control_get_extra_data(handle, ALARM_ALSOLUTE_DATE_KEY, &dateString);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to get AlarmDelay %d, %s", ret, AlarmUtil::getAlarmErrorMessage(ret).c_str());
+        return false;
+    }
+    LOGI("Date Strng = %s", dateString);
+    sscanf(dateString, "%d %d %d %d %d %d %d", &date.tm_year, &date.tm_mon,
+        &date.tm_mday,  &date.tm_hour, &date.tm_min,  &date.tm_sec, &date.tm_isdst);
+    mktime(&date);
+
+    LOGI("Converter AlarmAbsolute Date = Sec : %d, Min : %d, Hour : %d, Day : %d, MON : %d, Year : %d, Is DST ? %d",
+            date.tm_sec, date.tm_min, date.tm_hour, date.tm_mday, date.tm_mon, date.tm_year, date.tm_isdst);
+
+    ret = app_control_get_extra_data(handle, ALARM_ALSOLUTE_RECURRENCE_TYPE_KEY, &alarmType);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to get AlarmType %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+
+        free(dateString);
+        return false;
+    }
+
+    if (!strcmp(alarmType, ALARM_ALSOLUTE_RECURRENCE_TYPE_INTERVAL)) {
+        int interval = 0;
+        ret = alarm_get_scheduled_period(id, &interval);
+        if (ret != ALARM_ERROR_NONE) {
+            LOGE("Fail to get scheduled period, %d, %s", ret, AlarmUtil::getAlarmErrorMessage(ret).c_str());
+        }
+
+        LOGI("interval type alarm: %d", interval);
+        privateData->setInterval(interval);
+    } else if (!strcmp(alarmType, ALARM_ALSOLUTE_RECURRENCE_TYPE_BYDAYVALUE)) {
+        int byDayValue =0;
+        ret = alarm_get_scheduled_recurrence_week_flag(id, &byDayValue);
+        LOGI("daysOfWeek type alarm: %d, error: %d", byDayValue, ret);
+        if (ret==ALARM_ERROR_NONE && byDayValue>0) {
+            std::vector<std::string> result;
+            result = convertFlagToDaysOfTheWeek(byDayValue);
+            privateData->setByDayRecurrence(result);
+        } else {
+            LOGE("Can't get the recurrence week flag.");
+        }
+    }
+
+    privateData->setId(id);
+    privateData->setDate(date);
+
+    free(dateString);
+    free(alarmType);
+
+    return true;
+}
+
+bool AlarmConverter::toAlarmRelativePtr(int id, app_control_h handle, AlarmRelativePtr privateData)
+{
+    LOGD("Entered");
+
+    int interval = 0;
+    char* delayString;
+    int delay;
+
+    int ret = ALARM_ERROR_NONE;
+    ret = alarm_get_scheduled_period(id, &interval);
+    if (ret != ALARM_ERROR_NONE) {
+        interval = 0;
+        LOGE("Failed to get scheduled period, %d, %s", ret, AlarmUtil::getAlarmErrorMessage(ret).c_str());
+    }
+
+    ret = app_control_get_extra_data(handle, ALARM_RELATIVE_DELAY_KEY, &delayString);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to get AlarmDelay, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+        return false;
+    }
+    delay = atoi(delayString);
+    free(delayString);
+
+    privateData->setId(id);
+    privateData->setDelay(delay);
+    privateData->setPeriod(interval);
+
+    return true;
+}
+
+int AlarmConverter::toNativeInterval(std::string freq, std::string interval)
+{
+    LOGD("Entered");
+    int freqInSecond = 0;
+    int intervalValue = toInt(interval);
+
+    if (!freq.compare(ALARM_PROPERTY_MINUTELY_RECURRENCE))
+        freqInSecond = 60;
+    else if (!freq.compare(ALARM_PROPERTY_HOURLY_RECURRENCE))
+        freqInSecond = 3600;
+    else if (!freq.compare(ALARM_PROPERTY_DAILY_RECURRENCE))
+        freqInSecond = 3600*24;
+    else if (!freq.compare(ALARM_PROPERTY_WEEKLY_RECURRENCE))
+        freqInSecond = 3600 * 24 * 7;
+
+    return freqInSecond * intervalValue;
+}
+
+bool AlarmConverter::toAlarmService(app_control_h service, DeviceAPI::Application::ApplicationControlPtr appservice)
+{
+    LOGD("Entered");
+
+    int ret = 0;
+
+    if (appservice->getOperation().compare("") != 0) {
+        ret = app_control_set_operation(service, appservice->getOperation().c_str());
+        LOGE("Fail to set operation, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    } else {
+        LOGD("Error. operation is madatory field. cannot be null");
+        return false;
+    }
+
+    if (appservice->getUri().compare("") != 0) {
+        ret = app_control_set_uri(service, appservice->getUri().c_str() );
+        LOGE("Fail to set uri, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    if (appservice->getMime().compare("") != 0) {
+        ret = app_control_set_mime(service, appservice->getMime().c_str() );
+        LOGE("Fail to set mime, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    std::vector<DeviceAPI::Application::ApplicationControlDataPtr> appControlDataArray = appservice->getAppControlDataArray();
+
+    if (!appControlDataArray.empty()) {
+        std::string key;
+        const char** arr = NULL;
+
+        for (size_t i = 0; i < appControlDataArray.size(); ++i) {
+            key = appControlDataArray.at(i)->getKey();
+            if (key.empty()) {
+                    return false;
+            }
+            std::vector<std::string> valueArray = appControlDataArray.at(i)->getValue();
+            size_t size = valueArray.size();
+
+            arr = (const char**)calloc(sizeof(char*), size);
+
+            for (size_t j = 0; j < size; j++) {
+                arr[j] = valueArray.at(j).c_str();
+            }
+
+            app_control_add_extra_data_array(service, key.c_str(), arr, size);
+
+            if (arr)
+                free(arr);
+        }
+    }
+    return true;
+}
+
+} //Alarm
+} //DeviceAPI
diff --git a/src/Alarm/AlarmConverter.h b/src/Alarm/AlarmConverter.h
new file mode 100755 (executable)
index 0000000..0718816
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_TIZEN_ALARM_CONVERTER_H_
+#define _JS_TIZEN_ALARM_CONVERTER_H_
+
+#include <vector>
+#include <string>
+#include <app.h>
+#include <app_alarm.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+#include <JSApplicationControl.h>
+#include <ApplicationControl.h>
+#include <ApplicationConverter.h>
+
+#include "JSAlarmAbsolute.h"
+#include "AlarmAbsolute.h"
+#include "JSAlarmRelative.h"
+#include "AlarmRelative.h"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+class AlarmConverter : public WrtDeviceApis::CommonsJavaScript::Converter
+{
+public:
+    using Converter::toJSValueRef;
+    explicit AlarmConverter(JSContextRef context);
+    virtual ~AlarmConverter();
+
+    int toNativeAlarmValue(std::vector<std::string> daysOfTheWeek);
+    std::vector<std::string> convertFlagToDaysOfTheWeek(int byDayValue);
+    int toNativeValue(int interval);
+    std::vector<std::string> toPrivateValue(int byDayValue);
+    app_control_h toService(std::string id);
+    app_control_h toService(std::string id, std::string page);
+    bool toAlarmAbsolutePtr(int id, app_control_h handle, AlarmAbsolutePtr ptr);
+    bool toAlarmRelativePtr(int id, app_control_h handle, AlarmRelativePtr ptr);
+    int toNativeInterval(std::string freq, std::string interval);
+    bool toAlarmService(app_control_h alarm_service, DeviceAPI::Application::ApplicationControlPtr ptr);
+};
+
+typedef ConverterFactory<AlarmConverter> AlarmConverterFactory;
+
+}
+}
+
+#endif /* _JS_TIZEN_ALARM_CONVERTER_H_ */
diff --git a/src/Alarm/AlarmRelative.cpp b/src/Alarm/AlarmRelative.cpp
new file mode 100755 (executable)
index 0000000..8153b16
--- /dev/null
@@ -0,0 +1,148 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSTimeDuration.h>
+#include <app.h>
+
+#include "AlarmRelative.h"
+#include "AlarmUtil.h"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+AlarmRelative::AlarmRelative()
+{
+    LOGD("Entered");
+
+    int ret = 0;
+
+    m_isRecurrence = false;
+
+    ret = app_control_create(&m_app_control_handle);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to create alarm, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    ret = app_control_add_extra_data(m_app_control_handle, ALARM_TYPE_KEY, ALARM_TYPE_RELATIVE_VALUE);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to create alarm, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    m_Period = -1;
+    m_id = -1;
+    is_registered = false;
+    m_Period_null = false;
+}
+
+AlarmRelative::AlarmRelative(app_control_h handle)
+{
+    LOGD("Entered");
+
+    int ret = 0;
+
+    ret = app_control_clone(&m_app_control_handle, handle);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to copy app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    m_Period = -1;
+    m_id = -1;
+    is_registered = false;
+    m_Period_null = false;
+}
+
+AlarmRelative::~AlarmRelative()
+{
+    LOGD("Entered");
+
+    int ret = 0;
+
+    ret = app_control_destroy(m_app_control_handle);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to destory app control, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+}
+
+int AlarmRelative::getId() const
+{
+    return m_id;
+}
+
+void AlarmRelative::setId(const int id)
+{
+    m_id = id;
+    is_registered = true;
+}
+
+bool AlarmRelative::isRecurrence()
+{
+    return m_isRecurrence;
+}
+
+void AlarmRelative::setIsRecurrence(bool value)
+{
+    m_isRecurrence = value;
+}
+
+void AlarmRelative::setDelay(int delay)
+{
+    LOGD("Entered");
+
+    int ret = 0;
+    char result[12];
+    snprintf(result, sizeof(result), "%d", delay);
+    ret = app_control_add_extra_data(m_app_control_handle, ALARM_RELATIVE_DELAY_KEY, result);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Fail to add extra data, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+    }
+
+    m_delay = delay;
+}
+
+int AlarmRelative::getDelay()
+{
+    return m_delay;
+}
+
+void AlarmRelative::setPeriod(int value)
+{
+    m_Period = value;
+}
+
+int AlarmRelative::getPeriod()
+{
+    return m_Period;
+}
+
+void AlarmRelative::setPeriodNull(bool value)
+{
+    m_Period_null = value;
+}
+
+bool AlarmRelative::getPeriodNull()
+{
+    return m_Period_null;
+}
+
+app_control_h AlarmRelative::getService()
+{
+    return m_app_control_handle;
+}
+
+} //Alarm
+} //DeviceAPI
+
diff --git a/src/Alarm/AlarmRelative.h b/src/Alarm/AlarmRelative.h
new file mode 100755 (executable)
index 0000000..01cc606
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_API_ALARMRELATIVE_H_
+#define TIZENAPIS_API_ALARMRELATIVE_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <time.h>
+#include <app.h>
+
+#include "alarm_common.h"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+class AlarmRelative;
+typedef std::shared_ptr<AlarmRelative> AlarmRelativePtr;
+typedef std::vector<AlarmRelativePtr> AlarmRelativeArrayPtr;
+
+class AlarmRelative
+{
+  public:
+    typedef enum {
+        ALARM_TYPE_DELAY,
+        ALARM_TYPE_DATE,
+        ALARM_TYPE_INVALID,
+    } alarm_type_e;
+
+    AlarmRelative();
+    AlarmRelative(app_control_h handle);
+    ~AlarmRelative();
+    void setIsRecurrence(bool value);
+    int getId() const;
+    void setId(const int id);
+    void setDelay(int delay);
+    int getDelay();
+    bool isRecurrence();
+    void setPeriod(int value);
+    int getPeriod();
+    void setPeriodNull(bool value);
+    bool getPeriodNull();
+    app_control_h getService();
+
+ public:
+    bool is_registered;
+
+  private:
+    int m_id;
+    int m_delay;
+    bool m_isRecurrence;
+    int m_Period;
+    bool m_Period_null;
+    app_control_h m_app_control_handle;
+
+};
+
+}
+}
+
+#endif
diff --git a/src/Alarm/AlarmUtil.cpp b/src/Alarm/AlarmUtil.cpp
new file mode 100755 (executable)
index 0000000..022faea
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <app.h>
+#include <app_alarm.h>
+
+#include "AlarmUtil.h"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+std::string AlarmUtil::getAlarmErrorMessage(const int errorCode)
+{
+    switch(errorCode) {
+        case ALARM_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case ALARM_ERROR_INVALID_TIME:
+            return "Invalid time";
+        case ALARM_ERROR_INVALID_DATE:
+            return "Invalid date";
+        case ALARM_ERROR_CONNECTION_FAIL:
+            return "Connection fail";
+        case ALARM_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case ALARM_ERROR_PERMISSION_DENIED :
+            return "Permission denied";
+        default:
+            return "Unknown Error";
+    }
+}
+
+std::string AlarmUtil::getAppControlErrorMessage(const int errorCode)
+{
+    switch(errorCode) {
+        case APP_CONTROL_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case APP_CONTROL_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case APP_CONTROL_ERROR_APP_NOT_FOUND:
+            return "Not found application";
+        case APP_CONTROL_ERROR_KEY_NOT_FOUND:
+            return "Not found key";
+        case APP_CONTROL_ERROR_KEY_REJECTED:
+            return "Key rejected";
+        case APP_CONTROL_ERROR_INVALID_DATA_TYPE:
+            return "Invalid data type";
+        case APP_CONTROL_ERROR_LAUNCH_REJECTED:
+            return "Launch rejected";
+        case APP_CONTROL_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case APP_CONTROL_ERROR_LAUNCH_FAILED:
+            return "Launch failed";
+        case APP_CONTROL_ERROR_TIMED_OUT:
+            return "Time out";
+        default:
+            return "Unknown Error";
+    }
+}
+
+} // Alarm
+} // Device API
diff --git a/src/Alarm/AlarmUtil.h b/src/Alarm/AlarmUtil.h
new file mode 100755 (executable)
index 0000000..6dea5f5
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ALARM_UTIL_H__
+#define __TIZEN_ALARM_UTIL_H__
+
+#include <string>
+#include <sstream>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace Alarm {
+
+class AlarmUtil {
+public:
+
+    static std::string getAlarmErrorMessage(const int errorCode);
+    static std::string getAppControlErrorMessage(const int errorCode);
+
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwAlarmException(const int errorCode, const std::string &hint)
+    {
+        std::stringstream ss;
+        ss << "Failed" << hint << " : " << getAlarmErrorMessage(errorCode);
+        LOGE("%s", ss.str().c_str());
+
+        throw T(ss.str().c_str());
+    }
+
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwAppControlException(const int errorCode, const std::string &hint)
+    {
+        std::stringstream ss;
+        ss << "Failed" << hint << " : " << getAppControlErrorMessage(errorCode);
+        LOGE("%s", ss.str().c_str());
+
+        throw T(ss.str().c_str());
+    }
+
+};
+
+
+} // Alarm
+} // Device API
+
+#endif // __TIZEN_ALARM_UTIL_H__
diff --git a/src/Alarm/CMakeLists.txt b/src/Alarm/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..4d044b0
--- /dev/null
@@ -0,0 +1,63 @@
+SET(TARGET_NAME ${alarm_target})
+SET(DESTINATION_NAME ${alarm_dest})
+SET(TARGET_IMPL_NAME ${alarm_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_alarm REQUIRED
+    capi-appfw-application
+    capi-appfw-alarm
+)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+INCLUDE_DIRECTORIES(
+    ${platform_pkgs_alarm_INCLUDE_DIRS}
+    ${INCLUDE_COMMON}
+    ${TOP}/Application
+    ${TOP}/TimeUtil
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${timeutil_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${application_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    AlarmUtil.cpp
+    AlarmAbsolute.cpp
+    AlarmConverter.cpp
+    AlarmRelative.cpp
+    JSAlarmAbsolute.cpp
+    JSAlarmManager.cpp
+    JSAlarmRelative.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${platform_pkgs_alarm_LIBRARIES}
+    ${tizen_impl}
+    ${application_impl}
+    ${timeutil_impl}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/alarm
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Alarm/JSAlarmAbsolute.cpp b/src/Alarm/JSAlarmAbsolute.cpp
new file mode 100755 (executable)
index 0000000..70b7e3a
--- /dev/null
@@ -0,0 +1,361 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSDOMExceptionFactory.h>
+#include <ArgumentValidator.h>
+#include <Commons/Exception.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <app_alarm.h>
+#include <app.h>
+#include <time.h>
+#include <JSUtil.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <Logger.h>
+
+#include "AlarmAbsolute.h"
+#include "AlarmConverter.h"
+#include "JSAlarmAbsolute.h"
+#include "JSAlarmManager.h"
+
+#define ALARM_FUNCTION_API_GET_NEXT_SCHEDULED_DATE "getNextScheduledDate"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+JSClassRef JSAlarmAbsolute::m_jsClassRef = NULL;
+
+JSClassDefinition JSAlarmAbsolute::m_jsClassInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_ALARM_ABSOLUTE_INTERFACE,
+        NULL,
+        m_property,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,Geolocation
+        NULL, //getPropertyNames,
+        NULL,
+        NULL, // constructor
+        NULL,
+        NULL
+};
+
+JSStaticFunction JSAlarmAbsolute::m_function[] = {
+    { ALARM_FUNCTION_API_GET_NEXT_SCHEDULED_DATE, JSAlarmAbsolute::getNextScheduledDate, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSStaticValue JSAlarmAbsolute::m_property[] = {
+    { TIZEN_ALARM_ABSOLUTE_ATTRIBUTE_ID, getId, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_ALARM_ABSOLUTE_ATTRIBUTE_DATE, getDate, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_ALARM_ABSOLUTE_ATTRIBUTE_PERIOD, getInterval, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_ALARM_ABSOLUTE_ATTRIBUTE_DAYSOFTHEWEEK, getDaysOfTheWeek, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSAlarmAbsolute::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAlarmAbsolute::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+void JSAlarmAbsolute::initialize(JSContextRef context, JSObjectRef object)
+{
+}
+void JSAlarmAbsolute::finalize(JSObjectRef object)
+{
+    JSAlarmAbsolutePriv *priv = static_cast<JSAlarmAbsolutePriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Private object is null");
+    }
+    delete priv;
+
+}
+
+
+JSObjectRef DLL_EXPORT JSAlarmAbsolute::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    ArgumentValidator validator(ctx, argumentCount, arguments);
+
+    AlarmAbsolutePtr priv = AlarmAbsolutePtr(new AlarmAbsolute());
+
+    try {
+        time_t date = validator.toTimeT(0);
+        struct tm *startDate = localtime(&date);
+        mktime(startDate);
+
+        priv->setDate(*startDate);
+
+        if (argumentCount >= 2) {
+            if (JSIsArrayValue(ctx, arguments[1])) {
+                std::vector<std::string> daysOfTheWeek =  validator.toStringVector(1);
+
+                for (size_t i = 0; i < daysOfTheWeek.size(); i++ ) {
+                    if ( (daysOfTheWeek[i]!="SU") && (daysOfTheWeek[i]!="MO") &&
+                         (daysOfTheWeek[i]!="TU") && (daysOfTheWeek[i]!="WE") &&
+                         (daysOfTheWeek[i]!="TH") && (daysOfTheWeek[i]!="FR") &&
+                         (daysOfTheWeek[i]!="SA") ) {
+                        // remove unacceptable data from vector
+                        daysOfTheWeek.erase(std::remove(daysOfTheWeek.begin(), daysOfTheWeek.end(), daysOfTheWeek[i]), daysOfTheWeek.end());
+                    }
+                }
+
+                if (daysOfTheWeek.size() > 0) {
+                    priv->setByDayRecurrence(daysOfTheWeek);
+                }
+            } else {
+                long interval = validator.toLong(1);
+                if (interval < 0) {
+                    throw InvalidValuesException("period can not be negative value");
+                }
+
+                priv->setInterval(interval);
+            }
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Exception occured while creating constructor : %s ", err.getMessage().c_str());
+    }
+
+    JSAlarmAbsolutePriv *jspriv = new JSAlarmAbsolutePriv(ctx, priv);
+    JSObjectRef obj = JSObjectMake(ctx, getClassRef(), jspriv);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(ctx, obj, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    return obj;
+}
+
+AlarmAbsolutePtr JSAlarmAbsolute::getPrivData(JSObjectRef object)
+{
+    JSAlarmAbsolutePriv *priv = static_cast<JSAlarmAbsolutePriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    AlarmAbsolutePtr result = priv->getObject();
+    if (!result) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return result;
+}
+
+
+JSValueRef JSAlarmAbsolute::createJSObject(JSContextRef context, AlarmAbsolutePtr privateData)
+{
+    JSAlarmAbsolutePriv *priv = new JSAlarmAbsolutePriv(context, privateData);
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+}
+
+JSValueRef JSAlarmAbsolute::getNextScheduledDate( JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        struct tm date;
+        Converter converter(ctx);
+
+        AlarmAbsolutePtr privateData = getPrivData(thisObject);
+        if (!privateData) {
+            throw TypeMismatchException("Private object is null");
+        }
+
+        if (!privateData->is_registered) {
+            return JSValueMakeNull(ctx);
+        }
+
+        int id = privateData->getId();
+        TIME_TRACER_ITEM_BEGIN("(getNextScheduledDate)alarm_get_scheduled_date", 0);
+        int err = alarm_get_scheduled_date(id, &date);
+        TIME_TRACER_ITEM_END("(getNextScheduledDate)alarm_get_scheduled_date", 0);
+        if (err != ALARM_ERROR_NONE) {
+            return JSValueMakeNull(ctx);
+        }
+
+        // check wheter the alarm is expired or not
+        struct tm curr_date;
+        TIME_TRACER_ITEM_BEGIN("(getNextScheduledDate)alarm_get_current_time", 0);
+        err = alarm_get_current_time(&curr_date);
+        TIME_TRACER_ITEM_END("(getNextScheduledDate)alarm_get_current_time", 0);
+        if (err != ALARM_ERROR_NONE) {
+            return JSValueMakeNull(ctx);
+        }
+
+        if (mktime(&date) < mktime(&curr_date)) {
+            return JSValueMakeNull(ctx);
+        }
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return converter.toJSValueRef(date);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+JSValueRef JSAlarmAbsolute::getDate(JSContextRef ctx,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    Converter converter(ctx);
+    struct tm date;
+
+    try {
+        AlarmAbsolutePtr privateData = getPrivData(object);
+        if (!privateData) {
+            throw TypeMismatchException("Private object is null");
+        }
+
+        date = privateData->getDate();
+        LOGI("JSAlarmAbsolute Date  = Sec : %d, Min : %d, Hour : %d, Day : %d, MON : %d, Year : %d",
+                date.tm_sec, date.tm_min, date.tm_hour, date.tm_mday, date.tm_mon, date.tm_year);
+
+        JSValueRef args[6];
+        args[0] = JSValueMakeNumber(ctx, date.tm_year + 1900);
+        args[1] = JSValueMakeNumber(ctx, date.tm_mon);
+        args[2] = JSValueMakeNumber(ctx, date.tm_mday);
+        args[3] = JSValueMakeNumber(ctx, date.tm_hour);
+        args[4] = JSValueMakeNumber(ctx, date.tm_min);
+        args[5] = JSValueMakeNumber(ctx, date.tm_sec);
+
+        JSObjectRef result = JSObjectMakeDate(ctx, 6, args, exception);
+        return result;
+    } catch (...) {
+        LOGE("Exception: occured");
+    }
+
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSAlarmAbsolute::getId(JSContextRef ctx,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        AlarmAbsolutePtr privateData = getPrivData(object);
+        if (!privateData) {
+            throw TypeMismatchException("Private object is null");
+        }
+
+        Converter converter(ctx);
+        if (privateData->is_registered) {
+            std::string strId = converter.toString(privateData->getId());
+            return converter.toJSValueRef(strId);
+        } else {
+            return JSValueMakeNull(ctx);
+        }
+    } catch (...) {
+        LOGE("Exception: occured");
+    }
+
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSAlarmAbsolute::getInterval(JSContextRef ctx,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        AlarmAbsolutePtr privateData = getPrivData(object);
+        AbsoluteRecurrence::Type alarmType = privateData->getRecurrenceType();
+
+        if (alarmType == AbsoluteRecurrence::Interval) {
+            long interval = privateData->getInterval();
+            if (interval == -1 ) {
+                return JSValueMakeNull(ctx);
+            } else {
+                return DeviceAPI::Common::JSUtil::toJSValueRef(ctx, interval);
+            }
+        } else {
+            return JSValueMakeNull(ctx);
+        }
+    } catch (...) {
+        LOGI("Exception: occured");
+    }
+
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSAlarmAbsolute::getDaysOfTheWeek(JSContextRef ctx,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    Converter converter(ctx);
+
+    try {
+        AlarmAbsolutePtr privateData = getPrivData(object);
+        if (!privateData) {
+            throw TypeMismatchException("Private object is null");
+        }
+
+        JSObjectRef jsResult = JSCreateArrayObject(ctx, 0, NULL);
+        if (jsResult == NULL) {
+            throw UnknownException("Could not create js array object");
+        }
+
+        std::vector<std::string> daysOfTheWeek = privateData->getByDayRecurrence();
+
+        if (daysOfTheWeek.size() > 0) {
+            for (size_t i = 0; i<daysOfTheWeek.size(); i++) {
+                JSValueRef val = converter.toJSValueRef(daysOfTheWeek.at(i));
+                if (!JSSetArrayElement(ctx, jsResult, i, val)) {
+                    throw UnknownException("Could not insert value into js array");
+                }
+            }
+        }
+
+        return jsResult;
+    } catch (...) {
+        LOGI("Exception: occured");
+    }
+
+    return JSValueMakeUndefined(ctx);
+}
+
+} // Alarm
+} // TizenApis
+
+
diff --git a/src/Alarm/JSAlarmAbsolute.h b/src/Alarm/JSAlarmAbsolute.h
new file mode 100755 (executable)
index 0000000..9f72e2a
--- /dev/null
@@ -0,0 +1,85 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_TIZEN_JSALARMABSOLUTE
+#define _JS_TIZEN_JSALARMABSOLUTE
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <IApplicationManager.h>
+
+#include "AlarmAbsolute.h"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+#define TIZEN_ALARM_ABSOLUTE_INTERFACE "AlarmAbsolute"
+
+#define TIZEN_ALARM_ABSOLUTE_ATTRIBUTE_ID "id"
+#define TIZEN_ALARM_ABSOLUTE_ATTRIBUTE_DATE "date"
+#define TIZEN_ALARM_ABSOLUTE_ATTRIBUTE_PERIOD "period"
+#define TIZEN_ALARM_ABSOLUTE_ATTRIBUTE_DAYSOFTHEWEEK "daysOfTheWeek"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<AlarmAbsolutePtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> JSAlarmAbsolutePriv;
+
+class JSAlarmAbsolute {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef createJSObject(JSContextRef context, AlarmAbsolutePtr privateData);
+
+protected:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static JSValueRef getNextScheduledDate(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+private:
+    static AlarmAbsolutePtr getPrivData(JSObjectRef object);
+
+    static JSValueRef getDate(JSContextRef context,
+                                        JSObjectRef object,
+                                        JSStringRef propertyName,
+                                        JSValueRef* exception);
+
+    static JSValueRef getId(JSContextRef context,
+                                        JSObjectRef object,
+                                        JSStringRef propertyName,
+                                        JSValueRef* exception);
+
+    static JSValueRef getInterval(JSContextRef context,
+                                                JSObjectRef object,
+                                                JSStringRef propertyName,
+                                                JSValueRef* exception);
+
+    static JSValueRef getDaysOfTheWeek(JSContextRef context,
+                                                JSObjectRef object,
+                                                JSStringRef propertyName,
+                                                JSValueRef* exception);
+
+
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+    static JSStaticFunction m_function[];
+    static JSStaticValue m_property[];
+};
+
+}// Alarm
+} // TizenApis
+
+#endif
diff --git a/src/Alarm/JSAlarmManager.cpp b/src/Alarm/JSAlarmManager.cpp
new file mode 100755 (executable)
index 0000000..b8b9378
--- /dev/null
@@ -0,0 +1,539 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <vector>
+#include <app.h>
+#include <time.h>
+#include <string>
+
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/JSDOMExceptionFactory.h>
+
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include <Security.h>
+
+#include <SecurityExceptions.h>
+#include <Commons/Exception.h>
+#include <Commons/Regex.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSApplicationControl.h>
+#include <ApplicationControl.h>
+#include <ApplicationConverter.h>
+
+#include <ail.h>
+#include <app_alarm.h>
+
+#include "plugin_config_impl.h"
+#include "AlarmConverter.h"
+#include "JSAlarmAbsolute.h"
+#include "AlarmAbsolute.h"
+#include "JSAlarmRelative.h"
+#include "AlarmRelative.h"
+#include "JSAlarmManager.h"
+#include "AlarmUtil.h"
+
+#include <TimeTracer.h>
+#include <Export.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Alarm {
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+static bool alarm_iterate_callback(int alarm_id, void *user_data)
+{
+    std::vector<int> *alarmIds = reinterpret_cast<std::vector<int>*>(user_data);
+
+    alarmIds->push_back(alarm_id);
+    return true;
+}
+
+JSClassRef JSAlarmManager::m_jsClassRef = NULL;
+
+JSClassDefinition JSAlarmManager::m_jsClassInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_ALARM_INTERFACE,
+        NULL,
+        m_property,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,Geolocation
+        NULL, //getPropertyNames,
+        NULL,
+        NULL, // constructor
+        NULL,
+        NULL
+};
+
+JSStaticFunction JSAlarmManager::m_function[] = {
+        { ALARM_FUNCTION_API_ADD, JSAlarmManager::add,kJSPropertyAttributeNone },
+        { ALARM_FUNCTION_API_REMOVE, JSAlarmManager::remove,kJSPropertyAttributeNone },
+        { ALARM_FUNCTION_API_REMOVE_ALL, JSAlarmManager::removeAll,kJSPropertyAttributeNone },
+        { ALARM_FUNCTION_API_GET_ALL, JSAlarmManager::getAll,kJSPropertyAttributeNone },
+        { ALARM_FUNCTION_API_GET, JSAlarmManager::get,kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+JSStaticValue JSAlarmManager::m_property[] = {
+        { TIZEN_ALARM_CONSTANT_PERIOD_MINUTE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { TIZEN_ALARM_CONSTANT_PERIOD_HOUR, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { TIZEN_ALARM_CONSTANT_PERIOD_DAY, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { TIZEN_ALARM_CONSTANT_PERIOD_WEEK, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSAlarmManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAlarmManager::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+JSContextRef JSAlarmManager::gContext = NULL;
+
+void JSAlarmManager::initialize(JSContextRef ctx, JSObjectRef object)
+{
+    gContext = ctx;
+
+    SecurityAccessor *priv = new SecurityAccessor();
+    JSObjectSetPrivate(object, static_cast<void*>(priv));
+}
+
+void JSAlarmManager::finalize(JSObjectRef object)
+{
+    SecurityAccessor *priv = static_cast<SecurityAccessor*>(JSObjectGetPrivate(object));
+    delete priv;
+}
+
+JSValueRef JSAlarmManager::add(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    app_control_h service;
+    struct tm startDate;
+    int delay = 0;
+    int alarm_id;
+    std::string applicationId;
+    std::string page;
+
+    SecurityAccessor *thisPriv = static_cast<SecurityAccessor*>(JSObjectGetPrivate(thisObject));
+    if (!thisPriv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(ctx, exception,
+                JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
+    }
+    TIME_TRACER_ITEM_BEGIN("(add)ace_check", 0);
+    TIZEN_CHECK_ACCESS(ctx, exception, thisPriv, ALARM_FUNCTION_API_ADD);
+    TIME_TRACER_ITEM_END("(add)ace_check", 0);
+
+    try {
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        AlarmConverter converter(ctx);
+
+        // applicationId
+        std::string appId = validator.toString(1);
+
+        // alarm
+        JSObjectRef alarmObj = validator.toObject(0);
+        if (JSValueIsObjectOfClass(ctx, alarmObj, JSAlarmAbsolute::getClassRef())) {
+
+            JSAlarmAbsolutePriv *priv = static_cast<JSAlarmAbsolutePriv*>(JSObjectGetPrivate(alarmObj));
+            if (!priv) {
+                throw TypeMismatchException("Object is null.");
+            }
+            AlarmAbsolutePtr alarmPtr = priv->getObject();
+            if (!alarmPtr) {
+                throw TypeMismatchException("Private object is null.");
+            }
+
+            startDate = alarmPtr->getDate();
+            service = alarmPtr->getService();
+            app_control_set_app_id(service, appId.c_str());
+
+            // appControl
+            JSObjectRef appControlObj = validator.toObject(2, true);
+            if (appControlObj) {
+                if (!JSValueIsObjectOfClass(ctx, appControlObj, DeviceAPI::Application::JSApplicationControl::getClassRef())) {
+                    throw TypeMismatchException("Third parameter is not a ApplicationControl object");
+                }
+                DeviceAPI::Application::ApplicationConverter applicationConverter(ctx);
+                DeviceAPI::Application::ApplicationControlPtr appService = applicationConverter.toApplicationControl(appControlObj);
+                if (converter.toAlarmService(service, appService) == false) {
+                    throw TypeMismatchException("Third parameter is not a ApplicationControl object");
+                }
+            } else {
+                app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
+            }
+
+            AbsoluteRecurrence::Type alarmType = alarmPtr->getRecurrenceType();
+
+            int err = ALARM_ERROR_NONE;
+            if (alarmType == AbsoluteRecurrence::ByDayValue) {
+                int bydayValue = converter.toNativeAlarmValue(alarmPtr->getByDayRecurrence());
+                LOGI("Native bydayValue = %d", bydayValue);
+                TIME_TRACER_ITEM_BEGIN("(add)alarm_schedule_with_recurrence_week_flag", 0);
+                err = alarm_schedule_with_recurrence_week_flag(service, &startDate, bydayValue, &alarm_id);
+                TIME_TRACER_ITEM_END("(add)alarm_schedule_with_recurrence_week_flag", 0);
+
+            } else if (alarmType == AbsoluteRecurrence::Interval) {
+                int interval = alarmPtr->getInterval();
+                TIME_TRACER_ITEM_BEGIN("(add)alarm_schedule_at_date", 0);
+                err = alarm_schedule_at_date(service, &startDate, interval, &alarm_id);
+                TIME_TRACER_ITEM_END("(add)alarm_schedule_at_date", 0);
+            } else {
+                TIME_TRACER_ITEM_BEGIN("(add)alarm_schedule_at_date", 0);
+                err = alarm_schedule_at_date(service, &startDate, 0, &alarm_id);
+                TIME_TRACER_ITEM_END("(add)alarm_schedule_at_date", 0);
+            }
+
+            if (err == ALARM_ERROR_NONE) {
+                alarmPtr->setId(alarm_id);
+            } else {
+                throw UnknownException("Alarm scheduling failed.");
+            }
+
+        } else if (JSValueIsObjectOfClass(ctx, alarmObj, JSAlarmRelative::getClassRef())) {
+
+            JSAlarmRelativePriv *priv = static_cast<JSAlarmRelativePriv*>(JSObjectGetPrivate(alarmObj));
+            if (!priv) {
+                throw TypeMismatchException("Object is null.");
+            }
+            AlarmRelativePtr alarmPtr = priv->getObject();
+            if (!alarmPtr) {
+                throw TypeMismatchException("Private object is null.");
+            }
+
+            delay = alarmPtr->getDelay();
+            if (delay < 0) {
+                throw InvalidValuesException("Alarm scheduling failed : delay cannot be negative value.");
+            }
+
+            long interval = alarmPtr->getPeriod();
+            service = alarmPtr->getService();
+            app_control_set_app_id(service, appId.c_str());
+
+            // appControl
+            JSObjectRef appControlObj = validator.toObject(2, true);
+            if (appControlObj) {
+                if (!JSValueIsObjectOfClass(ctx, appControlObj, DeviceAPI::Application::JSApplicationControl::getClassRef())) {
+                    throw TypeMismatchException("Third parameter is not a ApplicationControl object");
+                }
+                DeviceAPI::Application::ApplicationConverter applicationConverter(ctx);
+                DeviceAPI::Application::ApplicationControlPtr appService = applicationConverter.toApplicationControl(appControlObj);
+                if (converter.toAlarmService(service, appService) == false) {
+                    throw TypeMismatchException("Third parameter is not a ApplicationControl object");
+                }
+            } else {
+                app_control_set_operation(service, APP_CONTROL_OPERATION_DEFAULT);
+            }
+
+            TIME_TRACER_ITEM_BEGIN("(add)alarm_schedule_after_delay", 0);
+            int err = alarm_schedule_after_delay(service, delay, interval, &alarm_id);
+            TIME_TRACER_ITEM_END("(add)alarm_schedule_after_delay", 0);
+
+            if (err == ALARM_ERROR_NONE) {
+                alarmPtr->setId(alarm_id);
+            } else {
+                throw UnknownException("Alarm scheduling failed.");
+            }
+
+        } else {
+            LOGE("First parameter is not a Alarm object");
+            throw TypeMismatchException("First parameter is not a Alarm object");
+        }
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(ctx);
+
+    }  catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+JSValueRef JSAlarmManager::remove(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    SecurityAccessor *thisPriv = static_cast<SecurityAccessor*>(JSObjectGetPrivate(thisObject));
+    if (!thisPriv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(ctx, exception,
+                JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
+    }
+    TIME_TRACER_ITEM_BEGIN("(add)ace_check", 0);
+    TIZEN_CHECK_ACCESS(ctx, exception, thisPriv, ALARM_FUNCTION_API_REMOVE);
+    TIME_TRACER_ITEM_END("(add)ace_check", 0);
+
+    try {
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+
+        // id
+        std::string id = validator.toString(0);
+
+        int alarmId = 0;
+        std::stringstream(id) >> alarmId;
+
+        if (alarmId <= 0) {
+            throw InvalidValuesException("Invalid ID");
+        }
+
+        TIME_TRACER_ITEM_BEGIN("(remove)alarm_cancel", 0);
+        int ret = alarm_cancel(alarmId);
+        TIME_TRACER_ITEM_END("(remove)alarm_cancel", 0);
+
+        if (ret != ALARM_ERROR_NONE) {
+            throw NotFoundException("Alarm not found");
+        }
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(ctx);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+JSValueRef JSAlarmManager::removeAll(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    SecurityAccessor *thisPriv = static_cast<SecurityAccessor*>(JSObjectGetPrivate(thisObject));
+    if (!thisPriv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(ctx, exception,
+                JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
+    }
+    TIME_TRACER_ITEM_BEGIN("(add)ace_check", 0);
+    TIZEN_CHECK_ACCESS(ctx, exception, thisPriv, ALARM_FUNCTION_API_REMOVE_ALL);
+    TIME_TRACER_ITEM_END("(add)ace_check", 0);
+
+    TIME_TRACER_ITEM_BEGIN("(removeAll)alarm_cancel_all", 0);
+    int returnVal = alarm_cancel_all();
+    TIME_TRACER_ITEM_END("(removeAll)alarm_cancel_all", 0);
+
+    if (ALARM_ERROR_NONE != returnVal) {
+        LOGE("Error while removing all alarms: %d", returnVal);
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSAlarmManager::get(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        app_control_h service = NULL;
+        char* alarmType = NULL;
+        JSValueRef result = NULL;
+
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        AlarmConverter converter(ctx);
+
+        // id
+        std::string id = validator.toString(0);
+        int alarmId = 0;
+        std::stringstream(id) >> alarmId;
+
+        if (alarmId <= 0) {
+            LOGE("Wrong Alarm ID");
+            throw InvalidValuesException("Invalid ID");
+        }
+
+        TIME_TRACER_ITEM_BEGIN("(get)alarm_get_app_control", 0);
+        int ret = alarm_get_app_control(alarmId, &service);
+        if (ret != ALARM_ERROR_NONE) {
+            LOGE("Getting app control failed: %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+            throw NotFoundException("Alarm not found");
+        }
+
+        ret = app_control_get_extra_data(service, ALARM_TYPE_KEY, &alarmType);
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("Getting data failed: %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+            app_control_destroy(service);
+            throw UnknownException("Unknown error occurred.");
+        }
+        TIME_TRACER_ITEM_END("(get)alarm_get_app_control", 0);
+
+        if (strcmp(alarmType, ALARM_TYPE_ABSOLUTE_VALUE) == 0) {
+            AlarmAbsolutePtr privateData = AlarmAbsolutePtr(new AlarmAbsolute(service));
+
+            if (!converter.toAlarmAbsolutePtr(alarmId, service, privateData)) {
+                app_control_destroy(service);
+                throw TypeMismatchException("Alarm not found");
+            }
+
+            result = JSAlarmAbsolute::createJSObject(ctx, privateData);
+
+        } else if (strcmp(alarmType, ALARM_TYPE_RELATIVE_VALUE) == 0) {
+            AlarmRelativePtr privateData = AlarmRelativePtr(new AlarmRelative(service));
+
+            if (!converter.toAlarmRelativePtr(alarmId, service, privateData)) {
+                app_control_destroy(service);
+                 throw TypeMismatchException("Alarm not found");
+            }
+
+            result = JSAlarmRelative::createJSObject(ctx, privateData);
+        } else {
+            app_control_destroy(service);
+            throw UnknownException("Unknown error occurred.");
+        }
+
+        app_control_destroy(service);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return result;
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+
+JSValueRef JSAlarmManager::getAll(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        AlarmConverter converter(ctx);
+        std::vector<int> alarmIds;
+
+        TIME_TRACER_ITEM_BEGIN("(getAll)alarm_foreach_registered_alarm", 0);
+        int ret = alarm_foreach_registered_alarm(alarm_iterate_callback, &alarmIds);
+        TIME_TRACER_ITEM_END("(getAll)alarm_foreach_registered_alarm", 0);
+        if (ret == ALARM_ERROR_CONNECTION_FAIL) {
+            LOGE("Alarm system may not be ready yet.");
+            alarmIds.clear();
+        } else if (ret != ALARM_ERROR_NONE) {
+            LOGE("Error occurred while getting all alarms, %d, %s", ret, AlarmUtil::getAlarmErrorMessage(ret).c_str());
+            throw UnknownException("Unknown error occurred.");
+        }
+
+        JSObjectRef jsResult = JSCreateArrayObject(ctx, 0, NULL);
+        if (jsResult == NULL) {
+            throw TypeMismatchException("Could not create js array object.");
+        }
+
+        for (size_t i = 0 ; i < alarmIds.size(); i++) {
+
+            app_control_h handle = NULL;
+            char* alarmType = NULL;
+
+            TIME_TRACER_ITEM_BEGIN("(getAll)alarm_get_app_control", 0);
+            ret = alarm_get_app_control(alarmIds.at(i), &handle);
+            TIME_TRACER_ITEM_END("(getAll)alarm_get_app_control", 0);
+            if (ret != ALARM_ERROR_NONE) {
+                LOGE("Getting service failed, %d, %s", ret, AlarmUtil::getAlarmErrorMessage(ret).c_str());
+                throw NotFoundException("Alarm not found");
+            }
+
+            TIME_TRACER_ITEM_BEGIN("(getAll)app_control_get_extra_data", 0);
+            ret = app_control_get_extra_data(handle, ALARM_TYPE_KEY, &alarmType);
+            TIME_TRACER_ITEM_END("(getAll)app_control_get_extra_data", 0);
+            if (ret != APP_CONTROL_ERROR_NONE) {
+                LOGE("Getting data failed, %d, %s", ret, AlarmUtil::getAppControlErrorMessage(ret).c_str());
+                app_control_destroy(handle);
+                throw UnknownException("Unknown error occurred.");
+            }
+
+            JSValueRef obj = NULL;
+            if (strcmp(alarmType, ALARM_TYPE_ABSOLUTE_VALUE) == 0) {
+                AlarmAbsolutePtr privateData = AlarmAbsolutePtr(new AlarmAbsolute(handle));
+
+                if (!converter.toAlarmAbsolutePtr(alarmIds.at(i), handle, privateData)) {
+                    app_control_destroy(handle);
+                    throw TypeMismatchException("Absolute alarm conversion failed.");
+                }
+
+                obj = JSAlarmAbsolute::createJSObject(ctx, privateData);
+
+            } else if (!strcmp(alarmType, ALARM_TYPE_RELATIVE_VALUE)) {
+                AlarmRelativePtr privateData = AlarmRelativePtr(new AlarmRelative(handle));
+
+                if (!converter.toAlarmRelativePtr(alarmIds.at(i), handle, privateData)) {
+                    app_control_destroy(handle);
+                    throw TypeMismatchException("Relative alarm conversion failed.");
+                }
+                obj = JSAlarmRelative::createJSObject(ctx, privateData);
+
+            }  else {
+                app_control_destroy(handle);
+                throw UnknownException("Unknown error occurred.");
+            }
+
+            app_control_destroy(handle);
+
+            if (!JSSetArrayElement(ctx, jsResult, i, obj)) {
+                app_control_destroy(handle);
+                throw UnknownException("JS array creation failed.");
+            }
+        }
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return jsResult;
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+JSValueRef JSAlarmManager::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_ALARM_CONSTANT_PERIOD_MINUTE)) {
+            return JSUtil::toJSValueRef(context, (long)60);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_ALARM_CONSTANT_PERIOD_HOUR)) {
+            return JSUtil::toJSValueRef(context, (long)3600);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_ALARM_CONSTANT_PERIOD_DAY)) {
+            return JSUtil::toJSValueRef(context, (long)86400);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_ALARM_CONSTANT_PERIOD_WEEK)) {
+            return JSUtil::toJSValueRef(context, (long)604800);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("Getting property is failed. %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+} // Alarm
+} // TizenApis
+
diff --git a/src/Alarm/JSAlarmManager.h b/src/Alarm/JSAlarmManager.h
new file mode 100755 (executable)
index 0000000..e93ab95
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_TIZEN_ALARM_MANAGER
+#define _JS_TIZEN_ALARM_MANAGER
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+
+namespace DeviceAPI {
+namespace Alarm {
+
+#define TIZEN_ALARM_INTERFACE "AlarmManager"
+
+#define TIZEN_ALARM_CONSTANT_PERIOD_MINUTE "PERIOD_MINUTE"
+#define TIZEN_ALARM_CONSTANT_PERIOD_HOUR "PERIOD_HOUR"
+#define TIZEN_ALARM_CONSTANT_PERIOD_DAY "PERIOD_DAY"
+#define TIZEN_ALARM_CONSTANT_PERIOD_WEEK "PERIOD_WEEK"
+
+class JSAlarmManager {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSContextRef gContext;
+
+protected:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static JSValueRef add(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef remove(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef removeAll(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef get(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef getAll(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+private:
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+    static JSStaticFunction m_function[];
+    static JSStaticValue m_property[];
+
+};
+
+}
+} // TizenApis
+
+#endif
diff --git a/src/Alarm/JSAlarmRelative.cpp b/src/Alarm/JSAlarmRelative.cpp
new file mode 100755 (executable)
index 0000000..0d8ef9c
--- /dev/null
@@ -0,0 +1,318 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSDOMExceptionFactory.h>
+#include <app_alarm.h>
+
+#include <ArgumentValidator.h>
+
+#include <Commons/Exception.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+
+#include "AlarmRelative.h"
+#include "AlarmConverter.h"
+#include "JSAlarmRelative.h"
+#include "JSAlarmManager.h"
+
+#include <JSUtil.h>
+
+#include <TimeTracer.h>
+#include <app.h>
+#include <time.h>
+#include <Export.h>
+#include <Logger.h>
+
+#define ALARM_FUNCTION_API_GET_REMAINING_SECONDS "getRemainingSeconds"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+JSClassRef JSAlarmRelative::m_jsClassRef = NULL;
+
+JSClassDefinition JSAlarmRelative::m_jsClassInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_ALARM_RELATIVE_INTERFACE,
+    NULL,
+    m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,Geolocation
+    NULL, //getPropertyNames,
+    NULL,
+    NULL, // constructor
+    NULL,
+    NULL
+};
+
+JSStaticFunction JSAlarmRelative::m_function[] = {
+        { ALARM_FUNCTION_API_GET_REMAINING_SECONDS, JSAlarmRelative::getRemainingSeconds, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+JSStaticValue JSAlarmRelative::m_property[] = {
+    { TIZEN_ALARM_RELATIVE_ATTRIBUTE_ID, getId, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_ALARM_RELATIVE_ATTRIBUTE_DELAY, getDelay, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_ALARM_RELATIVE_ATTRIBUTE_PERIOD, getPeriod, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSAlarmRelative::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAlarmRelative::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+void JSAlarmRelative::initialize(JSContextRef context, JSObjectRef object)
+{
+}
+void JSAlarmRelative::finalize(JSObjectRef object)
+{
+    JSAlarmRelativePriv *priv = static_cast<JSAlarmRelativePriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Private object is null");
+    }
+    delete priv;
+}
+
+
+JSObjectRef DLL_EXPORT JSAlarmRelative::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception)
+{
+    ArgumentValidator validator(ctx, argumentCount, arguments);
+
+    AlarmRelativePtr privateData = AlarmRelativePtr(new AlarmRelative());
+
+    try {
+        long delay = validator.toLong(0);
+        privateData->setDelay(delay);
+
+      if (validator.isNull(1) || validator.isOmitted(1)) {
+        privateData->setPeriodNull(true);
+      }
+      long period = validator.toLong(1, true, -1);
+      privateData->setPeriod(period);
+
+    } catch (const BasePlatformException& err) {
+        LOGE("Exception occured while creating constructor : %s", err.getMessage().c_str());
+    }
+
+    JSAlarmRelativePriv *priv = new JSAlarmRelativePriv(ctx, privateData);
+    JSObjectRef obj = JSObjectMake(ctx, getClassRef(), priv);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(ctx, obj, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    return obj;
+}
+
+AlarmRelativePtr JSAlarmRelative::getPrivData(JSObjectRef object)
+{
+    JSAlarmRelativePriv *priv = static_cast<JSAlarmRelativePriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    AlarmRelativePtr result = priv->getObject();
+    if (!result) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return result;
+}
+
+JSValueRef JSAlarmRelative::createJSObject(JSContextRef context, AlarmRelativePtr privateData)
+{
+    JSAlarmRelativePriv *priv = new JSAlarmRelativePriv(context, privateData);
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+}
+
+
+JSValueRef JSAlarmRelative::createJSObject(JSContextRef context, int delay, int interval)
+{
+    AlarmRelativePtr privateData = AlarmRelativePtr(new AlarmRelative());
+    privateData->setDelay(delay);
+    privateData->setPeriod(interval);
+
+    JSAlarmRelativePriv *priv = new JSAlarmRelativePriv(context, privateData);
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+}
+
+JSValueRef JSAlarmRelative::getRemainingSeconds(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception)
+{
+    struct tm date;
+    struct tm current;
+    time_t currentTime;
+    time_t nextTime;
+    int id;
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        AlarmRelativePtr privateData = getPrivData(thisObject);
+
+        if (!privateData->is_registered) {
+            return JSValueMakeNull(ctx);
+        }
+
+        id = privateData->getId();
+
+        TIME_TRACER_ITEM_BEGIN("(getRemainingSeconds)alarm_get_scheduled_date", 0);
+        int err = alarm_get_scheduled_date(id, &date);
+        TIME_TRACER_ITEM_END("(getRemainingSeconds)alarm_get_scheduled_date", 0);
+        if (err != ALARM_ERROR_NONE)
+        {
+            if (err == ALARM_ERROR_INVALID_PARAMETER) {
+                return JSValueMakeNull(ctx);
+            } else  {
+                throw UnknownException("Unknown exception occurred. fail to get scheduled date");
+            }
+        }
+
+        TIME_TRACER_ITEM_BEGIN("(getRemainingSeconds)alarm_get_current_time", 0);
+        alarm_get_current_time(&current);
+
+        nextTime = mktime(&date);
+        currentTime = mktime(&current);
+        TIME_TRACER_ITEM_END("(getRemainingSeconds)alarm_get_current_time", 0);
+
+        long result = nextTime - currentTime;
+
+        LOGI("nextTime: %ld, currentTime: %ld, result: %ld", nextTime, currentTime, result);
+
+        if (result < 0) {
+            return JSValueMakeNull(ctx);
+        }
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+        return DeviceAPI::Common::JSUtil::toJSValueRef(ctx, result);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+JSValueRef JSAlarmRelative::getId(JSContextRef ctx,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    Converter converter(ctx);
+
+    try {
+        AlarmRelativePtr privateData = getPrivData(object);
+        if (!privateData) {
+            throw TypeMismatchException("Private object is null");
+        }
+
+        if (privateData->is_registered) {
+            std::string strId = converter.toString(privateData->getId());
+            return converter.toJSValueRef(strId);
+        } else {
+            return JSValueMakeNull(ctx);
+        }
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::TypeMismatchException err("TypeMismatchException occured");
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+JSValueRef JSAlarmRelative::getDelay(JSContextRef ctx,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    long delay;
+
+    try {
+        AlarmRelativePtr privateData = getPrivData(object);
+        if (!privateData) {
+            throw TypeMismatchException("Private object is null");
+        }
+
+        delay = privateData->getDelay();
+        LOGI("JSAlarmRelative delay = %ld", delay);
+        return DeviceAPI::Common::JSUtil::toJSValueRef(ctx, delay);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::TypeMismatchException err("TypeMismatchException occured");
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+JSValueRef JSAlarmRelative::getPeriod(JSContextRef ctx,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    long period =0;
+
+    try {
+        AlarmRelativePtr privateData = getPrivData(object);
+        if (!privateData) {
+            throw TypeMismatchException("Private object is null");
+        }
+
+        period = privateData->getPeriod();
+      bool periodIsNull = privateData->getPeriodNull();
+        LOGI("JSAlarmRelative interval = %ld", period);
+         if (period == -1 && periodIsNull ) {
+            return JSValueMakeNull(ctx);
+        } else {
+            return DeviceAPI::Common::JSUtil::toJSValueRef(ctx, period);
+        }
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::TypeMismatchException err("TypeMismatchException occured");
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+} // Alarm
+} // TizenApis
+
+
diff --git a/src/Alarm/JSAlarmRelative.h b/src/Alarm/JSAlarmRelative.h
new file mode 100755 (executable)
index 0000000..93ae88c
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_TIZEN_ALARMRELATIVE
+#define _JS_TIZEN_ALARMRELATIVE
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <IApplicationManager.h>
+
+#include "AlarmRelative.h"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+#define TIZEN_ALARM_RELATIVE_INTERFACE "AlarmRelative"
+
+#define TIZEN_ALARM_RELATIVE_ATTRIBUTE_ID "id"
+#define TIZEN_ALARM_RELATIVE_ATTRIBUTE_DELAY "delay"
+#define TIZEN_ALARM_RELATIVE_ATTRIBUTE_PERIOD "period"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<AlarmRelativePtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> JSAlarmRelativePriv;
+
+class JSAlarmRelative {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, AlarmRelativePtr privateData);
+    static JSValueRef createJSObject(JSContextRef context, int delay, int interval);
+    static JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+protected:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static JSValueRef getRemainingSeconds(JSContextRef context, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef * exception);
+
+private:
+    static AlarmRelativePtr getPrivData(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+                                        JSObjectRef object,
+                                        JSStringRef propertyName,
+                                        JSValueRef* exception);
+
+    static JSValueRef getDelay(JSContextRef context,
+                                                JSObjectRef object,
+                                                JSStringRef propertyName,
+                                                JSValueRef* exception);
+
+    static JSValueRef getPeriod(JSContextRef context,
+                                                JSObjectRef object,
+                                                JSStringRef propertyName,
+                                                JSValueRef* exception);
+
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+    static JSStaticFunction m_function[];
+    static JSStaticValue m_property[];
+};
+
+}// Alarm
+} // TizenApis
+
+#endif
diff --git a/src/Alarm/alarm_common.h b/src/Alarm/alarm_common.h
new file mode 100755 (executable)
index 0000000..4c0460c
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_ALARM_COMMON_H_
+#define TIZENAPIS_API_ALARM_COMMON_H_
+
+namespace DeviceAPI {
+namespace Alarm {
+
+// Alarm Type
+#define ALARM_TYPE_KEY "TYPE"
+#define ALARM_TYPE_ABSOLUTE_VALUE "ABSOLUTE"
+#define ALARM_TYPE_RELATIVE_VALUE "RELATIVE"
+
+// Absolute Alarm Recurrence
+#define ALARM_ALSOLUTE_RECURRENCE_TYPE_KEY "RECURRENCE"
+#define ALARM_ALSOLUTE_RECURRENCE_TYPE_INTERVAL "INTERVAL"
+#define ALARM_ALSOLUTE_RECURRENCE_TYPE_BYDAYVALUE "BYDAYVALUE"
+#define ALARM_ALSOLUTE_RECURRENCE_TYPE_NONE "NONE"
+#define ALARM_ABSOLUTE_FREQUENCY_KEY "FREQUENCY"
+#define ALARM_ABSOLUTE_FREQUENCY_INTERVAL "FREQUENCY_INTERVAL"
+#define ALARM_ALSOLUTE_DATE_KEY "DATE"
+
+// Relative Alarm Delay
+#define ALARM_RELATIVE_DELAY_KEY "RELATIVE_DELAY"
+
+// Frequency
+#define ALARM_PROPERTY_MINUTELY_RECURRENCE    "MINUTELY"
+#define ALARM_PROPERTY_HOURLY_RECURRENCE    "HOURLY"
+#define ALARM_PROPERTY_DAILY_RECURRENCE    "DAILY"
+#define ALARM_PROPERTY_WEEKLY_RECURRENCE   "WEEKLY"
+#define ALARM_PROPERTY_MONTHLY_RECURRENCE  "MONTHLY"
+#define ALARM_PROPERTY_YEARLY_RECURRENCE   "YEARLY"
+
+namespace AbsoluteRecurrence
+{
+    typedef enum
+    {
+        NoRecurrence,
+        ByDayValue,
+        Interval,
+    }Type;
+}
+
+}
+}
+#endif
diff --git a/src/Alarm/config.xml b/src/Alarm/config.xml
new file mode 100755 (executable)
index 0000000..7363bdf
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-alarm.so</library-name>
+    <feature-install-uri>alarm.install.uri</feature-install-uri>
+    <api-feature>
+        <name>http://tizen.org/privilege/alarm</name>
+        <device-capability>alarm</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/Alarm/plugin_config.cpp b/src/Alarm/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..f9930b0
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <iostream>
+#include <Commons/Exception.h>
+#include <dpl/exception.h>
+#include <map>
+
+#include "plugin_config_impl.h"
+#include "plugin_config.h"
+
+#define ALARM_FEATURE_API "http://tizen.org/privilege/alarm"
+
+#define ALARM_DEVICE_CAP "alarm"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Alarm {
+
+static FunctionMapping createAlarmFunctions();
+
+static FunctionMapping AlarmFunctions =
+    createAlarmFunctions();
+
+DEFINE_FUNCTION_GETTER(Alarm, AlarmFunctions);
+
+static FunctionMapping createAlarmFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_ALARM, ALARM_DEVICE_CAP);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_ALARM);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_ALARM, DEVICE_CAP_ALARM);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_ALARM, ALARM_FEATURE_API);
+
+    ACE_CREATE_FEATURE_LIST(ALARM_FEATURES);
+    ACE_ADD_API_FEATURE(ALARM_FEATURES, FEATURE_ALARM);
+
+    /**
+     * Functions
+     */
+    FunctionMapping alarmMapping;
+
+    // add
+    AceFunction addFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD,
+            ALARM_FUNCTION_API_ADD,
+            ALARM_FEATURES,
+            DEVICE_LIST_ALARM);
+
+    alarmMapping.insert(std::make_pair(
+                                ALARM_FUNCTION_API_ADD,
+                                addFunc));
+
+    // remove
+    AceFunction removeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE,
+            ALARM_FUNCTION_API_REMOVE,
+            ALARM_FEATURES,
+            DEVICE_LIST_ALARM);
+
+    alarmMapping.insert(std::make_pair(
+                                ALARM_FUNCTION_API_REMOVE,
+                                removeFunc));
+
+
+    // removeAll
+    AceFunction removeAllFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_ALL,
+            ALARM_FUNCTION_API_REMOVE_ALL,
+            ALARM_FEATURES,
+            DEVICE_LIST_ALARM);
+
+    alarmMapping.insert(std::make_pair(
+                                ALARM_FUNCTION_API_REMOVE_ALL,
+                                removeAllFunc));
+
+    return alarmMapping;
+}
+
+}
+}
diff --git a/src/Alarm/plugin_config.h b/src/Alarm/plugin_config.h
new file mode 100755 (executable)
index 0000000..3bc1f15
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _ALARM_PLUGIN_CONFIG_H_
+#define _ALARM_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+namespace DeviceAPI {
+namespace Alarm {
+
+DECLARE_FUNCTION_GETTER(Alarm);
+
+#define ALARM_CHECK_ACCESS(functionName)                     \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(                \
+        getAlarmFunctionData,           \
+        functionName)
+}
+}
+#endif
+
diff --git a/src/Alarm/plugin_config_impl.h b/src/Alarm/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..3849162
--- /dev/null
@@ -0,0 +1,29 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _ALARM_PLUGIN_CONFIG_IMPL_H_
+#define _ALARM_PLUGIN_CONFIG_IMPL_H_
+
+#define ALARM_FUNCTION_API_GET_ALL "getAll"
+#define ALARM_FUNCTION_API_GET "get"
+#define ALARM_FUNCTION_API_ADD "add"
+#define ALARM_FUNCTION_API_REMOVE "remove"
+#define ALARM_FUNCTION_API_REMOVE_ALL "removeAll"
+#define ALARM_FUNCTION_API_GET_NEXT_SCHEDULED_DATE "getNextScheduledDate"
+#define ALARM_FUNCTION_API_GET_REMAINING_SECONDS "getRemainingSeconds"
+
+#endif
diff --git a/src/Alarm/plugin_initializer.cpp b/src/Alarm/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..56a7ac0
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+#include <TimeTracer.h>
+#include "JSAlarmManager.h"
+#include "JSAlarmAbsolute.h"
+#include "JSAlarmRelative.h"
+#include <Logger.h>
+#include <Security.h>
+#include "plugin_config.h"
+
+#define WRT_JS_EXTENSION_OBJECT_TIZEN "tizen"
+
+namespace DeviceAPI {
+namespace Alarm {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+AceSecurityStatus alarmAceCheckAccessFunction(const char* functionName)
+{
+    return ALARM_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerAlarmSetter,
+                                DeviceAPI::Common::SecurityAccessor,
+                                gSecurityAccessor);
+
+class_definition_options_t ClassOptions =
+{
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerAlarmSetter,
+    NULL,
+    NULL
+};
+
+class_definition_options_t ConstructorClassOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGI("[Tizen\\AlarmManager ] on_widget_start_callback (%d)", widgetId);
+    Try
+    {
+        TIME_TRACER_INIT();
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LOGE("WrtAccess initialization failed");
+    }
+
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, alarmAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGI("[Tizen\\AlarmManager ] on_widget_stop_callback (%d)", widgetId);
+    Try
+    {
+        TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"Alarm");
+        TIME_TRACER_RELEASE();
+       WrtAccessSingleton::Instance().deinitialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LOGE("WrtAccess deinitialization failed");
+    }
+
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(
+        WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "alarm",
+        (js_class_template_getter)DeviceAPI::Alarm::JSAlarmManager::getClassRef,
+        &ClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(
+    WRT_JS_EXTENSION_OBJECT_TIZEN,
+    TIZEN_ALARM_ABSOLUTE_INTERFACE,
+    (js_class_template_getter)DeviceAPI::Alarm::JSAlarmAbsolute::getClassRef,
+    reinterpret_cast<js_class_constructor_cb_t>(DeviceAPI::Alarm::JSAlarmAbsolute::constructor),
+    &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(
+    WRT_JS_EXTENSION_OBJECT_TIZEN,
+    TIZEN_ALARM_RELATIVE_INTERFACE,
+    (js_class_template_getter)DeviceAPI::Alarm::JSAlarmRelative::getClassRef,
+    reinterpret_cast<js_class_constructor_cb_t>(DeviceAPI::Alarm::JSAlarmRelative::constructor),
+    &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_END
+
+} // Alarm
+} // DeviceAPI
diff --git a/src/Application/AppManagerWrapper.cpp b/src/Application/AppManagerWrapper.cpp
new file mode 100755 (executable)
index 0000000..1eae637
--- /dev/null
@@ -0,0 +1,377 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AppManagerWrapper.h"
+#include "ApplicationUtil.h"
+#include <Commons/Exception.h>
+#include <Commons/Regex.h>
+
+// To get package id from appId
+#include <package_manager.h>
+#include <TimeTracer.h>
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+
+
+AppManagerWrapper::AppManagerWrapper() :
+    m_manager_handle(NULL),
+    m_watchIdAcc(0)
+{
+    LOGD("Entered");
+}
+
+AppManagerWrapper::~AppManagerWrapper()
+{
+    LOGD("Entered");
+    if (m_manager_handle != NULL)
+    {
+        unregisterAppListChangedCallbacks();
+    }
+}
+
+void AppManagerWrapper::registerAppListChangedCallbacks(
+        IAppManagerAppListChangedCallbacks *callbacks)
+{
+    LOGD("Entered");
+    if (callbacks == NULL)
+    {
+        LOGE("callback cannot be set to NULL.");
+        return;
+    }
+
+    if (!m_manager_handle)
+    {
+        registerAppListChangedCallbacks();
+    }
+
+    m_callbacks.insert(callbacks);
+}
+
+void AppManagerWrapper::unregisterAppListChangedCallbacks(
+        IAppManagerAppListChangedCallbacks *callbacks)
+{
+    LOGD("Entered");
+    if (callbacks == NULL)
+    {
+        LOGE("callback cannot be set to NULL.");
+        return;
+    }
+
+    if (m_callbacks.size() == 0)
+    {
+        LOGE("No callbacks are registered.");
+        return;
+    }
+
+    AppListChangedCallbacksSet::iterator iter = m_callbacks.find(callbacks);
+    if (iter == m_callbacks.end())
+    {
+        LOGE("Callback is not registered.");
+        return;
+    }
+
+    m_callbacks.erase(iter);
+
+    if (m_callbacks.size() == 0)
+    {
+        unregisterAppListChangedCallbacks();
+    }
+}
+
+
+long AppManagerWrapper::getWatchIdAndInc()
+{
+    LOGD("Entered");
+    return ++m_watchIdAcc;
+}
+
+
+bool AppManagerWrapper::app_callback(package_info_app_component_type_e comp_type,
+        const char *app_id,
+        void *user_data)
+{
+    LOGD("Entered");
+    if (app_id == NULL) {
+        LOGE("Callback is called. but no package name is passed. skip this request");
+        return true;
+    }
+
+    if (user_data == NULL) {
+        LOGE("user data is not exist. skip this request");
+        return true;
+    }
+
+    AppManagerWrapper *appManager = (AppManagerWrapper *)user_data;
+    appManager->applist.push_back(app_id);
+
+    return true;
+}
+
+void AppManagerWrapper::appListChangedCallback(app_info_event_e event_type,
+        const char *pkgId,
+        void *user_data)
+{
+    LOGD("Entered");
+    if (user_data == NULL) {
+        LOGE("user data is not exist. skip this request");
+        return;
+    }
+
+    AppManagerWrapper *appManager = (AppManagerWrapper *)user_data;
+
+    if (event_type == APP_INFO_EVENT_UNINSTALLED) {
+        for (size_t i = 0; i < appManager->applist.size(); i++) {
+            appListAppUninstalled(appManager->applist.at(i).c_str());
+        }
+    } else {
+        package_info_h package_info;
+
+        int ret = package_info_create(pkgId, &package_info);
+        if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "package_info_create()",
+                    ApplicationUtil::getApplicationPackageManagerMessage).c_str());
+            return;
+        }
+
+        ret = package_info_foreach_app_from_package(package_info,
+                PACKAGE_INFO_ALLAPP,
+                app_callback, user_data);
+        if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "package_info_foreach_app_from_package()",
+                    ApplicationUtil::getApplicationPackageManagerMessage).c_str());
+
+            ret = package_info_destroy(package_info);
+            if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "package_info_destroy()",
+                        ApplicationUtil::getApplicationPackageManagerMessage).c_str());
+            }
+            return;
+        }
+
+        ret = package_info_destroy(package_info);
+        if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "package_info_destroy()",
+                    ApplicationUtil::getApplicationPackageManagerMessage).c_str());
+        }
+
+        for (size_t i = 0; i < appManager->applist.size(); i++) {
+            switch(event_type)
+            {
+                case APP_INFO_EVENT_INSTALLED:
+                    appListAppInstalled(appManager->applist.at(i).c_str());
+                    break;
+                case APP_INFO_EVENT_UPDATED:
+                    appListAppUpdated(appManager->applist.at(i).c_str());
+                    break;
+                default:
+                    LOGE("app_manager listener gave wrong event_type : %d", event_type);
+                    break;
+            }
+        }
+    }
+
+    // clean-up applist
+    appManager->applist.clear();
+}
+
+
+void AppManagerWrapper::appListAppInstalled(const char *appId)
+{
+    LOGD("Entered");
+    AppListChangedCallbacksSet::iterator iter = m_callbacks.begin();
+    for (; iter != m_callbacks.end(); iter++)
+    {
+        (*iter)->onAppManagerEventInstalled(appId);
+    }
+}
+
+void AppManagerWrapper::appListAppUninstalled(const char *appId)
+{
+    LOGD("Entered");
+    AppListChangedCallbacksSet::iterator iter = m_callbacks.begin();
+    for (; iter != m_callbacks.end(); iter++)
+    {
+        (*iter)->onAppManagerEventUninstalled(appId);
+    }
+}
+
+void AppManagerWrapper::appListAppUpdated(const char *appId)
+{
+    LOGD("Entered");
+    AppListChangedCallbacksSet::iterator iter = m_callbacks.begin();
+    for (; iter != m_callbacks.end(); iter++)
+    {
+        (*iter)->onAppManagerEventUpdated(appId);
+    }
+}
+
+
+int AppManagerWrapper::app_list_changed_cb_broker(int id,
+        const char *type,
+        const char *package,
+        const char *key,
+        const char *val,
+        const void *msg,
+        void *data)
+{
+    LOGD("Entered");
+    static app_info_event_e event_type;
+
+    if (!strcasecmp(key, "start")) {
+        if (!strcasecmp(val, "install")) {
+            event_type = APP_INFO_EVENT_INSTALLED;
+        } else if (!strcasecmp(val, "uninstall"))    {
+            // After uninstallation, we cannot get app ids from package name.
+            // So, we have to store app ids which is included to target package.
+            package_info_h package_info;
+
+            int ret = package_info_create(package, &package_info);
+            if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "package_info_create()",
+                        ApplicationUtil::getApplicationPackageManagerMessage).c_str());
+            }
+
+            ret = package_info_foreach_app_from_package(package_info,
+                    PACKAGE_INFO_ALLAPP, app_callback, data);
+            if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "package_info_foreach_app_from_package()",
+                        ApplicationUtil::getApplicationPackageManagerMessage).c_str());
+            }
+
+            ret = package_info_destroy(package_info);
+            if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "package_info_destroy()",
+                        ApplicationUtil::getApplicationPackageManagerMessage).c_str());
+            }
+            event_type = APP_INFO_EVENT_UNINSTALLED;
+        } else if (!strcasecmp(val, "update")) {
+            event_type = APP_INFO_EVENT_UPDATED;
+        }
+    } else if (!strcasecmp(key, "end") && !strcasecmp(val, "ok"))    {
+        if (event_type >= 0) {
+            if (data != NULL) {
+                AppManagerWrapper *appManager = (AppManagerWrapper *)data;
+                appManager->appListChangedCallback(event_type, package, data);
+            }
+        }
+    }
+
+    return APP_MANAGER_ERROR_NONE;
+}
+
+
+void AppManagerWrapper::registerAppListChangedCallbacks()
+{
+    LOGD("Entered");
+    if (m_manager_handle != NULL) {
+        LOGW("Callback is already registered.");
+        return;
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(addAppInfoEventListener)pkgmgr_client_new", 0);
+    m_manager_handle = pkgmgr_client_new(PC_LISTENING);
+    TIME_TRACER_ITEM_END("(addAppInfoEventListener)pkgmgr_client_new", 0);
+    if (NULL == m_manager_handle) {
+        LOGE("pkgmgr_client: NULL");
+        ApplicationUtil::throwApplicationException<InvalidArgumentException>(
+                PKGMGR_R_ERROR,
+                "pkgmgr_client_new()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage);
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(addAppInfoEventListener)pkgmgr_client_listen_status", 0);
+    int request_id = pkgmgr_client_listen_status(m_manager_handle,
+            app_list_changed_cb_broker,
+            this);
+    TIME_TRACER_ITEM_END("(addAppInfoEventListener)pkgmgr_client_listen_status", 0);
+    if (request_id < 0) {
+        LOGE("ret: %d", request_id);
+        ApplicationUtil::throwApplicationException<PlatformException>(request_id,
+                "pkgmgr_client_listen_status()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage);
+    }
+}
+
+void AppManagerWrapper::unregisterAppListChangedCallbacks()
+{
+    LOGD("Entered");
+    if (m_manager_handle == NULL) {
+        LOGE("No callback is registered");
+        return;
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(removeAppInfoEventListener)pkgmgr_client_free", 0);
+    int ret = pkgmgr_client_free(m_manager_handle);
+    if (PKGMGR_R_OK != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "pkgmgr_client_free()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+    }
+    TIME_TRACER_ITEM_END("(removeAppInfoEventListener)pkgmgr_client_free", 0);
+    m_manager_handle = NULL;
+}
+
+bool AppManagerWrapper::initializeAppInfo(ApplicationInformationPtr &appInfo)
+{
+    LOGD("Entered");
+    pkgmgr_client *pc = NULL;
+    int ret = 0;
+
+    do {
+        // get installed size from package server (to solve smack issue)
+        pc = pkgmgr_client_new(PC_REQUEST);
+        if (!pc) {
+            LOGE("pc: NULL");
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(PKGMGR_R_ERROR,
+                    "pkgmgr_client_new()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+            break;
+        }
+        ret = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE,
+            PM_GET_TOTAL_SIZE, pc, NULL, appInfo->getPackageId().c_str(),
+                NULL, NULL, NULL);
+        if (ret < 0) {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgr_client_request_service()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+            break;
+        }
+        appInfo->setInstallSize(ret);
+    } while (false);
+
+    pkgmgr_client_free(pc);
+    appInfo->setInitialize();
+    return true;
+}
+
+SINGLETON_IMPLEMENTATION(AppManagerWrapper)
+
+} // Application
+} // DeviceAPI
diff --git a/src/Application/AppManagerWrapper.h b/src/Application/AppManagerWrapper.h
new file mode 100755 (executable)
index 0000000..f019813
--- /dev/null
@@ -0,0 +1,107 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_PLATFORM_APPLICATION_APP_MANAGER_WRAPPER_H_
+#define TIZENAPIS_PLATFORM_APPLICATION_APP_MANAGER_WRAPPER_H_
+
+#include <string>
+#include <map>
+#include <set>
+#include <memory>
+
+#include <app_manager.h>
+#include <package-manager.h>
+#include <package_manager.h>
+#include <package_info.h>
+
+#include "ApplicationInformation.h"
+
+// To get app size and installed time
+#include <pkgmgr-info.h>
+
+#include <Singleton.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+
+class IAppManagerAppListChangedCallbacks
+{
+public:
+    friend class AppManagerWrapper;
+
+    IAppManagerAppListChangedCallbacks() {}
+    ~IAppManagerAppListChangedCallbacks() {}
+
+protected:
+    virtual void onAppManagerEventInstalled(const char *appId) = 0;
+    virtual void onAppManagerEventUninstalled(const char *appId) = 0;
+    virtual void onAppManagerEventUpdated(const char *appId) = 0;
+};
+
+class DLL_EXPORT AppManagerWrapper
+{
+public:
+    AppManagerWrapper();
+    virtual ~AppManagerWrapper();
+
+    // Can throw InvalidArgumentException or PlatformException
+    void registerAppListChangedCallbacks(IAppManagerAppListChangedCallbacks *callbacks);
+
+    // No throws
+    void unregisterAppListChangedCallbacks(IAppManagerAppListChangedCallbacks *callbacks);
+
+    long getWatchIdAndInc();
+
+    bool initializeAppInfo(ApplicationInformationPtr &appInfo);
+
+private:
+
+    static bool app_callback(package_info_app_component_type_e comp_type,
+            const char *app_id, void *user_data);
+    void appListChangedCallback(app_info_event_e event_type,
+            const char *pkgId, void *user_data);
+    static int app_list_changed_cb_broker(int id, const char *type, const char *package,
+            const char *key, const char *val, const void *msg, void *data);
+
+    void appListAppInstalled(const char *appId);
+    void appListAppUninstalled(const char *appId);
+    void appListAppUpdated(const char *appId);
+
+    void registerAppListChangedCallbacks();
+    void unregisterAppListChangedCallbacks();
+
+    typedef std::set<IAppManagerAppListChangedCallbacks *> AppListChangedCallbacksSet;
+    AppListChangedCallbacksSet m_callbacks;
+    pkgmgr_client *m_manager_handle;
+    long m_watchIdAcc;
+    std::string m_curr_app_id;
+
+public:
+    std::vector<std::string> applist;
+
+public:
+    friend class AppManagerWrapperSingleton;
+};
+
+SINGLETON_DEFINITION(AppManagerWrapper)
+
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_PLATFORM_APPLICATION_APP_MANAGER_WRAPPER_H_
diff --git a/src/Application/Application.cpp b/src/Application/Application.cpp
new file mode 100755 (executable)
index 0000000..3679281
--- /dev/null
@@ -0,0 +1,213 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "Application.h"
+
+#include <bundle.h>
+#include <app.h>
+#include <app_control.h>
+#include <app_control_internal.h>
+
+#include "ApplicationControlData.h"
+#include "ApplicationControl.h"
+#include "ApplicationManager.h"
+#include "ApplicationUtil.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+Application::Application()
+{
+    LOGD("Entered");
+}
+
+Application::~Application()
+{
+    LOGD("Entered");
+}
+
+std::string Application::getContextId() const
+{
+    LOGD("Entered");
+    return m_contextId;
+}
+
+void Application::setContextId(const std::string &id)
+{
+    LOGD("Entered");
+    m_contextId = id;
+}
+
+ApplicationInformationPtr Application::getAppInfo() const
+{
+    LOGD("Entered");
+    return m_appInfo;
+}
+
+void Application::setAppInfo(ApplicationInformationPtr& appInfo)
+{
+    LOGD("Entered");
+    m_appInfo = appInfo;
+}
+
+void Application::getRequestedAppControl(
+        const EventApplicationGetRequestedAppControlPtr& event)
+{
+    LOGD("Entered");
+    Try
+    {
+        int ret = 0;
+
+        std::string bundle_str = event->getEncodedBundle();
+
+        app_control_h service = NULL;
+        char* tmpStr = NULL;
+
+        bundle *request_bundle = bundle_decode((bundle_raw*)bundle_str.c_str(),
+                bundle_str.length());
+        ret = app_control_create_event(request_bundle, &service);
+        if (APP_CONTROL_ERROR_NONE != ret)
+        {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_create_event()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
+            bundle_free(request_bundle);
+            return;
+        }
+        bundle_free(request_bundle);
+
+        ApplicationControlPtr appControl(new ApplicationControl());
+        appControl->setService_h(service);
+
+        ret = app_control_get_operation(service, &tmpStr);
+        if ((APP_CONTROL_ERROR_NONE == ret) && (NULL != tmpStr)) {
+            appControl->setOperation(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        } else {
+            if (NULL == tmpStr) {
+                LOGW("app_control_get_operation() returned NULL operation");
+            }
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_get_operation()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        ret = app_control_get_uri(service, &tmpStr);
+        if ((APP_CONTROL_ERROR_NONE == ret) && (NULL != tmpStr)) {
+            appControl->setUri(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        } else {
+            if (NULL == tmpStr) {
+                LOGW("app_control_get_uri() returned NULL operation");
+            }
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_get_uri()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        ret = app_control_get_mime(service, &tmpStr);
+        if ((APP_CONTROL_ERROR_NONE == ret)  && (NULL != tmpStr)) {
+            appControl->setMime(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        } else {
+            if (NULL == tmpStr) {
+                LOGW("app_control_get_mime() returned NULL operation");
+            }
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_get_mime()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        ret = app_control_get_category(service, &tmpStr);
+        if ((APP_CONTROL_ERROR_NONE == ret)  && (NULL != tmpStr))
+        {
+            appControl->setCategory(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        } else {
+            if (NULL == tmpStr) {
+                LOGW("app_control_get_category() returned NULL operation");
+            }
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_get_category()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        std::vector<ApplicationControlDataPtr> appControlDataArray;
+        ret = app_control_foreach_extra_data(service,
+                ApplicationManager::service_extra_data_callback, &appControlDataArray);
+        if (APP_CONTROL_ERROR_NONE != ret)
+        {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_foreach_extra_data()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
+        }
+        else
+        {
+            appControl->setAppControlDataArray(appControlDataArray);
+        }
+
+        RequestedApplicationControlPtr appCtrMgr(new RequestedApplicationControl());
+        appCtrMgr->setAppControl(appControl);
+
+        // add caller id
+        ret = app_control_get_caller(service, &tmpStr);
+        if ((APP_CONTROL_ERROR_NONE == ret) && (NULL != tmpStr))
+        {
+            appCtrMgr->setCallerAppId(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        } else {
+            if (NULL == tmpStr) {
+                LOGW("app_control_get_caller() returned NULL operation");
+            }
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_get_caller()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+                event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+            }
+        }
+        event->setRequestedAppControl(appCtrMgr);
+
+    }
+    Catch (WrtDeviceApis::Commons::Exception)
+    {
+        LOGE("Error on getAppControl : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+}
+
+}
+}
diff --git a/src/Application/Application.h b/src/Application/Application.h
new file mode 100644 (file)
index 0000000..8e5d944
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_H_
+#define TIZENAPIS_API_APPLICATION_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+#include "ApplicationInformation.h"
+#include "EventApplicationGetRequestedAppControl.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class Application;
+typedef std::shared_ptr<Application> ApplicationPtr;
+
+class Application
+{
+  public:
+    Application();
+    ~Application();
+
+    std::string getContextId() const;
+    void setContextId(const std::string &id);
+    ApplicationInformationPtr getAppInfo() const;
+    void setAppInfo(ApplicationInformationPtr &appInfo);
+
+    void getRequestedAppControl(const EventApplicationGetRequestedAppControlPtr& event);
+
+  private:
+    ApplicationInformationPtr m_appInfo;
+    std::string m_contextId;
+};
+
+}
+}
+
+#endif
diff --git a/src/Application/ApplicationAsyncCallbackManager.cpp b/src/Application/ApplicationAsyncCallbackManager.cpp
new file mode 100755 (executable)
index 0000000..f48124a
--- /dev/null
@@ -0,0 +1,27 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "ApplicationAsyncCallbackManager.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+SINGLETON_IMPLEMENTATION(ApplicationAsyncCallbackManager)
+
+} // Application
+} // DeviceAPI
diff --git a/src/Application/ApplicationAsyncCallbackManager.h b/src/Application/ApplicationAsyncCallbackManager.h
new file mode 100644 (file)
index 0000000..7c57339
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_APPLICATION_ASYNC_CALLBACK_MANAGER_H_
+#define _TIZEN_APPLICATION_ASYNC_CALLBACK_MANAGER_H_
+
+#include <AsyncCallbackManager.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationAsyncCallbackManager : public DeviceAPI::Common::AsyncCallbackManager
+{
+private:
+    ApplicationAsyncCallbackManager()
+    {
+        LOGD("Entered");
+    }
+
+public:
+    virtual ~ApplicationAsyncCallbackManager()
+    {
+        LOGD("Entered");
+    }
+
+    friend class ApplicationAsyncCallbackManagerSingleton;
+};
+
+SINGLETON_DEFINITION(ApplicationAsyncCallbackManager)
+
+} // Application
+} // DeviceAPI
+
+#endif // _TIZEN_APPLICATION_ASYNC_CALLBACK_MANAGER_H_
diff --git a/src/Application/ApplicationCert.cpp b/src/Application/ApplicationCert.cpp
new file mode 100644 (file)
index 0000000..e6b1cd8
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ApplicationCert.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+ApplicationCert::ApplicationCert()
+{
+    LOGD("Entered");
+}
+
+ApplicationCert::~ApplicationCert()
+{
+    LOGD("Entered");
+}
+
+std::string ApplicationCert::getType() const
+{
+    LOGD("Entered");
+    return m_type;
+}
+
+void ApplicationCert::setType(const std::string &type)
+{
+    LOGD("Entered");
+    m_type = type;
+}
+
+std::string ApplicationCert::getValue() const
+{
+    LOGD("Entered");
+    return m_value;
+}
+
+void ApplicationCert::setValue(const std::string &value)
+{
+    LOGD("Entered");
+    m_value = value;
+}
+
+}
+}
diff --git a/src/Application/ApplicationCert.h b/src/Application/ApplicationCert.h
new file mode 100644 (file)
index 0000000..d2afc75
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_CERT_H_
+#define TIZENAPIS_API_APPLICATION_CERT_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationCert;
+typedef std::shared_ptr<ApplicationCert> ApplicationCertPtr;
+
+typedef std::vector<ApplicationCertPtr> ApplicationCertArray;
+typedef std::shared_ptr<ApplicationCertArray> ApplicationCertArrayPtr;
+
+
+class ApplicationCert
+{
+  public:
+    ApplicationCert();
+    ~ApplicationCert();
+
+    std::string getType() const;
+    void setType(const std::string &type);
+    std::string getValue() const;
+    void setValue(const std::string &value);
+
+  private:
+    std::string m_type;
+    std::string m_value;
+};
+}
+}
+#endif
diff --git a/src/Application/ApplicationContext.cpp b/src/Application/ApplicationContext.cpp
new file mode 100755 (executable)
index 0000000..7c5f2d2
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "ApplicationContext.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+ApplicationContext::ApplicationContext()
+{
+    LOGD("Entered");
+}
+
+ApplicationContext::~ApplicationContext()
+{
+    LOGD("Entered");
+}
+
+std::string ApplicationContext::getAppId() const
+{
+    LOGD("Entered");
+    return m_appId;
+}
+void ApplicationContext::setAppId(const std::string &appId)
+{
+    LOGD("Entered");
+    m_appId = appId;
+}
+
+std::string ApplicationContext::getContextId() const
+{
+    LOGD("Entered");
+    return m_contextId;
+}
+void ApplicationContext::setContextId(const std::string &contextId)
+{
+    LOGD("Entered");
+    m_contextId = contextId;
+}
+
+
+}
+}
diff --git a/src/Application/ApplicationContext.h b/src/Application/ApplicationContext.h
new file mode 100755 (executable)
index 0000000..8256e3a
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_CONTEXT_H_
+#define TIZENAPIS_API_APPLICATION_CONTEXT_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationContext;
+typedef std::shared_ptr<ApplicationContext> ApplicationContextPtr;
+
+typedef std::vector<ApplicationContextPtr> ApplicationContextArray;
+typedef std::shared_ptr<ApplicationContextArray> ApplicationContextArrayPtr;
+
+class ApplicationContext
+{
+  public:
+    ApplicationContext();
+    ~ApplicationContext();
+
+    std::string getAppId() const;
+    void setAppId(const std::string &appId);
+    std::string getContextId() const;
+    void setContextId(const std::string &contextId);
+
+
+  private:
+    std::string m_appId;
+    std::string m_contextId;
+
+};
+}
+}
+#endif
diff --git a/src/Application/ApplicationControl.cpp b/src/Application/ApplicationControl.cpp
new file mode 100755 (executable)
index 0000000..c77e506
--- /dev/null
@@ -0,0 +1,253 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+/**
+ * @file        ApplicationControl.cpp
+ * @version     0.1
+ */
+
+#include "ApplicationControl.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+namespace {
+const char* TIZEN_APPLICATION_CONTROL_OPERATION_VIEW = "http://tizen.org/appcontrol/operation/view";
+const char* TIZEN_APPLICATION_CONTROL_OPERATION_CALL = "http://tizen.org/appcontrol/operation/call";
+const char* TIZEN_APPLICATION_CONTROL_OPERATION_PICK = "http://tizen.org/appcontrol/operation/pick";
+const char* TIZEN_APPLICATION_CONTROL_OPERATION_CREATE_CONTENT = "http://tizen.org/appcontrol/operation/create_content";
+const char* TIZEN_APPLICATION_CONTROL_OPERATION_DIAL = "http://tizen.org/appcontrol/operation/dial";
+const char* TIZEN_APPLICATION_CONTROL_OPERATION_SHARE = "http://tizen.org/appcontrol/operation/share";
+const char* TIZEN_APPLICATION_CONTROL_OPERATION_MULTI_SHARE = "http://tizen.org/appcontrol/operation/multi_share";
+}
+
+ApplicationControl::ApplicationControl() :
+    m_appControl(NULL)
+{
+    LOGD("Entered");
+}
+
+ApplicationControl::ApplicationControl(const std::string &op, const std::string &uri,
+        const std::string &mime, const std::string &category,
+        std::vector<ApplicationControlDataPtr> &dataArray) :
+    m_appControl(NULL)
+{
+    LOGD("Entered");
+    m_operation = op;
+    m_uri = uri;
+    m_mime = mime;
+    m_category = category;
+    m_appControlDataArray = dataArray;
+}
+
+ApplicationControl::~ApplicationControl()
+{
+    LOGD("Entered");
+}
+
+std::string ApplicationControl::getOperation() const
+{
+    LOGD("Entered");
+    return m_operation;
+}
+
+void ApplicationControl::setOperation(const std::string &operation)
+{
+    LOGD("Entered");
+    m_operation = operation;
+}
+
+std::string ApplicationControl::getUri() const
+{
+    LOGD("Entered");
+    return m_uri;
+}
+
+void ApplicationControl::setUri(const std::string &uri)
+{
+    LOGD("Entered");
+    m_uri = uri;
+}
+
+std::string ApplicationControl::getMime() const
+{
+    LOGD("Entered");
+    return m_mime;
+}
+
+void ApplicationControl::setMime(const std::string &mime)
+{
+    LOGD("Entered");
+    m_mime = mime;
+}
+
+std::string ApplicationControl::getCategory() const
+{
+    LOGD("Entered");
+    return m_category;
+}
+
+void ApplicationControl::setCategory(const std::string &category)
+{
+    LOGD("Entered");
+    m_category = category;
+}
+
+std::vector<ApplicationControlDataPtr> ApplicationControl::getAppControlDataArray() const
+{
+    LOGD("Entered");
+    return m_appControlDataArray;
+}
+
+void ApplicationControl::setAppControlDataArray(
+        const std::vector<ApplicationControlDataPtr> &dataArray)
+{
+    LOGD("Entered");
+    m_appControlDataArray = dataArray;
+}
+
+void ApplicationControl::addAppControlData(const ApplicationControlDataPtr &data)
+{
+    LOGD("Entered");
+    m_appControlDataArray.push_back(data);
+
+}
+
+app_control_h ApplicationControl::getService_h() const
+{
+    LOGD("Entered");
+    return m_appControl;
+}
+
+void ApplicationControl::setService_h(const app_control_h service)
+{
+    LOGD("Entered");
+    m_appControl = service;
+}
+
+
+#if 0
+void ApplicationControl::replyResult(
+        std::vector<ApplicationControlDataPtr> &appControlDataArray)
+{
+    LOGD("Entered");
+    app_control_h reply;
+
+    int ret = app_control_create(&reply);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_create()",
+                ApplicationUtil::getApplicationMessage).c_str());
+    }
+    const char* key = NULL;
+    const char** arr = NULL;
+
+    if (!appControlDataArray.empty())
+    {
+        LOGD("appControlDataArray.size() : %d", appControlDataArray.size());
+        for (size_t i = 0; i < appControlDataArray.size(); ++i) {
+            key = appControlDataArray.at(i)->getKey().c_str();
+            std::vector<std::string> valueArray = appControlDataArray.at(i)->getValue();
+
+            arr = (const char**) calloc (sizeof(char*), valueArray.size());
+
+            for (size_t j = 0; j < valueArray.size(); j++) {
+                arr[j] = valueArray.at(j).c_str();
+            }
+            ret = app_control_add_extra_data_array(reply, key, arr, valueArray.size());
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_add_extra_data_array()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+    } else {
+        LOGE("appControlDataArray is empty");
+    }
+
+    ret = app_control_reply_to_launch_request(reply, m_appControl,
+            APP_CONTROL_RESULT_SUCCEEDED);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_reply_to_launch_request()",
+                ApplicationUtil::getApplicationMessage).c_str());
+    }
+
+    ret = app_control_destroy(reply);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_destroy()",
+                ApplicationUtil::getApplicationMessage).c_str());
+    }
+
+    if (arr) {
+        free (arr);
+    }
+
+}
+
+void ApplicationControl::replyFailure()
+{
+    LOGD("Entered");
+    app_control_h reply;
+    int ret = app_control_create(&reply);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_create()",
+                ApplicationUtil::getApplicationMessage).cstr());
+    }
+
+    LOGE("==[replyFailure] enter ApplicationControl::replyFailure");
+    ret = app_control_reply_to_launch_request(reply, m_appControl,
+            APP_CONTROL_RESULT_FAILED);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_reply_to_launch_request()",
+                ApplicationUtil::getApplicationMessage).c_str());
+    }
+
+    ret = app_control_destroy(reply);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_destroy()",
+                ApplicationUtil::getApplicationMessage).c_str());
+    }
+}
+#endif
+
+bool ApplicationControl::isValid()
+{
+    LOGD("Entered");
+    if (m_operation == TIZEN_APPLICATION_CONTROL_OPERATION_VIEW ||
+            m_operation == TIZEN_APPLICATION_CONTROL_OPERATION_SHARE) {
+        if (m_uri.empty()) {
+            return false;
+        }
+    } else if (m_operation == TIZEN_APPLICATION_CONTROL_OPERATION_MULTI_SHARE) {
+        if (m_appControlDataArray.size() == 0) {
+            return false;
+        }
+    }
+
+    return true;
+}
+
+
+}
+}
diff --git a/src/Application/ApplicationControl.h b/src/Application/ApplicationControl.h
new file mode 100755 (executable)
index 0000000..4d08f02
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_CONTROL_H_
+#define TIZENAPIS_API_APPLICATION_CONTROL_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <app_control.h>
+#include "ApplicationControlData.h"
+#include <Export.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationControl;
+typedef std::shared_ptr<ApplicationControl> ApplicationControlPtr;
+
+/* This object represents a single extra data for service request and reply */
+class DLL_EXPORT ApplicationControl
+{
+  public:
+    ApplicationControl();
+    ApplicationControl(const std::string &op, const std::string &uri,
+            const std::string &mime,
+            const std::string &category,
+            std::vector<ApplicationControlDataPtr> &dataArray) ;
+    ~ApplicationControl();
+
+    std::string getOperation() const;
+    void setOperation(const std::string &operation);
+
+    std::string getUri() const;
+    void setUri(const std::string &uri);
+
+    std::string getMime() const;
+    void setMime(const std::string &uri);
+
+    std::string getCategory() const;
+    void setCategory(const std::string &category);
+
+    std::vector<ApplicationControlDataPtr> getAppControlDataArray() const;
+    void setAppControlDataArray(const std::vector<ApplicationControlDataPtr> &dataArray);
+    void addAppControlData(const ApplicationControlDataPtr &data);
+
+    app_control_h getService_h() const;
+    void setService_h(const app_control_h service);
+
+    bool isValid();
+
+#if 0
+    void replyResult(std::vector<ApplicationControlDataPtr> &appControlDataArray);
+    void replyFailure();
+#endif
+
+  private:
+    std::string m_operation;
+    std::string m_uri;
+    std::string m_mime;
+    std::string m_category;
+    std::vector<ApplicationControlDataPtr> m_appControlDataArray;
+    app_control_h m_appControl;
+};
+}
+}
+#endif
diff --git a/src/Application/ApplicationControlData.cpp b/src/Application/ApplicationControlData.cpp
new file mode 100644 (file)
index 0000000..b43c528
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "ApplicationControlData.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+ApplicationControlData::ApplicationControlData()
+{
+    LOGD("Entered");
+}
+
+ApplicationControlData::~ApplicationControlData()
+{
+    LOGD("Entered");
+    //nothing to do in destructor
+}
+
+std::string ApplicationControlData::getKey() const
+{
+    LOGD("Entered");
+    return m_key;
+}
+
+void ApplicationControlData::setKey(const std::string &key)
+{
+    LOGD("Entered");
+    m_key = key;
+}
+
+std::vector<std::string> ApplicationControlData::getValue() const
+{
+    LOGD("Entered");
+    return m_value;
+}
+void ApplicationControlData::setValue(const std::vector<std::string> &value)
+{
+    LOGD("Entered");
+    m_value = value;
+}
+
+}
+}
diff --git a/src/Application/ApplicationControlData.h b/src/Application/ApplicationControlData.h
new file mode 100755 (executable)
index 0000000..b712ce0
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_CONTROL_DATA_H_
+#define TIZENAPIS_API_APPLICATION_CONTROL_DATA_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <Export.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationControlData;
+typedef std::shared_ptr<ApplicationControlData> ApplicationControlDataPtr;
+
+typedef std::vector<ApplicationControlDataPtr> ApplicationControlDataArray;
+typedef std::shared_ptr<ApplicationControlDataArray> ApplicationControlDataArrayPtr;
+
+/* This object represents a single extra data for app control request and reply */
+class DLL_EXPORT ApplicationControlData
+{
+  public:
+    ApplicationControlData();
+    ~ApplicationControlData();
+
+    std::string getKey() const;
+    void setKey(const std::string &key);
+
+    std::vector<std::string> getValue() const;
+    void setValue(const std::vector<std::string> &value);
+
+  private:
+    std::string m_key;
+    std::vector<std::string>    m_value;
+};
+}
+}
+#endif
diff --git a/src/Application/ApplicationController.cpp b/src/Application/ApplicationController.cpp
new file mode 100755 (executable)
index 0000000..6f2b89e
--- /dev/null
@@ -0,0 +1,672 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <TimeTracer.h>
+#include "ApplicationController.h"
+#include "ApplicationConverter.h"
+#include "JSApplicationEventCallbackManager.h"
+#include "ApplicationAsyncCallbackManager.h"
+#include "ApplicationInformationEventPrivateData.h"
+
+// to unset event callback for kill() API
+#include <app_manager.h>
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+ApplicationController::ApplicationController(JSContextRef context,
+        IApplicationManagerPtr application) :
+    EventApplicationLaunchEventAnswerReceiver(ThreadEnum::NULL_THREAD),
+    EventApplicationKillEventAnswerReceiver(ThreadEnum::NULL_THREAD),
+    EventApplicationLaunchAppControlEventAnswerReceiver(ThreadEnum::NULL_THREAD),
+    EventApplicationLaunchAppControlReplyEventAnswerReceiver(ThreadEnum::NULL_THREAD),
+    EventApplicationFindAppControlEventAnswerReceiver(ThreadEnum::NULL_THREAD),
+    EventApplicationGetAppsContextEventAnswerReceiver(ThreadEnum::NULL_THREAD),
+    EventApplicationGetAppsInfoEventAnswerReceiver(ThreadEnum::NULL_THREAD),
+    EventApplicationAppInfoEventListenerListener(ThreadEnum::NULL_THREAD),
+    SecurityAccessor(),
+    ApplicationPrivObject(context, application)
+{
+    LOGD("Entered");
+    if (!application) {
+        LOGE("controller has no application object");
+    }
+}
+
+ApplicationController::~ApplicationController()
+{
+    LOGD("Entered");
+}
+
+void ApplicationController::OnAnswerReceived(
+        const EventApplicationLaunchPtr &event)
+{
+    LOGD("Entered");
+    ApplicationAsyncAnswerHandler::launch(event);
+    TIME_TRACER_ITEM_END("launch(async)", 0);
+}
+
+void ApplicationController::OnAnswerReceived(
+        const EventApplicationKillPtr &event)
+{
+    LOGD("Entered");
+    ApplicationAsyncAnswerHandler::kill(event);
+    //TIME_TRACER_ITEM_END("kill(async)", 0);
+}
+
+void ApplicationController::OnAnswerReceived(
+        const EventApplicationLaunchAppControlPtr &event)
+{
+    LOGD("Entered");
+    ApplicationAsyncAnswerHandler::launchAppControl(event);
+    TIME_TRACER_ITEM_END("launchAppControl(async)", 0);
+}
+
+void ApplicationController::OnAnswerReceived(
+        const EventApplicationLaunchAppControlReplyPtr &event)
+{
+    LOGD("Entered");
+    ApplicationAsyncAnswerHandler::launchAppControlReply(event);
+    TIME_TRACER_ITEM_END("launchAppControlReply(async)", 0);
+}
+
+void ApplicationController::OnAnswerReceived(
+        const EventApplicationFindAppControlPtr &event)
+{
+    LOGD("Entered");
+    ApplicationAsyncAnswerHandler::findAppControl(event);
+    TIME_TRACER_ITEM_END("findAppControl(async)", 0);
+}
+
+void ApplicationController::OnAnswerReceived(
+        const EventApplicationGetAppsContextPtr &event)
+{
+    LOGD("Entered");
+    ApplicationAsyncAnswerHandler::getAppsContext(event);
+    TIME_TRACER_ITEM_END("getAppsContext(async)", 0);
+}
+
+void ApplicationController::OnAnswerReceived(
+        const EventApplicationGetAppsInfoPtr &event)
+{
+    LOGD("Entered");
+    ApplicationAsyncAnswerHandler::getAppsInfo(event);
+    TIME_TRACER_ITEM_END("getAppsInfo(async)", 0);
+}
+
+void ApplicationController::onAnswerReceived(
+        const EventApplicationAppInfoEventListenerPtr &event)
+{
+    LOGD("Entered");
+    ApplicationAsyncAnswerHandler::eventListener(event);
+}
+
+void ApplicationAsyncAnswerHandler::launch(
+        const EventApplicationLaunchPtr &event)
+{
+    LOGD("Entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager>(event->getPrivateData());
+    if (!callbackManager) {
+        LOGE("no callback manager");
+        return;
+    }
+
+    ApplicationAsyncCallbackManagerSingleton::Instance().unregisterCallbackManager(
+            callbackManager);
+    if (callbackManager->getOnSuccess()==NULL && callbackManager->getOnError()==NULL)
+    {
+        LOGD("Callback was not registered or context has been already expired.");
+        return;
+    }
+
+    if (event->checkCancelled()) {
+        LOGD("Operation cancelled");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+
+    JSValueRef error = NULL;
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::InvalidArgumentException:
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::NOT_FOUND_ERROR, "given app id is not found");
+            break;
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        return;
+    }
+
+    Try {
+        callbackManager->callOnSuccess();
+        LOGD("launch success callback called");
+        return;
+    } Catch(Exception) {
+        LOGE("error during processing answer %s", _rethrown_exception.GetMessage().c_str());
+        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+
+        callbackManager->callOnError(error);
+        LOGD("launch error callback called");
+        return;
+    }
+}
+
+void ApplicationAsyncAnswerHandler::kill(const EventApplicationKillPtr &event)
+{
+    LOGD("Entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager>(event->getPrivateData());
+    if (!callbackManager) {
+        LOGE("no callback manager");
+        return;
+    }
+
+    ApplicationAsyncCallbackManagerSingleton::Instance().unregisterCallbackManager(
+            callbackManager);
+    if (callbackManager->getOnSuccess()==NULL && callbackManager->getOnError()==NULL)
+    {
+        LOGD("Callback was not registered or context has been already expired.");
+        return;
+    }
+
+    if (event->checkCancelled()) {
+        LOGD("Operation cancelled");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+
+    JSValueRef error = NULL;
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::NOT_FOUND_ERROR,"given package is not found");
+            break;
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"platform exception");
+            break;
+        case ExceptionCodes::InvalidArgumentException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "invalid value");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        LOGD("kill error callback called");
+        return;
+    }
+
+    Try {
+        callbackManager->callOnSuccess();
+        LOGD("kill success callback called");
+        return;
+    } Catch(Exception) {
+        LOGE("error during processing answer %s", _rethrown_exception.GetMessage().c_str());
+        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+
+        callbackManager->callOnError(error);
+        LOGD("kill error callback called");
+        return;
+    }
+}
+
+void ApplicationAsyncAnswerHandler::launchAppControl(
+        const EventApplicationLaunchAppControlPtr &event)
+{
+    LOGD("Entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager>(event->getPrivateData());
+    if (!callbackManager) {
+        LOGE("no callback manager");
+        return;
+    }
+
+    ApplicationAsyncCallbackManagerSingleton::Instance().unregisterCallbackManager(callbackManager);
+    if (callbackManager->getOnSuccess()==NULL && callbackManager->getOnError()==NULL)
+    {
+        LOGD("Callback was not registered or context has been already expired.");
+        return;
+    }
+
+    if (event->checkCancelled()) {
+        LOGD("Operation cancelled");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+
+    JSValueRef error = NULL;
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::InvalidArgumentException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR,"Argument is not valid");
+            break;
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::NOT_FOUND_ERROR,"given package is not found");
+            break;
+        case ExceptionCodes::SecurityException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::SECURITY_ERROR,"This app is not permitted to launch this operation");
+            break;
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"platform exception");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        LOGD("launchAppControl error callback called");
+        return;
+    }
+
+    Try {
+        callbackManager->callOnSuccess();
+        LOGD("launchAppControl success callback called");
+        return;
+    } Catch(Exception) {
+        LOGE("error during processing answer %s", _rethrown_exception.GetMessage().c_str());
+        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+
+        callbackManager->callOnError(error);
+        LOGD("launchAppControl error callback called");
+        return;
+    }
+}
+
+void ApplicationAsyncAnswerHandler::launchAppControlReply(
+        const EventApplicationLaunchAppControlReplyPtr &event)
+{
+    LOGD("Entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager>(event->getPrivateData());
+    if (!callbackManager) {
+        LOGE("no callback manager");
+        return;
+    }
+
+    ApplicationAsyncCallbackManagerSingleton::Instance().unregisterCallbackManager(
+            callbackManager);
+    if (callbackManager->getOnSuccess()==NULL && callbackManager->getOnError()==NULL)
+    {
+        LOGD("Callback was not registered or context has been already expired.");
+        return;
+    }
+
+    if (event->checkCancelled()) {
+        LOGD("Operation cancelled");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        callbackManager->callOnError();
+        LOGD("launchAppControl reply failure callback called");
+        return;
+    }
+
+    Try {
+        ApplicationControlDataArrayPtr appControlDataArray = event->getAppControlDataArray();
+        if (appControlDataArray.get() == NULL)
+        {
+            ThrowMsg(WrtDeviceApis::Commons::UnknownException, "No reply");
+        }
+
+        ApplicationConverterFactory::ConverterType converter =
+            ApplicationConverterFactory::getConverter(gContext);
+        JSValueRef result = converter->toJSValueRef(*appControlDataArray);
+
+        callbackManager->callOnSuccess(result);
+        LOGD("launchAppControl reply return callback called");
+        return;
+    } Catch(Exception) {
+        callbackManager->callOnError();
+        LOGD("launchAppControl reply failure callback called");
+        return;
+    }
+}
+
+void ApplicationAsyncAnswerHandler::findAppControl(
+        const EventApplicationFindAppControlPtr &event)
+{
+    LOGD("Entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager>(event->getPrivateData());
+    if (!callbackManager) {
+        LOGE("no callback manager");
+        return;
+    }
+
+    ApplicationAsyncCallbackManagerSingleton::Instance().unregisterCallbackManager(
+            callbackManager);
+    if (callbackManager->getOnSuccess()==NULL && callbackManager->getOnError()==NULL)
+    {
+        LOGD("Callback was not registered or context has been already expired.");
+        return;
+    }
+
+    if (event->checkCancelled()) {
+        LOGD("Operation cancelled");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+
+    JSValueRef error = NULL;
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::InvalidArgumentException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR,"Argument is not valid");
+            break;
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::NOT_FOUND_ERROR,"given package is not found");
+            break;
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"platform exception");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        LOGD("findAppControl error callback called");
+        return;
+    }
+
+    Try {
+        ApplicationInformationArrayPtr appInfos = event->getAppInfos();
+        ApplicationControlPtr appControl = event->getAppControl();
+
+        ApplicationConverter converter(gContext, event.get());
+
+        JSValueRef result[2];
+        result[0] = converter.toJSValueRef(appInfos);
+        result[1] = converter.toJSValueRef(appControl);
+
+        callbackManager->callOnSuccess(result, 2);
+        LOGD("findAppControl success callback called");
+        return;
+    } Catch(Exception) {
+        LOGE("error during processing answer %s", _rethrown_exception.GetMessage().c_str());
+        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+
+        callbackManager->callOnError(error);
+        LOGD("findAppControl error callback called");
+        return;
+    }
+}
+
+void ApplicationAsyncAnswerHandler::getAppsContext(
+        const EventApplicationGetAppsContextPtr &event)
+{
+    LOGD("Entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager>(event->getPrivateData());
+    if (!callbackManager) {
+        LOGE("no callback manager");
+        return;
+    }
+
+    ApplicationAsyncCallbackManagerSingleton::Instance().unregisterCallbackManager(callbackManager);
+    if (callbackManager->getOnSuccess()==NULL && callbackManager->getOnError()==NULL)
+    {
+        LOGD("Callback was not registered or context has been already expired.");
+        return;
+    }
+
+    if (event->checkCancelled()) {
+        LOGD("Operation cancelled");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+
+    JSValueRef error = NULL;
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::NOT_FOUND_ERROR,"given package is not found");
+            break;
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"platform exception");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        LOGD("getAppsContext error callback called");
+        return;
+    }
+
+    Try {
+        ApplicationContextArrayPtr appContextArray = event->getAppContextArray();
+
+        ApplicationConverterFactory::ConverterType converter =
+            ApplicationConverterFactory::getConverter(gContext);
+
+        JSValueRef result = converter->toJSValueRef(appContextArray);
+
+        callbackManager->callOnSuccess(result);
+        LOGD("getAppsContext success callback called");
+        return;
+    } Catch(Exception) {
+        LOGE("error during processing answer %s", _rethrown_exception.GetMessage().c_str());
+        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+
+        callbackManager->callOnError(error);
+        LOGD("getAppsContext error callback called");
+        return;
+    }
+}
+
+void ApplicationAsyncAnswerHandler::getAppsInfo(
+        const EventApplicationGetAppsInfoPtr &event)
+{
+    LOGD("Entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager>(event->getPrivateData());
+    if (!callbackManager) {
+        LOGE("no callback manager");
+        return;
+    }
+
+    ApplicationAsyncCallbackManagerSingleton::Instance().unregisterCallbackManager(
+            callbackManager);
+    if (callbackManager->getOnSuccess()==NULL && callbackManager->getOnError()==NULL)
+    {
+        LOGD("Callback was not registered or context has been already expired.");
+        return;
+    }
+
+    if (event->checkCancelled()) {
+        LOGD("Operation cancelled");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+
+    JSValueRef error = NULL;
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::NOT_FOUND_ERROR,"given package is not found");
+            break;
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"platform exception");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR,"unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        LOGD("getAppsInfo error callback called");
+        return;
+    }
+
+    Try {
+        ApplicationInformationArrayPtr appInfoArray = event->getAppInfoArray();
+
+        ApplicationConverter converter(gContext, event.get());
+
+        JSValueRef result = converter.toJSValueRef(appInfoArray);
+
+        callbackManager->callOnSuccess(result);
+        LOGD("getAppsInfo success callback called");
+        return;
+    } Catch(Exception) {
+        LOGE("error during processing answer %s", _rethrown_exception.GetMessage().c_str());
+        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+
+        callbackManager->callOnError(error);
+        LOGD("getAppsInfo error callback called");
+        return;
+    }
+}
+
+
+void ApplicationAsyncAnswerHandler::eventListener(
+        const EventApplicationAppInfoEventListenerPtr &event)
+{
+    LOGD("Entered");
+    JSApplicationEventCallbackManagerPtr callbackManager =
+        std::static_pointer_cast<JSApplicationEventCallbackManager>(event->getPrivateData());
+    if (!callbackManager)
+    {
+        LOGE("no callback manager");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+
+    ApplicationConverter converter(gContext, callbackManager.get());
+
+    Try {
+        if (event->getType() == EventApplicationAppInfoEventListener::OnInstalled)
+        {
+            ApplicationInformationPtr appInfo = event->getAppInfo();
+            if (appInfo.get() == NULL)
+            {
+                LOGE("AppInfo is not set.");
+                return;
+            }
+            JSValueRef result = converter.toJSValueRefFromApplicationInformation(appInfo);
+            callbackManager->callOnInstalled(result);
+            LOGD("AppInfoEvent oninstalled callback called");
+        }
+        else if (event->getType() == EventApplicationAppInfoEventListener::OnUpdated)
+        {
+            ApplicationInformationPtr appInfo = event->getAppInfo();
+            if (appInfo.get() == NULL)
+            {
+                LOGE("AppInfo is not set.");
+                return;
+            }
+            JSValueRef result = converter.toJSValueRefFromApplicationInformation(appInfo);
+            callbackManager->callOnUpdated(result);
+            LOGD("AppInfoEvent onupdated callback called");
+        }
+        else if (event->getType() == EventApplicationAppInfoEventListener::OnUninstalled)
+        {
+            ApplicationInformationPtr appInfo = event->getAppInfo();
+            std::string appId = appInfo->getAppId();
+            if (appId == "")
+            {
+                LOGE("AppId is not set.");
+                return;
+            }
+            JSValueRef result = converter.toJSValueRef(appId);
+            callbackManager->callOnUninstalled(result);
+            LOGD("AppInfoEvent onuninstalled callback called");
+        }
+        else
+        {
+            LOGE("Event callback type is wrong.");
+            return;
+        }
+    } Catch (Exception) {
+        LOGE("Conversion error");
+        return;
+    }
+}
+
+} // Application
+} // DeviceAPI
diff --git a/src/Application/ApplicationController.h b/src/Application/ApplicationController.h
new file mode 100755 (executable)
index 0000000..4ad3793
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_APPLICATION_APPLICATION_CONTROLLER_H_
+#define _TIZEN_APPLICATION_APPLICATION_CONTROLLER_H_
+
+#include <memory>
+#include <Commons/EventReceiver.h>
+#include <Commons/EventListener.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <Security.h>
+#include "IApplicationManager.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<IApplicationManagerPtr,
+                    WrtDeviceApis::CommonsJavaScript::NoOwnership> ApplicationPrivObject;
+
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<EventApplicationLaunch>
+        EventApplicationLaunchEventAnswerReceiver;
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<EventApplicationKill>
+        EventApplicationKillEventAnswerReceiver;
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<EventApplicationLaunchAppControl>
+        EventApplicationLaunchAppControlEventAnswerReceiver;
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<EventApplicationLaunchAppControlReply>
+        EventApplicationLaunchAppControlReplyEventAnswerReceiver;
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<EventApplicationFindAppControl>
+        EventApplicationFindAppControlEventAnswerReceiver;
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<EventApplicationGetAppsContext>
+        EventApplicationGetAppsContextEventAnswerReceiver;
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<EventApplicationGetAppsInfo>
+        EventApplicationGetAppsInfoEventAnswerReceiver;
+typedef WrtDeviceApis::Commons::EventListener<EventApplicationAppInfoEventListener>
+        EventApplicationAppInfoEventListenerListener;
+
+class ApplicationController :
+    public EventApplicationLaunchEventAnswerReceiver,
+    public EventApplicationKillEventAnswerReceiver,
+    public EventApplicationLaunchAppControlEventAnswerReceiver,
+    public EventApplicationLaunchAppControlReplyEventAnswerReceiver,
+    public EventApplicationFindAppControlEventAnswerReceiver,
+    public EventApplicationGetAppsContextEventAnswerReceiver,
+    public EventApplicationGetAppsInfoEventAnswerReceiver,
+    public EventApplicationAppInfoEventListenerListener,
+    public DeviceAPI::Common::SecurityAccessor,
+    public ApplicationPrivObject
+{
+public:
+    ApplicationController(JSContextRef context,
+            IApplicationManagerPtr application);
+    virtual ~ApplicationController();
+protected:
+    void     OnAnswerReceived(const EventApplicationLaunchPtr &event);
+    void     OnAnswerReceived(const EventApplicationKillPtr &event);
+    void     OnAnswerReceived(const EventApplicationLaunchAppControlPtr &event);
+    void     OnAnswerReceived(const EventApplicationLaunchAppControlReplyPtr &event);
+    void     OnAnswerReceived(const EventApplicationFindAppControlPtr &event);
+    void     OnAnswerReceived(const EventApplicationGetAppsContextPtr &event);
+    void     OnAnswerReceived(const EventApplicationGetAppsInfoPtr &event);
+    void     onAnswerReceived(const EventApplicationAppInfoEventListenerPtr &event);
+};
+
+typedef std::shared_ptr<ApplicationController> ApplicationControllerPtr;
+
+//common part
+class ApplicationAsyncAnswerHandler
+{
+public:
+    static void launch(const EventApplicationLaunchPtr &event);
+    static void kill(const EventApplicationKillPtr &event);
+    static void launchAppControl(const EventApplicationLaunchAppControlPtr &event);
+    static void launchAppControlReply(const EventApplicationLaunchAppControlReplyPtr &event);
+    static void findAppControl(const EventApplicationFindAppControlPtr &event);
+    static void getAppsContext(const EventApplicationGetAppsContextPtr &event);
+    static void getAppsInfo(const EventApplicationGetAppsInfoPtr &event);
+    static void eventListener(const EventApplicationAppInfoEventListenerPtr &event);
+};
+
+} // Application
+} // DeviceAPI
+
+#endif // _TIZEN_APPLICATION_APPLICATION_CONTROLLER_H_
diff --git a/src/Application/ApplicationConverter.cpp b/src/Application/ApplicationConverter.cpp
new file mode 100755 (executable)
index 0000000..ef0f76d
--- /dev/null
@@ -0,0 +1,505 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+#include <Commons/RegexUtils.h>
+#include <Commons/Exception.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+
+#include "ApplicationConverter.h"
+#include "JSApplication.h"
+#include "JSApplicationInformation.h"
+#include "JSApplicationContext.h"
+#include "JSApplicationControlData.h"
+#include "JSApplicationControlData.h"
+#include "JSApplicationControl.h"
+#include "JSRequestedApplicationControl.h"
+#include "JSApplicationMetaData.h"
+#include "JSApplicationCert.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+ApplicationConverter::ApplicationConverter(
+        JSContextRef context,
+        const SecurityAccessor *accessor):
+    Converter(context),
+    m_securityAccessor(accessor)
+{
+    LOGD("Entered");
+}
+
+ApplicationConverter::~ApplicationConverter()
+{
+    LOGD("Entered");
+}
+
+
+JSValueRef ApplicationConverter::toJSValueRefFromApplication(
+        const ApplicationPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::ConversionException);
+    }
+    return CommonsJavaScript::JSUtils::makeObject(m_context,
+            JSApplication::getClassRef(), arg);
+}
+
+
+JSValueRef ApplicationConverter::toJSValueRefFromApplicationCert(
+        const ApplicationCertPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::ConversionException);
+    }
+    return CommonsJavaScript::JSUtils::makeObject(m_context,
+            JSApplicationCert::getClassRef(), arg);
+}
+
+
+JSValueRef ApplicationConverter::toJSValueRefFromApplicationCerts(
+        const ApplicationCertArrayPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::InvalidArgumentException);
+    }
+    return toJSValueRef_(*arg,
+            &ApplicationConverter::toJSValueRefFromApplicationCert, this);
+}
+
+
+JSValueRef ApplicationConverter::toJSValueRefFromApplicationMetaData(
+        const ApplicationMetaDataPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::ConversionException);
+    }
+    return CommonsJavaScript::JSUtils::makeObject(m_context,
+            JSApplicationMetaData::getClassRef(), arg);
+}
+
+
+JSValueRef ApplicationConverter::toJSValueRefFromApplicationMetaDataArray(
+        const ApplicationMetaDataArrayPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::InvalidArgumentException);
+    }
+    return toJSValueRef_(*arg,
+            &ApplicationConverter::toJSValueRefFromApplicationMetaData, this);
+}
+
+
+JSValueRef ApplicationConverter::toJSValueRefFromApplicationInformation(
+        const ApplicationInformationPtr &arg)
+{
+    LOGD("Entered");
+    if (m_securityAccessor == NULL)
+        Throw(Commons::ConversionException);
+
+    if (arg.get() == NULL) {
+        Throw(Commons::ConversionException);
+    }
+    JSApplicationInformationPriv *priv = new JSApplicationInformationPriv(m_context, arg);
+    priv->copyAceCheckAccessFunction(m_securityAccessor);
+    return JSObjectMake(m_context, JSApplicationInformation::getClassRef(), priv);
+}
+
+ApplicationInformationPtr ApplicationConverter::toApplicationInformation(
+        const JSValueRef &jsValue)
+{
+    LOGD("Entered");
+    if (JSApplicationInformation::isObjectOfClass(m_context, jsValue))
+        return JSApplicationInformation::getApplicationInformation(m_context, jsValue);
+
+    const ScopedJSStringRef nameStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_INFORMATION_NAME));
+    const ScopedJSStringRef appIdStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_INFORMATION_ID));
+    const ScopedJSStringRef iconPathStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_INFORMATION_ICONPATH));
+    const ScopedJSStringRef versionStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_INFORMATION_VERSION));
+    const ScopedJSStringRef showStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_INFORMATION_SHOW));
+    const ScopedJSStringRef categoriesStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_INFORMATION_CATEGORIES));
+    const ScopedJSStringRef installDateStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_INFORMATION_INSTALL_DATE));
+    const ScopedJSStringRef installSizeStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_INFORMATION_INSTALL_SIZE));
+    const ScopedJSStringRef packageIdStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_INFORMATION_PACKAGE_ID));
+
+    JSObjectRef jsObject = toJSObjectRef(jsValue);
+
+    JSValueRef nameData =
+            JSObjectGetProperty(m_context, jsObject, nameStr.get(), NULL);
+    JSValueRef appIdStrData =
+            JSObjectGetProperty(m_context, jsObject, appIdStr.get(), NULL);
+    JSValueRef iconPathData =
+            JSObjectGetProperty(m_context, jsObject, iconPathStr.get(), NULL);
+    JSValueRef versionData =
+            JSObjectGetProperty(m_context, jsObject, versionStr.get(), NULL);
+    JSValueRef showData =
+            JSObjectGetProperty(m_context, jsObject, showStr.get(), NULL);
+    JSValueRef categoriesData =
+            JSObjectGetProperty(m_context, jsObject, categoriesStr.get(), NULL);
+    JSValueRef installDateData =
+            JSObjectGetProperty(m_context, jsObject, installDateStr.get(), NULL);
+    JSValueRef installSizeData =
+            JSObjectGetProperty(m_context, jsObject, installSizeStr.get(), NULL);
+    JSValueRef pkgIdStrData =
+            JSObjectGetProperty(m_context, jsObject, packageIdStr.get(), NULL);
+
+    std::string name;
+    std::string appid;
+    std::string iconPath;
+    std::string version;
+    bool show;
+    std::vector <std::string> categories;
+    time_t installDate;
+    long installSize;
+    std::string pkgid;
+
+    ApplicationInformationPtr result(new ApplicationInformation());
+    if (!result) {
+        Throw(Commons::ConversionException);
+    }
+
+    if (!JSValueIsUndefined(m_context, nameData)) {
+        name = toString(nameData);
+        result->setName(name);
+    }
+    if (!JSValueIsUndefined(m_context, appIdStrData)) {
+        appid = toString(appIdStrData);
+        result->setAppId(appid);
+    }
+    if (!JSValueIsUndefined(m_context, iconPathData)) {
+        iconPath = toString(iconPathData);
+        result->setIconPath(iconPath);
+    }
+    if (!JSValueIsUndefined(m_context, versionData)) {
+        version = toString(versionData);
+        result->setVersion(version);
+    }
+    if (!JSValueIsUndefined(m_context, showData)) {
+        show = toBool(showData);
+        result->setShow(show);
+    }
+    if (!JSValueIsUndefined(m_context, categoriesData)) {
+        categories = toVectorOfStrings(categoriesData);
+        result->setCategories(categories);
+    }
+    if (!JSValueIsUndefined(m_context, installDateData)) {
+        installDate = toDateTimeT(installDateData);
+        result->setInstallDate(installDate);
+    }
+    if (!JSValueIsUndefined(m_context, installSizeData)) {
+        installSize = toDateTimeT(installSizeData);
+        result->setInstallSize(installSize);
+    }
+    if (!JSValueIsUndefined(m_context, pkgIdStrData)) {
+        pkgid = toString(pkgIdStrData);
+        result->setPackageId(pkgid);
+    }
+    return result;
+}
+
+JSValueRef ApplicationConverter::toJSValueRef(
+        const ApplicationInformationArrayPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::InvalidArgumentException);
+    }
+    return toJSValueRef_(*arg,
+            &ApplicationConverter::toJSValueRefFromApplicationInformation, this);
+}
+
+ApplicationInformationArrayPtr ApplicationConverter::toApplicationInformationArray(
+        const JSValueRef &jsValue)
+{
+    LOGD("Entered");
+    ApplicationInformationArrayPtr result(new ApplicationInformationArray());
+
+    JSObjectRef jsObject = toJSObjectRef(jsValue);
+    for (std::size_t i = 0; i < JSGetArrayLength(m_context, jsObject); ++i) {
+        JSValueRef element = JSGetArrayElement(m_context, jsObject, i);
+        result->push_back(toApplicationInformation(element));
+    }
+    return result;
+}
+
+JSValueRef ApplicationConverter::toJSValueRefFromApplicationContext(
+        const ApplicationContextPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::InvalidArgumentException);
+    }
+    return CommonsJavaScript::JSUtils::makeObject(m_context,
+            JSApplicationContext::getClassRef(), arg);
+}
+
+ApplicationContextPtr ApplicationConverter::toApplicationContext(
+        const JSValueRef &jsValue)
+{
+    LOGD("Entered");
+    if (JSApplicationContext::isObjectOfClass(m_context, jsValue))
+        return JSApplicationContext::getApplicationContext(m_context, jsValue);
+
+    const ScopedJSStringRef appIdStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_CONTEXT_APP_ID));
+    const ScopedJSStringRef contextIdStr(
+            JSStringCreateWithUTF8CString(TIZEN_APPLICATION_CONTEXT_ID));
+
+    JSObjectRef jsObject = toJSObjectRef(jsValue);
+
+    JSValueRef appIdStrData =
+            JSObjectGetProperty(m_context, jsObject, appIdStr.get(), NULL);
+    JSValueRef contextIdStrData =
+            JSObjectGetProperty(m_context, jsObject, contextIdStr.get(), NULL);
+
+    std::string appid;
+    std::string contextid;
+
+    ApplicationContextPtr result(new ApplicationContext());
+    if (!result) {
+        Throw(Commons::ConversionException);
+    }
+
+    if (!JSValueIsUndefined(m_context, appIdStrData)) {
+        appid = toString(appIdStrData);
+        result->setAppId(appid);
+    }
+    if (!JSValueIsUndefined(m_context, contextIdStrData)) {
+        contextid = toString(contextIdStrData);
+        result->setContextId(contextid);
+    }
+
+    return result;
+}
+
+JSValueRef ApplicationConverter::toJSValueRef(
+        const ApplicationContextArrayPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::ConversionException);
+    }
+    return toJSValueRef_(*arg,
+            &ApplicationConverter::toJSValueRefFromApplicationContext, this);
+}
+
+ApplicationContextArrayPtr ApplicationConverter::toApplicationContextArray(
+        const JSValueRef &jsValue)
+{
+    LOGD("Entered");
+    ApplicationContextArrayPtr result(new ApplicationContextArray());
+
+    JSObjectRef jsObject = toJSObjectRef(jsValue);
+    for (std::size_t i = 0; i < JSGetArrayLength(m_context, jsObject); ++i) {
+        JSValueRef element = JSGetArrayElement(m_context, jsObject, i);
+        result->push_back(toApplicationContext(element));
+    }
+    return result;
+}
+
+
+JSValueRef ApplicationConverter::toJSValueRef(
+        const RequestedApplicationControlPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::InvalidArgumentException);
+    }
+    return CommonsJavaScript::JSUtils::makeObject(m_context,
+            JSRequestedApplicationControl::getClassRef(), arg);
+}
+
+RequestedApplicationControlPtr ApplicationConverter::toRequestedApplicationControl(
+        const JSValueRef &jsValue)
+{
+    LOGD("Entered");
+    if (JSRequestedApplicationControl::isObjectOfClass(m_context, jsValue)) {
+        return JSRequestedApplicationControl::getRequestedApplicationControl(m_context,
+                jsValue);
+    } else {
+        ThrowMsg(Commons::ConversionException, "Wrong parameter type.");
+    }
+}
+
+
+JSValueRef ApplicationConverter::toJSValueRef(
+        const ApplicationControlPtr &arg)
+{
+    LOGD("Entered");
+    if (arg.get() == NULL) {
+        Throw(Commons::InvalidArgumentException);
+    }
+
+    JSValueRef jsValueData = toJSValueRef(arg->getAppControlDataArray());
+
+    return JSApplicationControl::createJSObject(m_context, arg, jsValueData);
+}
+
+ApplicationControlPtr ApplicationConverter::toApplicationControl(
+        const JSValueRef &jsValue)
+{
+    LOGD("Entered");
+    if (JSApplicationControl::isObjectOfClass(m_context, jsValue)) {
+        ApplicationControlPtr result = JSApplicationControl::getApplicationControl(m_context,
+                jsValue);
+
+        JSObjectRef jsObject = toJSObjectRef(jsValue);
+
+        const ScopedJSStringRef appControlDataStr(JSStringCreateWithUTF8CString(
+                TIZEN_APPLICATION_CONTROL_DATA_INTERNAL));
+        JSValueRef appControlDataData = JSObjectGetProperty(
+                m_context, jsObject, appControlDataStr.get(), NULL);
+
+        std::vector<ApplicationControlDataPtr> appControlDataArray;
+        try {
+            appControlDataArray = toApplicationControlDataArray(appControlDataData);
+        } catch(const Commons::ConversionException &err) {
+            LOGD("ApplicationControlDataArray is wrong.");
+        }
+
+        result->setAppControlDataArray(appControlDataArray);
+
+        return result;
+    } else {
+        throw TypeMismatchException("not a object of class ApplicationControl");
+    }
+}
+
+JSValueRef ApplicationConverter::toJSValueRef(
+        const ApplicationControlDataPtr &arg)
+{
+    LOGD("Entered");
+    JSValueRef jsValueValue = toJSValueRef(arg->getValue());
+
+    return JSApplicationControlData::createJSObject(m_context, arg, jsValueValue);
+}
+
+ApplicationControlDataPtr ApplicationConverter::toApplicationControlData(
+        const JSValueRef &jsValue)
+{
+    LOGD("Entered");
+    if (JSApplicationControlData::isObjectOfClass(m_context, jsValue))
+    {
+        ApplicationControlDataPtr result =
+                JSApplicationControlData::getApplicationControlData(m_context, jsValue);
+
+        JSObjectRef jsObject = toJSObjectRef(jsValue);
+
+        const ScopedJSStringRef appControlDataValueStr(
+                JSStringCreateWithUTF8CString(TIZEN_APPLICATION_CONTROL_DATA_VALUE_INTERNAL));
+        JSValueRef appControlDataValueData =
+                JSObjectGetProperty(m_context, jsObject, appControlDataValueStr.get(), NULL);
+
+        if (!JSValueIsUndefined(m_context, appControlDataValueData)) {
+            result->setValue(toVectorOfStrings(appControlDataValueData));
+        }
+        return result;
+    }
+    else
+    {
+        const ScopedJSStringRef appControlDataKeyStr(
+                JSStringCreateWithUTF8CString(TIZEN_APPLICATION_CONTROL_DATA_KEY));
+        const ScopedJSStringRef appControlDataValueStr(
+                JSStringCreateWithUTF8CString(TIZEN_APPLICATION_CONTROL_DATA_VALUE_INTERNAL));
+
+        JSObjectRef jsObject = toJSObjectRef(jsValue);
+
+        JSValueRef appControlDataKeyData = JSObjectGetProperty(m_context,
+                jsObject, appControlDataKeyStr.get(), NULL);
+        JSValueRef appControlDataValueData = JSObjectGetProperty(m_context,
+                jsObject, appControlDataValueStr.get(), NULL);
+
+        ApplicationControlDataPtr result(new ApplicationControlData());
+        if (!result) {
+            Throw(Commons::ConversionException);
+        }
+
+        if (!JSValueIsUndefined(m_context, appControlDataKeyData)) {
+            result->setKey(toString(appControlDataKeyData));
+        }
+
+        if (!JSValueIsUndefined(m_context, appControlDataValueData)) {
+            result->setValue(toVectorOfStrings(appControlDataValueData));
+        }
+        return result;
+    }
+}
+
+JSValueRef ApplicationConverter::toJSValueRef(
+        const std::vector<ApplicationControlDataPtr> &arg)
+{
+    LOGD("Entered");
+    JSObjectRef jsResult = JSCreateArrayObject(m_context, 0, NULL);
+
+    if (jsResult == NULL) {
+        ThrowMsg(Commons::ConversionException, "Could not create js array object");
+    }
+
+    for (std::size_t i = 0; i < arg.size(); ++i) {
+        JSValueRef tmpVal = toJSValueRef(arg[i]);
+        if (!JSSetArrayElement(m_context, jsResult, i, tmpVal)) {
+            ThrowMsg(Commons::ConversionException, "Could not insert value into js array");
+        }
+    }
+
+    return jsResult;
+}
+
+std::vector<ApplicationControlDataPtr> ApplicationConverter::toApplicationControlDataArray(
+        const JSValueRef &jsValue)
+{
+    LOGD("Entered");
+    if (JSValueIsNull(m_context, jsValue) || JSValueIsUndefined(m_context, jsValue)) {
+        return std::vector<ApplicationControlDataPtr>();
+    }
+
+    if (!JSIsArrayValue(m_context, jsValue)) {
+        ThrowMsg(Commons::ConversionException, "Argument is not an JS array.");
+    }
+
+    std::vector<ApplicationControlDataPtr> result;
+    JSObjectRef objArg = toJSObjectRef(jsValue);
+    for (std::size_t i = 0; i < JSGetArrayLength(m_context, objArg); ++i) {
+        JSValueRef element = JSGetArrayElement(m_context, objArg, i);
+        result.push_back(toApplicationControlData(element));
+    }
+    return result;
+}
+
+}
+}
diff --git a/src/Application/ApplicationConverter.h b/src/Application/ApplicationConverter.h
new file mode 100755 (executable)
index 0000000..8cac585
--- /dev/null
@@ -0,0 +1,74 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_TIZEN_APPLICATION_CONVERTER_H_
+#define TIZENAPIS_TIZEN_APPLICATION_CONVERTER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/Converter.h>
+#include "IApplicationManager.h"
+#include "ApplicationInformation.h"
+#include "ApplicationContext.h"
+#include "ApplicationControlData.h"
+#include "ApplicationControl.h"
+#include "ApplicationCert.h"
+#include "ApplicationMetaData.h"
+#include "Application.h"
+#include <Export.h>
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Application {
+class DLL_EXPORT ApplicationConverter : public WrtDeviceApis::CommonsJavaScript::Converter
+{
+public:
+    using WrtDeviceApis::CommonsJavaScript::Converter::toJSValueRef;
+public:
+    explicit ApplicationConverter(JSContextRef context,
+            const DeviceAPI::Common::SecurityAccessor *securityAccessor = NULL);
+    virtual ~ApplicationConverter();
+    JSValueRef toJSValueRefFromApplication(const ApplicationPtr &arg);
+    JSValueRef toJSValueRefFromApplicationInformation(const ApplicationInformationPtr &arg);
+    JSValueRef toJSValueRefFromApplicationCert(const ApplicationCertPtr &arg);
+    JSValueRef toJSValueRefFromApplicationCerts(const ApplicationCertArrayPtr &arg);
+    JSValueRef toJSValueRefFromApplicationMetaData(const ApplicationMetaDataPtr &arg);
+    JSValueRef toJSValueRefFromApplicationMetaDataArray(const ApplicationMetaDataArrayPtr &arg);
+    ApplicationInformationPtr toApplicationInformation(const JSValueRef &jsValue);
+    JSValueRef toJSValueRef(const ApplicationInformationArrayPtr &arg);
+    ApplicationInformationArrayPtr toApplicationInformationArray(const JSValueRef &jsValue);
+    JSValueRef toJSValueRefFromApplicationContext(const ApplicationContextPtr &arg);
+    ApplicationContextPtr toApplicationContext(const JSValueRef &jsValue);
+    JSValueRef toJSValueRef(const ApplicationContextArrayPtr &arg);
+    ApplicationContextArrayPtr toApplicationContextArray(const JSValueRef &jsValue);
+    JSValueRef toJSValueRef(const RequestedApplicationControlPtr &arg);
+    RequestedApplicationControlPtr toRequestedApplicationControl(const JSValueRef &jsValue);
+    JSValueRef toJSValueRef(const ApplicationControlPtr &arg);
+    ApplicationControlPtr toApplicationControl(const JSValueRef &jsValue);
+    JSValueRef toJSValueRef(const ApplicationControlDataPtr &arg);
+    ApplicationControlDataPtr toApplicationControlData(const JSValueRef &jsValue);
+    JSValueRef toJSValueRef(const std::vector<ApplicationControlDataPtr> &arg);
+    std::vector<ApplicationControlDataPtr> toApplicationControlDataArray(const JSValueRef &jsValue);
+
+private:
+    const DeviceAPI::Common::SecurityAccessor *m_securityAccessor;
+};
+
+typedef WrtDeviceApis::CommonsJavaScript::ConverterFactory<ApplicationConverter> ApplicationConverterFactory;
+}
+}
+#endif
diff --git a/src/Application/ApplicationFactory.cpp b/src/Application/ApplicationFactory.cpp
new file mode 100755 (executable)
index 0000000..8e25f62
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "ApplicationManager.h"
+#include "ApplicationFactory.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+IApplicationManagerPtr ApplicationFactory::createApplication()
+{
+    LOGD("Entered");
+    return IApplicationManagerPtr(new ApplicationManager());
+}
+
+ApplicationFactory& ApplicationFactory::getInstance()
+{
+    LOGD("Entered");
+    static ApplicationFactory theInstance;
+    return theInstance;
+}
+
+ApplicationFactory::ApplicationFactory()
+{
+    LOGD("Entered");
+}
+
+}
+}
diff --git a/src/Application/ApplicationFactory.h b/src/Application/ApplicationFactory.h
new file mode 100755 (executable)
index 0000000..1bb9628
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_API_APPLICATION_FACTORY_H_
+#define TIZENAPIS_API_APPLICATION_FACTORY_H_
+
+#include <dpl/noncopyable.h>
+#include "IApplicationManager.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationFactory: DPL::Noncopyable {
+public:
+    IApplicationManagerPtr createApplication();
+    static ApplicationFactory& getInstance();
+
+protected:
+    ApplicationFactory();
+};
+
+}
+}
+
+#endif
diff --git a/src/Application/ApplicationInformation.cpp b/src/Application/ApplicationInformation.cpp
new file mode 100755 (executable)
index 0000000..3f00611
--- /dev/null
@@ -0,0 +1,206 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "ApplicationInformation.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+ApplicationInformation::ApplicationInformation(const std::string &appId)
+{
+    LOGD("Entered");
+    m_show = false;
+    m_installDate = 0;
+    m_installSize = 0;
+    m_isInitialized = false;
+    m_appId = appId;
+    m_categoriesJSValue = NULL;
+    m_installDateJSValue = NULL;
+}
+
+ApplicationInformation::ApplicationInformation()
+{
+    LOGD("Entered");
+    m_show = false;
+    m_installDate = 0;
+    m_installSize = 0;
+    m_isInitialized = false;
+    m_categoriesJSValue = NULL;
+    m_installDateJSValue = NULL;
+}
+
+ApplicationInformation::~ApplicationInformation()
+{
+    LOGD("Entered");
+    m_categoriesJSValue = NULL;
+    m_installDateJSValue = NULL;
+}
+
+std::string ApplicationInformation::getName() const
+{
+    LOGD("Entered");
+    return m_name;
+}
+
+void ApplicationInformation::setName(const std::string &name)
+{
+    LOGD("Entered");
+    m_name = name;
+}
+
+std::string ApplicationInformation::getAppId() const
+{
+    LOGD("Entered");
+    return m_appId;
+}
+
+void ApplicationInformation::setAppId(const std::string &appId)
+{
+    LOGD("Entered");
+    m_appId = appId;
+}
+
+std::string ApplicationInformation::getIconPath() const
+{
+    LOGD("Entered");
+    return m_iconPath;
+}
+
+void ApplicationInformation::setIconPath(const std::string &iconPath)
+{
+    LOGD("Entered");
+    m_iconPath = iconPath;
+}
+
+std::string ApplicationInformation::getVersion() const
+{
+    LOGD("Entered");
+    return m_version;
+}
+
+void ApplicationInformation::setVersion(const std::string &version)
+{
+    LOGD("Entered");
+    m_version = version;
+}
+
+bool ApplicationInformation::getShow() const
+{
+    LOGD("Entered");
+    return m_show;
+}
+
+void ApplicationInformation::setShow(const bool &show)
+{
+    LOGD("Entered");
+    m_show = show;
+}
+
+std::vector<std::string> ApplicationInformation::getCategories() const
+{
+    LOGD("Entered");
+    return m_categories;
+}
+
+void ApplicationInformation::setCategories(const std::vector<std::string> &categories)
+{
+    LOGD("Entered");
+    m_categories = categories;
+}
+
+void ApplicationInformation::addCategories(const std::string &category)
+{
+    LOGD("Entered");
+    m_categories.push_back(category);
+}
+
+time_t ApplicationInformation::getInstallDate() const
+{
+    LOGD("Entered");
+    return m_installDate;
+}
+
+void ApplicationInformation::setInstallDate(const time_t &date)
+{
+    LOGD("Entered");
+    m_installDate = date;
+}
+
+long ApplicationInformation::getInstallSize() const
+{
+    LOGD("Entered");
+    return m_installSize;
+}
+
+void ApplicationInformation::setInstallSize(const long &size)
+{
+    LOGD("Entered");
+    m_installSize = size;
+}
+
+std::string ApplicationInformation::getPackageId() const
+{
+    LOGD("Entered");
+    return m_pkgId;
+}
+
+void ApplicationInformation::setPackageId(const std::string &pkgId)
+{
+    LOGD("Entered");
+    m_pkgId = pkgId;
+}
+
+void ApplicationInformation::setCategoriesJSValue(const void *jsvalue)
+{
+    LOGD("Entered");
+    m_categoriesJSValue = jsvalue;
+}
+
+const void * ApplicationInformation::getCategoriesJSValue() const
+{
+    LOGD("Entered");
+    return m_categoriesJSValue;
+}
+
+void ApplicationInformation::setInstallDateJSValue(const void *jsvalue)
+{
+    LOGD("Entered");
+    m_installDateJSValue = jsvalue;
+}
+
+const void * ApplicationInformation::getInstallDateJSValue() const
+{
+    LOGD("Entered");
+    return m_installDateJSValue;
+}
+
+// Temporal code. if package manager issue is solved, disable below code.
+#if 1
+bool ApplicationInformation::isInitialized() const
+{
+    LOGD("Entered");
+    return m_isInitialized;
+}
+
+void ApplicationInformation::setInitialize()
+{
+    LOGD("Entered");
+    m_isInitialized = true;
+}
+#endif
+
+}
+}
diff --git a/src/Application/ApplicationInformation.h b/src/Application/ApplicationInformation.h
new file mode 100755 (executable)
index 0000000..55c2fcc
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_INFORMATION_H_
+#define TIZENAPIS_API_APPLICATION_INFORMATION_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationInformation;
+typedef std::shared_ptr<ApplicationInformation> ApplicationInformationPtr;
+
+typedef std::vector<ApplicationInformationPtr> ApplicationInformationArray;
+typedef std::shared_ptr<ApplicationInformationArray> ApplicationInformationArrayPtr;
+
+class ApplicationInformation
+{
+  public:
+    ApplicationInformation(const std::string &appId);
+    ApplicationInformation();
+    ~ApplicationInformation();
+
+    std::string getName() const;
+    void setName(const std::string &name);
+    std::string getAppId() const;
+    void setAppId(const std::string &appId);
+    std::string getIconPath() const;
+    void setIconPath(const std::string &iconPath);
+    std::string getVersion() const;
+    void setVersion(const std::string &version);
+    bool getShow() const;
+    void setShow(const bool &show);
+    std::vector<std::string> getCategories() const;
+    void setCategories(const std::vector<std::string> &categories);
+    void addCategories(const std::string &category);
+    time_t getInstallDate() const;
+    void setInstallDate(const time_t &date);
+    long getInstallSize() const;
+    void setInstallSize(const long &size);
+    std::string getPackageId() const;
+    void setPackageId(const std::string &pkgId);
+    // temporal code. if package manager issue is solved, disable below code.
+#if 1
+    bool isInitialized() const;
+    void setInitialize();
+#endif
+
+  private:
+    std::string m_name;
+    std::string m_appId;
+    std::string m_iconPath;
+    std::string m_version;
+    bool m_show;
+    time_t m_installDate;
+    long m_installSize;
+    std::string m_pkgId;
+    // temporal code. if package manager issue is solved, disable below code.
+    bool m_isInitialized;
+    std::vector<std::string> m_categories;
+
+  public:
+    void setCategoriesJSValue(const void *jsvalue);
+    const void * getCategoriesJSValue() const;
+    void setInstallDateJSValue(const void *jsvalue);
+    const void * getInstallDateJSValue() const;
+
+  private:
+    const void *m_categoriesJSValue;
+    const void *m_installDateJSValue;
+};
+}
+}
+#endif
diff --git a/src/Application/ApplicationInformationEventPrivateData.h b/src/Application/ApplicationInformationEventPrivateData.h
new file mode 100755 (executable)
index 0000000..0aa4cfa
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_TIZEN_APPLICATION_INFORMATION_EVENT_PRIVATE_DATA_H_
+#define TIZENAPIS_TIZEN_APPLICATION_INFORMATION_EVENT_PRIVATE_DATA_H_
+
+#include <memory>
+#include <Commons/IEvent.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+class ApplicationInformationEventPrivateData :
+        public WrtDeviceApis::Commons::IEventPrivateData
+{
+  public:
+    ApplicationInformationEventPrivateData(const JSCallbackManagerPtr& onInstalled,
+                                      const JSCallbackManagerPtr& onUpdated,
+                                      const JSCallbackManagerPtr& onUninstalled):
+        m_onInstalled(onInstalled),
+        m_onUpdated(onUpdated),
+        m_onUninstalled(onUninstalled)
+    {
+        LOGD("Entered");
+    }
+
+    JSCallbackManagerPtr getOnInstalled() const
+    {
+        LOGD("Entered");
+        return m_onInstalled;
+    }
+    JSCallbackManagerPtr getOnUpdated() const
+    {
+        LOGD("Entered");
+        return m_onUpdated;
+    }
+    JSCallbackManagerPtr getOnUninstalled() const
+    {
+        LOGD("Entered");
+        return m_onUninstalled;
+    }
+
+private:
+    JSCallbackManagerPtr m_onInstalled;
+    JSCallbackManagerPtr m_onUpdated;
+    JSCallbackManagerPtr m_onUninstalled;
+};
+
+typedef std::shared_ptr<ApplicationInformationEventPrivateData> ApplicationInformationEventPrivateDataPtr;
+}
+}
+#endif
diff --git a/src/Application/ApplicationListenerManager.cpp b/src/Application/ApplicationListenerManager.cpp
new file mode 100755 (executable)
index 0000000..6f703a0
--- /dev/null
@@ -0,0 +1,26 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ApplicationListenerManager.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+SINGLETON_IMPLEMENTATION(ApplicationListenerManager)
+
+} // Application
+} // DeviceAPI
diff --git a/src/Application/ApplicationListenerManager.h b/src/Application/ApplicationListenerManager.h
new file mode 100755 (executable)
index 0000000..5d4c75a
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_APPLICATION_LISTENER_MANAGER_H_
+#define _TIZEN_APPLICATION_LISTENER_MANAGER_H_
+
+#include <map>
+#include <JavaScriptCore/JavaScript.h>
+#include <memory>
+#include <IListenerManager.h>
+#include "JSApplicationManager.h"
+#include "ApplicationController.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationListenerManager : public DeviceAPI::Common::IListenerController
+{
+private:
+    ApplicationListenerManager()
+    {
+        LOGD("Entered");
+    }
+
+public:
+    virtual ~ApplicationListenerManager()
+    {
+        LOGD("Entered");
+    }
+
+    friend class ApplicationListenerManagerSingleton;
+};
+
+SINGLETON_DEFINITION(ApplicationListenerManager)
+
+class ApplicationListenerCanceller : public DeviceAPI::Common::IListenerItem
+{
+public:
+    ApplicationListenerCanceller(JSContextRef context, JSObjectRef object, long watchId) :
+        DeviceAPI::Common::IListenerItem(context, object, watchId)
+    {
+        LOGD("Entered");
+    }
+
+    virtual ~ApplicationListenerCanceller()
+    {
+        LOGD("Entered");
+    }
+
+    virtual void cancelListener()
+    {
+        LOGD("Entered");
+        ApplicationController *priv =
+                static_cast<ApplicationController*>(JSObjectGetPrivate(m_object));
+
+        if (!priv)
+        {
+            LOGE("Object has no private object.");
+            return;
+        }
+
+        IApplicationManagerPtr application(priv->getObject());
+
+        Try
+        {
+            LOGD("Remove a listener");
+            EventApplicationRemoveAppInfoEventListenerPtr event(
+                    new EventApplicationRemoveAppInfoEventListener());
+
+            event->setWatchId(m_watchId);
+            event->setForSynchronousCall();
+
+            Try {
+                LOGD("Remove change listener");
+                application->removeAppInfoEventListener(event);
+            } Catch(WrtDeviceApis::Commons::Exception) {
+                LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+            }
+        }
+        Catch(WrtDeviceApis::Commons::Exception)
+        {
+            LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+        }
+    }
+};
+typedef std::shared_ptr<ApplicationListenerCanceller> ApplicationListenerCancellerPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // _TIZEN_APPLICATION_LISTENER_MANAGER_H_
diff --git a/src/Application/ApplicationManager.cpp b/src/Application/ApplicationManager.cpp
new file mode 100755 (executable)
index 0000000..4384fca
--- /dev/null
@@ -0,0 +1,2102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ApplicationManager.h"
+
+#include <sstream>
+#include <Commons/Exception.h>
+#include <Commons/EventReceiver.h>
+#include <Commons/Regex.h>
+#include <plugins-ipc-message/ipc_message_support.h>
+
+#include "ApplicationInformation.h"
+#include "ApplicationContext.h"
+#include "ApplicationControlData.h"
+#include "ApplicationControl.h"
+#include "Application.h"
+#include "ApplicationUtil.h"
+
+#include <app.h>
+
+// to launch app by aul
+#include <aul.h>
+
+// to get package name by appid
+#include <app_info.h>
+#include <app_manager.h>
+
+// To get cert information from package
+#include <package_manager.h>
+#include <package_info.h>
+
+// To get app size and installed time
+#include <pkgmgr-info.h>
+
+// To get ppid
+#include <unistd.h>
+
+#include <TimeTracer.h>
+
+#include <Logger.h>
+
+#include <glib.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+typedef std::unique_ptr<char*, void(*)(char**)> auto_free_char_ptr;
+
+namespace{
+    void char_ptr_deleter(char** to_free) {
+        LOGD("Entered");
+        if (NULL != *to_free) {
+            free(*to_free);
+        }
+    }
+}
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+namespace {
+    static bool gPkgIdMapInited = false;
+    static std::map<std::string, std::string> gPkgIdMap; // appId - pkgId
+    static char pkgNameTmp[256];
+    static std::map<std::string, std::string> gPkgTypeMap;  // pkgId - type
+
+    class PackageInfo
+    {
+    public:
+        std::string version;
+        int installed_time;
+    };
+    static bool gPkgInfoMapTriggered = false;
+    static std::map<std::string, PackageInfo> gPkgInfoMap;
+
+    typedef KeyMultiMap<ApplicationManager*, LaunchAppControlPendingEvent> LaunchAppControlPendingEventMap;
+    static LaunchAppControlPendingEventMap gLaunchAppControlPendingEventMap;
+
+    // Callback from 'app_manager_set_app_context_event_cb'
+    // Used by 'kill'
+    static void app_manager_app_context_event_callback(app_context_h app_context,
+            app_context_event_e event, void *user_data)
+    {
+        LOGD("Entered");
+        int ret = 0;
+
+        if (event != APP_CONTEXT_EVENT_TERMINATED)
+            return;
+
+        int pid = 0;
+
+        ret = app_context_get_pid(app_context, &pid);
+        if (APP_MANAGER_ERROR_NONE != ret)
+        {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_context_get_pid()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            return;
+        }
+
+        ApplicationManager* appManager = (ApplicationManager*)(user_data);
+        appManager->invokeManualAnswerKill(pid);
+    }
+
+    // get package name by id
+    static char* getPackageByAppId(const char* appId)
+    {
+        LOGD("Entered");
+        app_info_h handle;
+        char* pkgName;
+        int ret = 0;
+
+        if (gPkgIdMapInited)
+        {
+            std::map<std::string, std::string>::iterator iter= gPkgIdMap.find(appId);
+            if (iter != gPkgIdMap.end())
+            {
+                strncpy(pkgNameTmp, iter->second.c_str(), 255);
+                return pkgNameTmp;
+            }
+        }
+
+        ret = app_info_create(appId, &handle);
+        if (ret < 0)
+        {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_info_create()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            return NULL;
+        }
+
+        ret = app_info_get_package(handle, &pkgName);
+        if (ret < 0)
+        {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_info_get_package()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            pkgName = NULL;
+        }
+
+        ret = app_info_destroy(handle);
+        if (ret < 0)
+        {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_info_destroy()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            return NULL;
+        }
+
+        return pkgName;
+    }
+
+
+    // Callback of 'app_manager_foreach_app_context'
+    // Used by 'getAppsContext'
+    static bool app_manager_app_context_callback(app_context_h app_context, void *user_data)
+    {
+        LOGD("Entered");
+        int ret = 0;
+
+        char *app_id = NULL;
+        int pid;
+
+        std::string contextId;
+
+        if (user_data == NULL)
+        {
+            return false;
+        }
+
+        ret = app_context_get_app_id(app_context, &app_id);
+        if ((APP_MANAGER_ERROR_NONE != ret) || (NULL == app_id))
+        {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_context_get_app_id()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            return false;
+        }
+
+        ret = app_context_get_pid(app_context, &pid);
+        if (APP_MANAGER_ERROR_NONE != ret)
+        {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_context_get_pid()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            if (app_id)
+                free(app_id);
+            return false;
+        }
+
+        std::stringstream sstream;
+        sstream << pid;
+        contextId = sstream.str();
+
+        ApplicationContextPtr appContext(new ApplicationContext());
+        appContext->setAppId(app_id);
+        appContext->setContextId(contextId);
+
+        ApplicationContextArray* appContextArray = (ApplicationContextArray*)user_data;
+
+        appContextArray->push_back(appContext);
+
+        if (app_id)
+            free(app_id);
+
+        return true;
+    }
+
+    // Callback of 'app_control_send_launch_request'
+    // Used by 'launchAppControl'
+    static void app_control_reply_callback(app_control_h request, app_control_h reply,
+            app_control_result_e result, void *user_data)
+    {
+        LOGD("Entered");
+        LaunchAppControlPendingEventMap::DataKeyType key =
+                (LaunchAppControlPendingEventMap::DataKeyType)user_data;
+
+        LaunchAppControlPendingEvent *pendingEvent =
+                gLaunchAppControlPendingEventMap.getData(key);
+        if (pendingEvent != NULL)
+        {
+            ApplicationManager *application =
+                    (ApplicationManager *)pendingEvent->getThisObject();
+            EventApplicationLaunchAppControlReplyPtr event = pendingEvent->getEvent();
+            application->invokeManualAnswerLaunchAppControl(request, reply, result, event);
+
+            delete pendingEvent;
+            pendingEvent = NULL;
+            user_data = NULL;
+
+            gLaunchAppControlPendingEventMap.eraseData(key);
+        }
+    }
+
+    static bool package_cert_cb(package_info_h handle, package_cert_type_e cert_type,
+            const char *cert_value, void *user_data)
+    {
+        LOGD("Entered");
+        ApplicationCertPtr cert(new ApplicationCert());
+        const char* certName = NULL;
+
+        switch(cert_type) {
+        case PACKAGE_INFO_AUTHOR_ROOT_CERT:
+            certName = "AUTHOR_ROOT";
+            break;
+        case PACKAGE_INFO_AUTHOR_INTERMEDIATE_CERT:
+            certName = "AUTHOR_INTERMEDIATE";
+            break;
+        case PACKAGE_INFO_AUTHOR_SIGNER_CERT:
+            certName = "AUTHOR_SIGNER";
+            break;
+        case PACKAGE_INFO_DISTRIBUTOR_ROOT_CERT:
+            certName = "DISTRIBUTOR_ROOT";
+            break;
+        case PACKAGE_INFO_DISTRIBUTOR_INTERMEDIATE_CERT:
+            certName = "DISTRIBUTOR_INTERMEDIATE";
+            break;
+        case PACKAGE_INFO_DISTRIBUTOR_SIGNER_CERT:
+            certName = "DISTRIBUTOR_SIGNER";
+            break;
+        case PACKAGE_INFO_DISTRIBUTOR2_ROOT_CERT:
+            certName = "DISTRIBUTOR2_ROOT";
+            break;
+        case PACKAGE_INFO_DISTRIBUTOR2_INTERMEDIATE_CERT:
+            certName = "DISTRIBUTOR2_INTERMEDIATE";
+            break;
+        case PACKAGE_INFO_DISTRIBUTOR2_SIGNER_CERT:
+            certName = "DISTRIBUTOR2_SIGNER";
+            break;
+        default:
+            LOGE("Unknow Cert type!!!");
+            break;
+        }
+
+        cert->setType(certName);
+        cert->setValue(cert_value);
+
+        ApplicationCertArray *certs = (ApplicationCertArray *)user_data;
+        certs->push_back(cert);
+
+        return true;
+    }
+
+    static std::string get_current_app_id()
+    {
+        LOGD("Entered");
+        char *app_id = NULL;
+        int pid = getpid();
+        int ret = app_manager_get_app_id(pid, &app_id);
+        if (APP_MANAGER_ERROR_NONE != ret) {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret, "app_manager_get_app_id()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            return "";
+        }
+
+        std::string appId = app_id;
+
+        free(app_id);
+
+        return appId;
+    }
+
+    static int category_cb(const char *category, void *user_data)
+    {
+        LOGD("Entered");
+        if (category == NULL)
+            return true;
+
+        ApplicationInformation* appInfo = (ApplicationInformation*)user_data;
+        appInfo->addCategories(category);
+        return true;
+    }
+
+    static ApplicationInformationPtr create_app_info(pkgmgrinfo_appinfo_h handle)
+    {
+        LOGD("Entered");
+        char* appId = NULL;
+        char* name = NULL;
+        char* iconPath = NULL;
+        bool noDisplay = false;
+        char* pkgId = NULL;
+        int ret = 0;
+
+        ApplicationInformationPtr appInfo(new ApplicationInformation());
+        ret = pkgmgrinfo_appinfo_get_appid(handle, &appId);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_appinfo_get_appid()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        } else {
+            appInfo->setAppId(appId);
+        }
+
+        ret = pkgmgrinfo_appinfo_get_label(handle, &name);
+        if ((PMINFO_R_OK != ret)) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_appinfo_get_label()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        } else {
+            if (NULL == name) {
+                LOGW("pkgmgrinfo_appinfo_get_label() returned NULL name");
+            } else {
+                appInfo->setName(name);
+            }
+        }
+
+        ret = pkgmgrinfo_appinfo_get_icon(handle, &iconPath);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_appinfo_get_icon()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        } else {
+            if (NULL == iconPath) {
+                LOGW("pkgmgrinfo_appinfo_get_icon() returned NULL name");
+            } else {
+                appInfo->setIconPath(iconPath);
+            }
+        }
+
+        ret = pkgmgrinfo_appinfo_is_nodisplay(handle, &noDisplay);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_appinfo_is_nodisplay()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        } else {
+            appInfo->setShow(!noDisplay);
+        }
+
+        ret = pkgmgrinfo_appinfo_foreach_category(handle, category_cb, (void*)appInfo.get());
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_appinfo_foreach_category()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        }
+
+        ret = pkgmgrinfo_appinfo_get_pkgid(handle, &pkgId);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_appinfo_get_pkgid()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+            return appInfo;
+        } else {
+            if (NULL == pkgId) {
+                LOGW("pkgmgrinfo_appinfo_get_pkgid() returned NULL name");
+            } else {
+                appInfo->setPackageId(pkgId);
+            }
+        }
+
+        if (gPkgInfoMapTriggered)
+        {
+            if (NULL == pkgId) {
+                LOGW("pkgId null");
+                return appInfo;
+            }
+
+            std::map<std::string, PackageInfo>::iterator iter = gPkgInfoMap.find(pkgId);
+            if (iter != gPkgInfoMap.end())
+            {
+                appInfo->setVersion(iter->second.version);
+                appInfo->setInstallDate(iter->second.installed_time);
+
+                return appInfo;
+            }
+        }
+
+        char *version = NULL;
+        int installed_time = 0;
+        pkgmgrinfo_pkginfo_h pkginfo_h;
+
+        ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId, &pkginfo_h);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_pkginfo_get_pkginfo()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        } else {
+            ret = pkgmgrinfo_pkginfo_get_version(pkginfo_h, &version);
+            if (PMINFO_R_OK != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "pkgmgrinfo_pkginfo_get_version()",
+                        ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+            } else {
+                appInfo->setVersion(version);
+            }
+
+            ret = pkgmgrinfo_pkginfo_get_installed_time(pkginfo_h, &installed_time);
+            if (PMINFO_R_OK != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "pkgmgrinfo_pkginfo_get_installed_time()",
+                        ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+            } else {
+                appInfo->setInstallDate(installed_time);
+            }
+
+            ret = pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
+            if (PMINFO_R_OK != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "pkgmgrinfo_pkginfo_destroy_pkginfo()",
+                        ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+            }
+        }
+
+        // remark : attribute "total size" is set at first attribute access time for performance.
+        return appInfo;
+    }
+
+
+    static int installed_app_info_cb(pkgmgrinfo_appinfo_h handle, void *user_data)
+    {
+        LOGD("Entered");
+        ApplicationInformationPtr appInfo = create_app_info(handle);
+        ApplicationInformationArray *appInfoArray = (ApplicationInformationArray*)user_data;
+        appInfoArray->push_back(appInfo);
+        gPkgIdMap[appInfo->getAppId()] = appInfo->getPackageId();
+        return 0;
+    }
+
+    static int get_package_list_cb(pkgmgrinfo_pkginfo_h handle, void *user_data)
+    {
+        LOGD("Entered");
+        int ret = 0;
+        char *pkgId;
+        char *version;
+        char *type;
+        int installed_time;
+
+        ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &pkgId);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_pkginfo_get_pkgid()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        }
+
+        ret = pkgmgrinfo_pkginfo_get_version(handle, &version);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_pkginfo_get_version()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        }
+
+        ret = pkgmgrinfo_pkginfo_get_installed_time(handle, &installed_time);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_pkginfo_get_installed_time()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        }
+
+        ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_pkginfo_get_type()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        }
+
+        PackageInfo pkginfo;
+        if (version)
+            pkginfo.version = version;
+        if (installed_time)
+            pkginfo.installed_time = installed_time;
+        gPkgInfoMap[pkgId] = pkginfo;
+
+        if (type)
+            gPkgTypeMap[pkgId] = type;
+
+        return 0;
+    }
+
+    // Callback from 'app_control_foreach_app_matched'
+    // Used by 'findAppControl'
+    static bool service_app_matched_callback(
+            app_control_h service, const char *appid, void *user_data)
+    {
+        LOGD("Entered");
+        if (appid == NULL)
+        {
+            LOGD("appid is NULL");
+            return false;
+        }
+        //ApplicationInformationPtr appInfo(new ApplicationInformation(appid));
+        pkgmgrinfo_appinfo_h handle;
+        int ret = pkgmgrinfo_appinfo_get_appinfo(appid, &handle);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_appinfo_get_appinfo()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        } else {
+            ApplicationInformationPtr appInfo = create_app_info(handle);
+            ret = pkgmgrinfo_appinfo_destroy_appinfo(handle);
+            if (PMINFO_R_OK != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "pkgmgrinfo_appinfo_get_appinfo()",
+                        ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+            }
+            ApplicationInformationArray *appInfos = (ApplicationInformationArray *)user_data;
+            appInfos->push_back(appInfo);
+        }
+
+        return true;
+    }
+
+    static int app_meta_data_cb(const char *meta_key, const char *meta_value, void *user_data)
+    {
+        LOGD("Entered");
+        if ((meta_key == NULL)  || (meta_value == NULL)) {
+            LOGE("meta_key or meta_value is null");
+            return 0;
+        }
+
+        ApplicationMetaDataPtr metaData(new ApplicationMetaData());
+
+        metaData->setKey(meta_key);
+        metaData->setValue(meta_value);
+
+        ApplicationMetaDataArray *metaDataArray = (ApplicationMetaDataArray *)user_data;
+        metaDataArray->push_back(metaData);
+
+        return 0;
+    }
+}
+
+ApplicationManager::ApplicationManager() :
+    m_initialized(false)
+{
+    LOGD("Entered");
+}
+
+ApplicationManager::~ApplicationManager()
+{
+    LOGD("Entered");
+    if (m_installedApplicationsEmitters.size() != 0)
+    {
+        AppManagerWrapperSingleton::Instance().unregisterAppListChangedCallbacks(this);
+        WatchIdMap::iterator iter = m_watchIdMap.begin();
+        for (; iter != m_watchIdMap.end(); iter++)
+        {
+            m_installedApplicationsEmitters.detach(iter->second);
+        }
+    }
+
+    LaunchAppControlPendingEventMap::DataPtrListType dataPtrList =
+            gLaunchAppControlPendingEventMap.getDataPtrList(this);
+
+    LaunchAppControlPendingEventMap::DataPtrListType::iterator iter = dataPtrList.begin();
+    for (; iter != dataPtrList.end(); iter++)
+    {
+        delete *iter;
+    }
+
+    gLaunchAppControlPendingEventMap.eraseKey(this);
+
+    // unset context event callback which is registered by kill().
+    app_manager_unset_app_context_event_cb();
+}
+
+void ApplicationManager::launch(const EventApplicationLaunchPtr& event)
+{
+    LOGD("Entered");
+    if (m_initialized == false) {
+        initialize();
+    }
+
+    EventRequestReceiver<EventApplicationLaunch>::PostRequest(event);
+}
+
+void ApplicationManager::kill(const EventApplicationKillPtr& event)
+{
+    LOGD("Entered");
+    if (m_initialized == false) {
+        initialize();
+    }
+
+    EventRequestReceiver<EventApplicationKill>::PostRequest(event);
+}
+
+void ApplicationManager::launchAppControl(const EventApplicationLaunchAppControlPtr& event)
+{
+    LOGD("Entered");
+    if (m_initialized == false) {
+        initialize();
+    }
+
+    EventApplicationLaunchAppControlReplyPtr eventReply = event->getEventReply();
+    if (eventReply.get() != NULL)
+        EventRequestReceiver<EventApplicationLaunchAppControlReply>::PostRequest(eventReply);
+
+    EventRequestReceiver<EventApplicationLaunchAppControl>::PostRequest(event);
+}
+
+void ApplicationManager::findAppControl(const EventApplicationFindAppControlPtr& event)
+{
+    LOGD("Entered");
+    if (m_initialized == false) {
+        initialize();
+    }
+
+    EventRequestReceiver<EventApplicationFindAppControl>::PostRequest(event);
+}
+
+void ApplicationManager::getAppsContext(const EventApplicationGetAppsContextPtr& event)
+{
+    LOGD("Entered");
+    if (m_initialized == false) {
+        initialize();
+    }
+
+    EventRequestReceiver<EventApplicationGetAppsContext>::PostRequest(event);
+}
+
+
+void ApplicationManager::getAppsInfo(const EventApplicationGetAppsInfoPtr& event)
+{
+    LOGD("Entered");
+    if (m_initialized == false) {
+        initialize();
+    }
+
+    EventRequestReceiver<EventApplicationGetAppsInfo>::PostRequest(event);
+}
+
+
+void ApplicationManager::addAppInfoEventListener(
+        const EventApplicationAddAppInfoEventListenerPtr& event)
+{
+    LOGD("Entered");
+    if (m_initialized == false) {
+        initialize();
+    }
+
+    EventRequestReceiver<EventApplicationAddAppInfoEventListener>::PostRequest(event);
+}
+
+void ApplicationManager::removeAppInfoEventListener(
+        const EventApplicationRemoveAppInfoEventListenerPtr& event)
+{
+    LOGD("Entered");
+    if (m_initialized == false) {
+        initialize();
+    }
+
+    EventRequestReceiver<EventApplicationRemoveAppInfoEventListener>::PostRequest(event);
+}
+
+
+void ApplicationManager::invokeManualAnswerLaunchAppControl(
+        app_control_h request, app_control_h reply,
+        app_control_result_e result,
+        EventApplicationLaunchAppControlReplyPtr &event)
+{
+    LOGD("Entered");
+    if (event.get() == NULL) {
+        return;
+    }
+
+    if (APP_CONTROL_RESULT_SUCCEEDED == result)
+    {
+        // create new service object to store result.
+        ApplicationControlDataArrayPtr appControlDataArray(new ApplicationControlDataArray());
+
+        int result = app_control_foreach_extra_data(
+                reply, service_extra_data_callback, appControlDataArray.get());
+        if (APP_CONTROL_ERROR_NONE == result)
+        {
+            event->setAppControlDataArray(appControlDataArray);
+        }
+        else
+        {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(
+                    result,
+                    "app_control_foreach_extra_data()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+        }
+    }
+    else if ((APP_CONTROL_RESULT_FAILED == result) || (APP_CONTROL_RESULT_CANCELED == result))
+    {
+        LOGE("%s", ApplicationUtil::getApplicationErrorMessage(result,
+                "app_control_foreach_extra_data()",
+                ApplicationUtil::getApplicationMessage).c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+    }
+
+    EventRequestReceiver<EventApplicationLaunchAppControlReply>::ManualAnswer(event);
+}
+
+void ApplicationManager::invokeManualAnswerKill(int pid)
+{
+    LOGD("Entered");
+    std::lock_guard<std::mutex> lock(m_killMapLock);
+
+    std::map<int, EventApplicationKillPtr>::iterator it = m_killEventMap.find(pid);
+    if (it == m_killEventMap.end()) {
+        return;
+    }
+
+    EventApplicationKillPtr event = it->second;
+    m_killEventMap.erase(it);
+
+    EventRequestReceiver<EventApplicationKill>::ManualAnswer(event);
+}
+
+
+bool ApplicationManager::service_extra_data_callback(
+        app_control_h service, const char *key, void* user_data)
+{
+    LOGD("Entered");
+    int ret = 0;
+
+    ApplicationControlDataArray* appControlDataArray =
+            (ApplicationControlDataArray*)user_data;
+
+    bool isArray = false;
+    ret = app_control_is_extra_data_array(service, key, &isArray);
+    if (APP_CONTROL_ERROR_NONE != ret)
+    {
+        LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_is_extra_data_array()",
+                ApplicationUtil::getApplicationMessage).c_str());
+        return true;
+    }
+
+    std::string keyStr(key);
+
+    if (isArray)
+    {
+        int length = 0;
+        char **value = NULL;
+
+        ret = app_control_get_extra_data_array(service, key, &value, &length);
+        if (APP_CONTROL_ERROR_NONE == ret) {
+            std::vector<std::string> valArray;
+            LOGI("value length : %d", length);
+            for (int i = 0; i < length; i++)
+            {
+                if (value[i])
+                {
+                    valArray.push_back(value[i]);
+                }
+            }
+
+            ApplicationControlDataPtr appControlData(new ApplicationControlData());
+            appControlData->setKey(keyStr);
+            appControlData->setValue(valArray);
+            appControlDataArray->push_back(appControlData);
+
+            for (int i = 0; i < length; i++)
+            {
+                if (value[i])
+                    free(value[i]);
+            }
+            if (value)
+                free(value);
+        }
+        else {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_get_extra_data_array()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+        }
+    }
+    else // (!isArray)
+    {
+        char *value = NULL;
+
+        ret = app_control_get_extra_data(service, key, &value);
+        if (APP_CONTROL_ERROR_NONE == ret)
+        {
+            if (value == NULL)
+            {
+                LOGE("app_control_get_extra_data returns NULL");
+            }
+            else {
+                std::vector<std::string> valArray;
+                valArray.push_back(value);
+
+                ApplicationControlDataPtr appControlData(new ApplicationControlData());
+                appControlData->setKey(keyStr);
+                appControlData->setValue(valArray);
+                appControlDataArray->push_back(appControlData);
+
+                if (value)
+                    free(value);
+                }
+        }
+        else {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(
+                    ret,
+                    "app_control_get_extra_data()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+        }
+    }
+
+    return true;
+}
+
+
+ApplicationPtr ApplicationManager::getCurrentApplication()
+{
+    LOGD("Entered");
+    std::string appId = get_current_app_id();
+
+    //ApplicationInformationPtr appinfo(new ApplicationInformation(appId));
+    pkgmgrinfo_appinfo_h handle;
+    TIME_TRACER_ITEM_BEGIN("(getCurrentApplication)pkgmgrinfo_appinfo_get_appinfo", 0);
+    int ret = pkgmgrinfo_appinfo_get_appinfo(appId.c_str(), &handle);
+    TIME_TRACER_ITEM_END("(getCurrentApplication)pkgmgrinfo_appinfo_get_appinfo", 0);
+    if (PMINFO_R_OK != ret) {
+        LOGW("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<UnknownException>(ret,
+                "pkgmgrinfo_appinfo_get_appinfo()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage);
+    }
+
+    ApplicationInformationPtr appInfo = create_app_info(handle);
+    ret = pkgmgrinfo_appinfo_destroy_appinfo(handle);
+    if (PMINFO_R_OK != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "pkgmgrinfo_appinfo_destroy_appinfo()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+    }
+
+    ApplicationPtr app(new Application());
+    app->setAppInfo(appInfo);
+
+    LOGD("set appinfo to application");
+    {
+        //int pid = getpid();
+        int pid = getppid();
+        std::stringstream sstr;
+        sstr << pid;
+        app->setContextId(sstr.str());
+    }
+
+    return app;
+}
+
+
+ApplicationContextPtr ApplicationManager::getAppContext(const std::string id)
+{
+    LOGD("Entered");
+    int ret = 0;
+
+    std::string contextId = id;
+    std::string appId;
+
+    int selfpid = getppid();
+
+    if (contextId.empty())
+    {
+        std::stringstream sstr;
+        sstr << selfpid;
+        contextId = sstr.str();
+
+        appId = get_current_app_id();
+    }
+    else
+    {
+        int pid = 0;
+        std::stringstream(contextId) >> pid;
+        if (pid <= 0)
+        {
+            LOGE("Given contextId is wrong");
+            ThrowMsg(NotFoundException, "Given contextId is wrong");
+        }
+
+        if (pid == selfpid)
+        {
+            std::stringstream sstr;
+            sstr << selfpid;
+            contextId = sstr.str();
+
+            appId = get_current_app_id();
+        }
+        else
+        {
+            char *app_id = NULL;
+
+            TIME_TRACER_ITEM_BEGIN("(getAppContext)app_manager_get_app_id", 0);
+            ret = app_manager_get_app_id(pid, &app_id);
+            auto_free_char_ptr ptr(&app_id, char_ptr_deleter);
+            TIME_TRACER_ITEM_END("(getAppContext)app_manager_get_app_id", 0);
+            if (APP_MANAGER_ERROR_NONE != ret)
+            {
+                switch(ret) {
+                    case APP_MANAGER_ERROR_NO_SUCH_APP:
+                    case APP_MANAGER_ERROR_INVALID_PARAMETER:
+                        LOGE("ret: %d", ret);
+                        ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                                "app_manager_get_app_id()",
+                                ApplicationUtil::getApplicationManagerMessage);
+                        break;
+                    default:
+                        LOGW("ret: %d", ret);
+                        ApplicationUtil::throwApplicationException<UnknownException>(ret,
+                                "app_manager_get_app_id()",
+                                ApplicationUtil::getApplicationManagerMessage);
+                        break;
+                }
+            }
+
+            appId = app_id;
+        }
+    }
+
+    ApplicationContextPtr appContext(new ApplicationContext());
+    appContext->setAppId(appId);
+    appContext->setContextId(contextId);
+
+    return appContext;
+}
+
+
+ApplicationInformationPtr ApplicationManager::getAppInfo(const std::string id)
+{
+    LOGD("Entered");
+    std::string appId = id;
+    // in case of no argument, get application information of current.
+    if (appId.empty())
+    {
+        appId = get_current_app_id();
+    }
+
+    pkgmgrinfo_appinfo_h handle;
+    TIME_TRACER_ITEM_BEGIN("(getAppInfo)pkgmgrinfo_appinfo_get_appinfo", 0);
+    int ret = pkgmgrinfo_appinfo_get_appinfo(appId.c_str(), &handle);
+    TIME_TRACER_ITEM_END("(getAppInfo)pkgmgrinfo_appinfo_get_appinfo", 0);
+    if (PMINFO_R_OK != ret) {
+        LOGW("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                "pkgmgrinfo_appinfo_get_appinfo()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage);
+    }
+
+    ApplicationInformationPtr appInfo = create_app_info(handle);
+
+    ret = pkgmgrinfo_appinfo_destroy_appinfo(handle);
+    if (PMINFO_R_OK != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "pkgmgrinfo_appinfo_destroy_appinfo()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+    }
+
+    return appInfo;
+}
+
+
+ApplicationCertArrayPtr ApplicationManager::getAppCerts(const std::string id)
+{
+    LOGD("Entered");
+    std::string appId = id;
+
+    // in case of no argument, get application information of current.
+    if (appId.empty())
+    {
+        appId = get_current_app_id();
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(getAppCerts)getPackageByAppId", 0);
+    char* package = getPackageByAppId(appId.c_str());
+
+ // TODO FIXME according to documentation variable package should be deallocated by free
+ // but application crashing when package is deallocated
+ // auto_free_char_ptr ptr(&package, char_ptr_deleter);
+    TIME_TRACER_ITEM_END("(getAppCerts)getPackageByAppId", 0);
+    if (package == NULL)
+    {
+        LOGE("Can not get package");
+        ThrowMsg(NotFoundException, "Can not get package");
+    }
+
+    if (gPkgIdMapInited)
+    {
+        std::map<std::string, std::string>::iterator iter= gPkgTypeMap.find(package);
+
+        if (iter != gPkgTypeMap.end() && iter->second == "rpm")
+        {
+            // rpm can never include certs
+            ApplicationCertArrayPtr certArray(new ApplicationCertArray());
+            free(package);
+
+            return certArray;
+        }
+    }
+
+    package_info_h pkg_info;
+    int result = 0;
+
+    TIME_TRACER_ITEM_BEGIN("(getAppCerts)package_info_create", 0);
+    result = package_info_create(package, &pkg_info);
+    TIME_TRACER_ITEM_END("(getAppCerts)package_info_create", 0);
+    if (PACKAGE_MANAGER_ERROR_NONE != result)
+    {
+        LOGW("ret: %d", result);
+        ApplicationUtil::throwApplicationException<UnknownException>(result,
+                "package_info_create()",
+                ApplicationUtil::getApplicationPackageManagerMessage);
+    }
+
+    ApplicationCertArrayPtr certArray(new ApplicationCertArray());
+
+    TIME_TRACER_ITEM_BEGIN("(getAppCerts)package_info_foreach_cert_info", 0);
+    result = package_info_foreach_cert_info(pkg_info, package_cert_cb, (void*)certArray.get());
+    TIME_TRACER_ITEM_END("(getAppCerts)package_info_foreach_cert_info", 0);
+    if ((PACKAGE_MANAGER_ERROR_NONE != result) && (PACKAGE_MANAGER_ERROR_IO_ERROR != result))
+    {
+        int ret = package_info_destroy(pkg_info);
+        if (PACKAGE_MANAGER_ERROR_NONE != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "package_info_destroy()",
+                     ApplicationUtil::getApplicationPackageManagerMessage).c_str());
+        }
+        LOGE("ret: %d", result);
+        ApplicationUtil::throwApplicationException<UnknownException>(result,
+                "package_info_foreach_cert_info()",
+                ApplicationUtil::getApplicationPackageManagerMessage);
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(getAppCerts)package_info_destroy", 0);
+    result = package_info_destroy(pkg_info);
+    TIME_TRACER_ITEM_END("(getAppCerts)package_info_destroy", 0);
+    if (PACKAGE_MANAGER_ERROR_NONE != result)
+    {
+        LOGE("%s", ApplicationUtil::getApplicationErrorMessage(result,
+                "package_info_destroy()",
+                ApplicationUtil::getApplicationPackageManagerMessage).c_str());
+    }
+
+    return certArray;
+}
+
+std::string ApplicationManager::getAppSharedURI(const std::string id)
+{
+#define TIZENAPIS_APP_FILE_SCHEME       "file://"
+#define TIZENAPIS_APP_SLASH             "/"
+#define TIZENAPIS_APP_SHARED            "shared"
+
+    LOGD("Entered");
+    std::string appId;
+
+    if (id.empty()) {
+        appId = get_current_app_id();
+    } else {
+        appId = id;
+    }
+
+    app_info_h handle;
+    char* pkg_name = NULL;
+    TIME_TRACER_ITEM_BEGIN("(getAppSharedURI)app_info_create", 0);
+    int ret = app_info_create(appId.c_str(), &handle);
+    TIME_TRACER_ITEM_END("(getAppSharedURI)app_info_create", 0);
+    if (APP_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                "app_info_create()",
+                ApplicationUtil::getApplicationManagerMessage);
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(getAppSharedURI)app_info_get_package", 0);
+    ret = app_info_get_package(handle, &pkg_name);
+    TIME_TRACER_ITEM_END("(getAppSharedURI)app_info_get_package", 0);
+    if (APP_MANAGER_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                "app_info_get_package()",
+                ApplicationUtil::getApplicationManagerMessage);
+    } else if (NULL == pkg_name) {
+        LOGE("app_info_get_package() returned NULL pkg_name");
+        ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                "app_info_get_package()",
+                ApplicationUtil::getApplicationManagerMessage);
+    }
+
+    ret = app_info_destroy(handle);
+    if (APP_MANAGER_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_info_destroy()",
+                ApplicationUtil::getApplicationManagerMessage).c_str());
+    }
+
+    pkgmgrinfo_pkginfo_h pkginfo_h;
+    char* root_path = NULL;
+
+    TIME_TRACER_ITEM_BEGIN("(getAppSharedURI)pkgmgrinfo_pkginfo_get_pkginfo", 0);
+    ret = pkgmgrinfo_pkginfo_get_pkginfo(pkg_name, &pkginfo_h);
+    TIME_TRACER_ITEM_END("(getAppSharedURI)pkgmgrinfo_pkginfo_get_pkginfo", 0);
+    if (PMINFO_R_OK != ret) {
+        free(pkg_name);
+        LOGE("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<UnknownException>(ret,
+                "pkgmgrinfo_pkginfo_get_pkginfo()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage);
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(getAppSharedURI)pkgmgrinfo_pkginfo_get_root_path", 0);
+    ret = pkgmgrinfo_pkginfo_get_root_path(pkginfo_h, &root_path);
+    TIME_TRACER_ITEM_END("(getAppSharedURI)pkgmgrinfo_pkginfo_get_root_path", 0);
+    if (PMINFO_R_OK != ret) {
+        free(pkg_name);
+        LOGE("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<UnknownException>(ret,
+                "pkgmgrinfo_pkginfo_get_root_path()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage);
+    }
+    else if (NULL == root_path) {
+            LOGE("pkgmgrinfo_pkginfo_get_root_path() returned NULL root_path");
+            ApplicationUtil::throwApplicationException<UnknownException>(ret,
+                    "pkgmgrinfo_pkginfo_get_root_path()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage);
+    }
+
+    std::string sharedURI = TIZENAPIS_APP_FILE_SCHEME + std::string(root_path) + TIZENAPIS_APP_SLASH + TIZENAPIS_APP_SHARED + TIZENAPIS_APP_SLASH;
+    free(pkg_name);
+
+    ret = pkgmgrinfo_pkginfo_destroy_pkginfo(pkginfo_h);
+    if (PMINFO_R_OK != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "pkgmgrinfo_pkginfo_destroy_pkginfo()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+    }
+    return sharedURI;
+}
+
+ApplicationMetaDataArrayPtr ApplicationManager::getAppMetaData(const std::string id)
+{
+    LOGD("Entered");
+    std::string appId = id;
+
+    // in case of no argument, get application information of current.
+    if (appId.empty())
+    {
+        appId = get_current_app_id();
+    }
+
+    int ret = 0;
+    pkgmgrinfo_appinfo_h handle;
+
+    TIME_TRACER_ITEM_BEGIN("(getAppMetaData)pkgmgrinfo_appinfo_get_appinfo", 0);
+    ret = pkgmgrinfo_appinfo_get_appinfo(appId.c_str(), &handle);
+    TIME_TRACER_ITEM_END("(getAppMetaData)pkgmgrinfo_appinfo_get_appinfo", 0);
+    if (PMINFO_R_OK != ret) {
+        LOGE("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                "pkgmgrinfo_appinfo_get_appinfo()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage);
+    }
+
+    ApplicationMetaDataArrayPtr metaDataArray(new ApplicationMetaDataArray());
+
+    TIME_TRACER_ITEM_BEGIN("(getAppMetaData)pkgmgrinfo_appinfo_foreach_metadata", 0);
+    ret = pkgmgrinfo_appinfo_foreach_metadata(handle, app_meta_data_cb, (void*)metaDataArray.get());
+    TIME_TRACER_ITEM_END("(getAppMetaData)pkgmgrinfo_appinfo_foreach_metadata", 0);
+
+    if (PMINFO_R_OK != ret) {
+        int results = pkgmgrinfo_appinfo_destroy_appinfo(handle);
+        if (PMINFO_R_OK != results) {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(results,
+                    "pkgmgrinfo_appinfo_destroy_appinfo()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        }
+        LOGE("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<UnknownException>(ret,
+                "pkgmgrinfo_appinfo_foreach_metadata()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage);
+    }
+
+    ret = pkgmgrinfo_appinfo_destroy_appinfo(handle);
+    if (PMINFO_R_OK != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "pkgmgrinfo_appinfo_destroy_appinfo()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+    }
+    return metaDataArray;
+}
+
+void ApplicationManager::OnRequestReceived(const EventApplicationLaunchPtr& event)
+{
+    LOGD("Entered");
+    Try
+    {
+        int ret;
+        int retry = 0;
+
+        std::string appId = event->getAppId();
+        if (appId.empty())
+        {
+            LOGE("App id is mandatory field.");
+            event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+            return;
+        }
+
+        // if the application is running, send raise event to the app instead of reset the application.
+        // give a second chance to launch application to avoid platform issue.
+        // this retry code will be removed after platform code change.
+        while (retry < 3) {
+            ret = aul_open_app(appId.c_str());
+            if (ret >= 0) {
+                break;
+            }
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret, "aul_open_app()",
+                    ApplicationUtil::getApplicationAulMessage).c_str());
+            // delay 300ms for each retry
+            usleep(300 * 1000);
+            retry++;
+            LOGD("retry launch request : %d", retry);
+        }
+
+        if (ret < 0) {
+            switch (ret)
+            {
+            case AUL_R_EINVAL:
+            case AUL_R_ERROR:
+                LOGE("returns Not Found error");
+                event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+                break;
+            case AUL_R_ECOMM:
+                LOGE("returns internal IPC error");
+                event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+                break;
+            default:
+                LOGE("returns Unknown error");
+                event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
+                break;
+            }
+        } else {
+            LOGD("Success to launch.");
+        }
+    }
+    Catch (WrtDeviceApis::Commons::Exception)
+    {
+        LOGE("Error on launch : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+}
+
+// Because of platform issue, some termination event is not come to
+// app_manager_set_app_context_event_cb().
+// To prevent blocking issue by wating callback function, add termination checking code.
+// this function check whether callback is called or not after 3 sec.
+//if callback is not called, calls callback function forcibily.
+// After fixing platform issue, below code should be removed
+
+typedef struct {
+    ApplicationManager* appManager;
+    int pid;
+    EventApplicationKillPtr event;
+} KILL_DATA_T;
+
+gboolean check_terminate_callback (gpointer user_data)
+{
+    LOGD("Entered");
+    //EventApplicationKillPtr event = (EventApplicationKillPtr)data;
+    KILL_DATA_T* data = (KILL_DATA_T*)user_data;
+
+    char * appId = NULL;
+    int ret = app_manager_get_app_id(data->pid, &appId);
+    if (APP_MANAGER_ERROR_NONE == ret) {
+        // if context is still alive, error callback should be called.
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_manager_get_app_id()",
+                ApplicationUtil::getApplicationManagerMessage).c_str());
+        data->event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+    auto_free_char_ptr ptr(&appId, char_ptr_deleter);
+
+    data->appManager->invokeManualAnswerKill(data->pid);
+    free(appId);
+
+    return false;
+}
+
+
+void ApplicationManager::OnRequestReceived(const EventApplicationKillPtr& event)
+{
+    LOGD("Entered");
+    Try
+    {
+        int ret;
+        std::string contextId = event->getContextId();
+
+        if (contextId.empty())
+        {
+            LOGE("Context id is mandatory");
+            event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+            return;
+        }
+
+        int pid;
+        std::stringstream(contextId) >> pid;
+        if (pid <= 0)
+        {
+            LOGE("Given context id is wrong");
+            event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+            return;
+        }
+
+        // if kill request is come for current context, throw InvalidValueException by spec
+        if (pid == getppid())
+        {
+            event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+            return;
+        }
+
+        char *appIdCStr = NULL;
+        ret = app_manager_get_app_id(pid, &appIdCStr);
+        if (APP_MANAGER_ERROR_NONE != ret)
+        {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_manager_get_app_id()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+            return;
+        }
+
+        std::string appId = appIdCStr;
+        free(appIdCStr);
+
+        app_context_h appContext;
+        ret = app_manager_get_app_context (appId.c_str(), &appContext);
+        if (APP_MANAGER_ERROR_NONE != ret)
+        {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_manager_get_app_context()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+            return;
+        }
+
+        // TODO thread
+        ret = app_manager_set_app_context_event_cb(app_manager_app_context_event_callback, this);
+        if (APP_MANAGER_ERROR_NONE != ret)
+        {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_manager_set_app_context_event_cb()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
+            return;
+        }
+
+        ret = app_manager_terminate_app(appContext);
+        if (APP_MANAGER_ERROR_NONE != ret)
+        {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_manager_terminate_app()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
+            return;
+        }
+
+        // Because of platform issue, some termination event is not come to
+        //app_manager_set_app_context_event_cb().
+        // To prevent blocking issue by wating callback function,
+        //add termination checking code.
+        // this function check whether callback is called or not after 3 sec.
+        //if callback is not called, calls callback function forcibily.
+        // After fixing platform issue, below code should be removed
+        {
+            KILL_DATA_T *data = new KILL_DATA_T;
+            data->pid = pid;
+            data->appManager = this;
+            data->event = event;
+            g_timeout_add(3000, check_terminate_callback, (void*)data);
+        }
+
+        std::lock_guard<std::mutex> lock(m_killMapLock);
+        m_killEventMap[pid] = event;
+        event->switchToManualAnswer();
+    }
+    Catch (WrtDeviceApis::Commons::Exception)
+    {
+        LOGE("Error on kill : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+}
+
+void ApplicationManager::OnRequestReceived(
+        const EventApplicationLaunchAppControlPtr& event)
+{
+    LOGD("Entered");
+    Try
+    {
+        int ret = 0;
+        int retry = 0;
+
+        ApplicationControlPtr appControl = event->getAppControl();
+        if (appControl.get() == NULL)
+        {
+            LOGE("appControl is mandatory");
+            event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+            return;
+        }
+
+        std::string operation = appControl->getOperation();
+        if (operation.empty())
+        {
+            LOGE("operation is madatory");
+            event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+            return;
+        }
+
+        if (!appControl->isValid())
+        {
+            LOGE("mandatory scheme is omitted");
+            event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+            return;
+        }
+
+        std::string appId = event->getAppId();
+
+        app_control_h service;
+        ret = app_control_create(&service);
+        if (APP_CONTROL_ERROR_NONE != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_create()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+        }
+
+        if (!appId.empty())
+        {
+            ret = app_control_set_app_id(service, appId.c_str());
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_set_app_id()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+            // get resolved app id for aliased app id cannot be used to app_info_create()
+            char* resolved_app_id = NULL;
+            ret = app_control_get_app_id(service, &resolved_app_id);
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_get_app_id()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+
+            // Application exist checking. if specific application is not exist, return Not Found Exception.
+            app_info_h info_h;
+            ret = app_info_create(resolved_app_id, &info_h);
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_info_create()",
+                        ApplicationUtil::getApplicationManagerMessage).c_str());
+                event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+                if (resolved_app_id) {
+                    free(resolved_app_id);
+                }
+                ret = app_control_destroy(service);
+                if (APP_CONTROL_ERROR_NONE != ret) {
+                    LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                            "app_control_destroy()",
+                            ApplicationUtil::getApplicationMessage).c_str());
+                }
+                return;
+            }
+
+            ret = app_info_destroy(info_h);
+            if (APP_MANAGER_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_info_destroy()",
+                        ApplicationUtil::getApplicationManagerMessage).c_str());
+            }
+
+            if (resolved_app_id) {
+                free(resolved_app_id);
+            }
+        }
+
+        const char* windowId = IPCMessageSupport::sendMessageToUiProcess(
+                "tizen://getWindowHandle", NULL);
+        if (windowId != NULL)
+        {
+            ret = app_control_set_window(service, atoi(windowId));
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_set_window()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        ret = app_control_set_operation(service, operation.c_str() );
+        if (APP_CONTROL_ERROR_NONE != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_set_operation()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+        }
+
+        std::string uri = appControl->getUri();
+        if (!uri.empty())
+        {
+            ret = app_control_set_uri(service, uri.c_str() );
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_set_uri()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        std::string mime = appControl->getMime();
+        if (!mime.empty())
+        {
+            ret = app_control_set_mime(service, mime.c_str() );
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_set_mime()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        std::string category = appControl->getCategory();
+        if (!category.empty())
+        {
+            ret = app_control_set_category(service, category.c_str() );
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_set_category()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        std::vector<ApplicationControlDataPtr> appControlDataArray =
+                appControl->getAppControlDataArray();
+
+        if (!appControlDataArray.empty())
+        {
+            LOGI(" data size: %u", appControlDataArray.size());
+
+            ApplicationControlDataArray::iterator iter;
+            for (iter = appControlDataArray.begin(); iter !=
+                    appControlDataArray.end(); iter++)
+            {
+                ApplicationControlDataPtr appControlData = *iter;
+
+                std::string key = appControlData->getKey();
+
+                if (key.empty())
+                {
+                    event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+                    continue;
+                }
+
+                std::vector<std::string> valueArray = appControlData->getValue();
+                size_t size = valueArray.size();
+
+                const char **arr = (const char**)calloc(sizeof(char*), size);
+
+                for (size_t j = 0; j < size; j++)
+                {
+                    arr[j] = valueArray.at(j).c_str();
+                }
+
+                // @20121207-wscho: roll-back to return extra-data instead of
+                //extra-data array when the value size is one.
+                const char *keyCStr = key.c_str();
+                if (size == 1) {
+                    ret = app_control_add_extra_data(service, keyCStr, arr[0]);
+                    if (APP_CONTROL_ERROR_NONE != ret) {
+                        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                                "app_control_add_extra_data()",
+                                ApplicationUtil::getApplicationMessage).c_str());
+                    }
+                } else {
+                    ret = app_control_add_extra_data_array(service, keyCStr, arr, size);
+                    if (APP_CONTROL_ERROR_NONE != ret) {
+                        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                                "app_control_add_extra_data_array()",
+                                ApplicationUtil::getApplicationMessage).c_str());
+                    }
+                }
+
+                if (arr)
+                    free(arr);
+            }
+        }
+
+        LaunchAppControlPendingEvent *pendingEvent = NULL;
+        LaunchAppControlPendingEventMap::DataKeyType key = 0;
+
+        EventApplicationLaunchAppControlReplyPtr eventReply = event->getEventReply();
+        if (eventReply)
+        {
+            pendingEvent = new LaunchAppControlPendingEvent((void*)this, eventReply);
+            key = gLaunchAppControlPendingEventMap.insert(this, pendingEvent);
+        }
+
+        // give a second chance to launch application to avoid platform issue.
+        // this retry code will be removed after platform code change.
+        while (retry < 3) {
+            ret = app_control_send_launch_request(service,
+                    app_control_reply_callback,
+                    (void *)key);
+            if (APP_CONTROL_ERROR_LAUNCH_REJECTED != ret) {
+                break;
+            }
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_send_launch_request()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+            // delay 300ms for each retry
+            usleep(300 * 1000);
+            retry++;
+            LOGD("retry launch request : %d", retry);
+        }
+
+        int result = app_control_destroy(service);
+        if (APP_CONTROL_ERROR_NONE != result) {
+            LOGE("%s", ApplicationUtil::getApplicationErrorMessage(result,
+                    "app_control_destroy()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+        }
+
+        if (APP_CONTROL_ERROR_NONE != ret)
+        {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_send_launch_request()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+            switch (ret)
+            {
+            case APP_CONTROL_ERROR_INVALID_PARAMETER:
+                LOGE("app_control_send_launch_request returns APP_CONTROL_ERROR_INVALID_PARAMETER");
+                event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+                break;
+            case APP_CONTROL_ERROR_OUT_OF_MEMORY:
+                LOGE("app_control_send_launch_request returns APP_CONTROL_ERROR_OUT_OF_MEMORY");
+                event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+                break;
+            case APP_CONTROL_ERROR_LAUNCH_REJECTED:
+                LOGE("app_control_send_launch_request returns APP_CONTROL_ERROR_LAUNCH_REJECTED!!!");
+                event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+                break;
+            case APP_CONTROL_ERROR_APP_NOT_FOUND:
+                LOGE("app_control_send_launch_request returns APP_CONTROL_ERROR_APP_NOT_FOUND");
+                event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+                break;
+            case APP_CONTROL_ERROR_PERMISSION_DENIED:
+                LOGE("app_control_send_launch_request returns APP_CONTROL_ERROR_PERMISSION_DENIED");
+                event->setExceptionCode(Commons::ExceptionCodes::SecurityException);
+                break;
+            default:
+                LOGE("app_control_send_launch_request returns UNKNOWN ERROR!!!");
+                event->setExceptionCode(Commons::ExceptionCodes::UnknownException);
+                break;
+            }
+
+            if (pendingEvent)
+            {
+                gLaunchAppControlPendingEventMap.eraseData(key);
+
+                delete pendingEvent;
+                pendingEvent = NULL;
+
+                eventReply->cancelRequest();
+                EventRequestReceiver<EventApplicationLaunchAppControlReply>::ManualAnswer(eventReply);
+            }
+        }
+        if (windowId != NULL)
+        {
+            free((char*)windowId);
+        }
+
+    }
+    Catch (WrtDeviceApis::Commons::Exception)
+    {
+        LOGE("Error on launchAppControl : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+
+}
+
+void ApplicationManager::OnRequestReceived(const EventApplicationLaunchAppControlReplyPtr& event)
+{
+    LOGD("Entered");
+    event->switchToManualAnswer();
+}
+
+void ApplicationManager::OnRequestReceived(const EventApplicationFindAppControlPtr& event)
+{
+    LOGD("Entered");
+    Try
+    {
+        ApplicationControlPtr appControl = event->getAppControl();
+        if (appControl.get() == NULL)
+        {
+            LOGE("appControl is NULL");
+            event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+            return;
+        }
+
+        std::string operation = appControl->getOperation();
+        if (operation.empty())
+        {
+            LOGE("operation is madatory");
+            event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+            return;
+        }
+
+        if (!appControl->isValid())
+        {
+            LOGE("madatory scheme is omitted");
+            event->setExceptionCode(Commons::ExceptionCodes::InvalidArgumentException);
+            return;
+        }
+
+        app_control_h service;
+        int ret = app_control_create(&service);
+        if (APP_CONTROL_ERROR_NONE != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_create()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+        }
+
+        ret = app_control_set_operation(service, operation.c_str() );
+        if (APP_CONTROL_ERROR_NONE != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_set_operation()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+        }
+
+        std::string uri = appControl->getUri();
+        if (!uri.empty())
+        {
+            ret = app_control_set_uri(service, uri.c_str() );
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_set_uri()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        std::string mime = appControl->getMime();
+        if (!mime.empty())
+        {
+            ret = app_control_set_mime(service, mime.c_str() );
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_set_mime()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        std::string category = appControl->getCategory();
+        if (!category.empty())
+        {
+            ret = app_control_set_category(service, category.c_str() );
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_set_category()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+        }
+
+        std::vector<ApplicationControlDataPtr> appControlDataArray =
+                appControl->getAppControlDataArray();
+
+        if (!appControlDataArray.empty())
+        {
+            LOGD(" data size: %u", appControlDataArray.size());
+
+            ApplicationControlDataArray::iterator iter;
+            for (iter = appControlDataArray.begin(); iter !=
+                    appControlDataArray.end(); iter++)
+            {
+                ApplicationControlDataPtr appControlData = *iter;
+
+                std::string key = appControlData->getKey();
+
+                if (key.empty())
+                {
+                    event->setExceptionCode(
+                            Commons::ExceptionCodes::InvalidArgumentException);
+                    continue;
+                }
+
+                std::vector<std::string> valueArray = appControlData->getValue();
+                size_t size = valueArray.size();
+
+                const char **arr = (const char**)calloc(sizeof(char*), size);
+
+                for (size_t j = 0; j < size; j++)
+                {
+                    arr[j] = valueArray.at(j).c_str();
+                }
+
+                // @20121207-wscho: roll-back to return extra-data instead of
+                //extra-data array when the value size is one.
+                const char *keyCStr = key.c_str();
+                if (size == 1) {
+                    ret = app_control_add_extra_data(service, keyCStr, arr[0]);
+                    if (APP_CONTROL_ERROR_NONE != ret) {
+                        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                                "app_control_add_extra_data()",
+                                ApplicationUtil::getApplicationMessage).c_str());
+                    }
+                } else {
+                    ret = app_control_add_extra_data_array(service, keyCStr, arr, size);
+                    if (APP_CONTROL_ERROR_NONE != ret) {
+                        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                                "app_control_add_extra_data_array()",
+                                ApplicationUtil::getApplicationMessage).c_str());
+                    }
+                }
+
+                if (arr)
+                    free(arr);
+            }
+        }
+
+        ApplicationInformationArrayPtr appInfos(new ApplicationInformationArray());
+
+        int result = app_control_foreach_app_matched(service,
+                service_app_matched_callback,
+                (void *)appInfos.get());
+        if (APP_CONTROL_ERROR_NONE != result)
+        {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(result,
+                    "app_control_foreach_app_matched()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+            int ret = app_control_destroy(service);
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_destroy()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+            return;
+        }
+
+        ret = app_control_destroy(service);
+        if (APP_CONTROL_ERROR_NONE != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_control_destroy()",
+                    ApplicationUtil::getApplicationMessage).c_str());
+        }
+        event->setAppInfos(appInfos);
+    }
+    Catch (WrtDeviceApis::Commons::Exception)
+    {
+        LOGE("Error on findAppControl : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+}
+
+
+void ApplicationManager::OnRequestReceived(const EventApplicationGetAppsContextPtr& event)
+{
+    LOGD("Entered");
+    Try
+    {
+        int ret = 0;
+
+        ApplicationContextArrayPtr appContextArray = event->getAppContextArray();
+        ret = app_manager_foreach_app_context(app_manager_app_context_callback,
+                appContextArray.get());
+        if (APP_MANAGER_ERROR_NONE != ret)
+        {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "app_manager_foreach_app_context()",
+                    ApplicationUtil::getApplicationManagerMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+        }
+    }
+    Catch (WrtDeviceApis::Commons::Exception)
+    {
+        LOGE("Error on  : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+}
+
+
+
+void ApplicationManager::OnRequestReceived(const EventApplicationGetAppsInfoPtr& event)
+{
+    LOGD("Entered");
+    Try
+    {
+        int ret = 0;
+
+        ret = pkgmgrinfo_pkginfo_get_list(get_package_list_cb, (void *)this);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_pkginfo_get_list()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+        }
+        gPkgInfoMapTriggered = true;
+
+        ApplicationInformationArrayPtr appInfoArray = event->getAppInfoArray();
+        gPkgIdMap.clear();
+        ret = pkgmgrinfo_appinfo_get_installed_list(installed_app_info_cb,
+                (void*)appInfoArray.get());
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_appinfo_get_installed_list()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+            event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+        }
+
+        gPkgIdMapInited = true;
+
+        gPkgInfoMapTriggered = false;
+        gPkgInfoMap.clear();
+    }
+    Catch (WrtDeviceApis::Commons::Exception)
+    {
+        LOGE("Error on getAppsInfo : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+}
+
+
+void ApplicationManager::OnRequestReceived(
+        const EventApplicationAddAppInfoEventListenerPtr& event)
+{
+    LOGD("Entered");
+    Try
+    {
+        EventApplicationAppInfoEventListenerEmitterPtr emitter = event->getEmitter();
+
+        if (m_installedApplicationsEmitters.size() == 0)
+        {
+            LOGD("First time registering event listener to this application object.");
+
+            // Below can throw Exception
+            AppManagerWrapperSingleton::Instance().registerAppListChangedCallbacks(this);
+        }
+
+        m_installedApplicationsEmitters.attach(emitter);
+
+        long watchId = AppManagerWrapperSingleton::Instance().getWatchIdAndInc();
+
+        m_watchIdMap[watchId] = emitter->getId();
+
+        event->setWatchId(watchId);
+    }
+    Catch (WrtDeviceApis::Commons::Exception)
+    {
+        LOGE("Error on addAppInfoEventListener : %s",
+                _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+}
+
+void ApplicationManager::OnRequestReceived(
+        const EventApplicationRemoveAppInfoEventListenerPtr& event)
+{
+    LOGD("Entered");
+    Try
+    {
+        long watchId = event->getWatchId();
+
+        if (m_watchIdMap.find(watchId) == m_watchIdMap.end()) {
+            ThrowMsg(NotFoundException, "No watchId : " << watchId);
+        }
+
+        EventApplicationAppInfoEventListenerEmitter::IdType emitterId =
+                m_watchIdMap[watchId];
+
+        bool success = m_installedApplicationsEmitters.detach(emitterId);
+        if (!success)
+            ThrowMsg(NotFoundException, "No watchId : " << watchId);
+
+        if (m_installedApplicationsEmitters.size() == 0)
+        {
+            LOGD("No more event listener on this application object.");
+
+            AppManagerWrapperSingleton::Instance().unregisterAppListChangedCallbacks(this);
+        }
+    }
+    Catch (WrtDeviceApis::Commons::NotFoundException)
+    {
+        LOGE("Not found : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+    }
+    Catch (WrtDeviceApis::Commons::Exception)
+    {
+        LOGE("Error on removeAppInfoEventListener : %s",
+                _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::PlatformException);
+    }
+}
+
+
+
+void ApplicationManager::onAppManagerEventInstalled(const char *appId)
+{
+    LOGD("Entered");
+    EventApplicationAppInfoEventListenerPtr event(new EventApplicationAppInfoEventListener());
+
+    pkgmgrinfo_appinfo_h handle;
+    int ret = pkgmgrinfo_appinfo_get_appinfo(appId, &handle);
+    if (ret != PMINFO_R_OK) {
+        event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+    } else {
+        ApplicationInformationPtr appInfo = create_app_info(handle);
+        event->setAppInfo(appInfo);
+        pkgmgrinfo_appinfo_destroy_appinfo(handle);
+    }
+
+    event->setType(EventApplicationAppInfoEventListener::OnInstalled);
+    m_installedApplicationsEmitters.emit(event);
+}
+
+void ApplicationManager::onAppManagerEventUninstalled(const char *appId)
+{
+    LOGD("Entered");
+    EventApplicationAppInfoEventListenerPtr event(new EventApplicationAppInfoEventListener());
+
+    ApplicationInformationPtr appInfo(new ApplicationInformation(appId));
+
+    event->setType(EventApplicationAppInfoEventListener::OnUninstalled);
+    event->setAppInfo(appInfo);
+    m_installedApplicationsEmitters.emit(event);
+}
+
+void ApplicationManager::onAppManagerEventUpdated(const char *appId)
+{
+    LOGD("Entered");
+    EventApplicationAppInfoEventListenerPtr event(new EventApplicationAppInfoEventListener());
+
+    pkgmgrinfo_appinfo_h handle;
+    int ret = pkgmgrinfo_appinfo_get_appinfo(appId, &handle);
+    if (PMINFO_R_OK != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "pkgmgrinfo_appinfo_get_appinfo()",
+                ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        event->setExceptionCode(Commons::ExceptionCodes::NotFoundException);
+    } else {
+        ApplicationInformationPtr appInfo = create_app_info(handle);
+        event->setAppInfo(appInfo);
+        ret = pkgmgrinfo_appinfo_destroy_appinfo(handle);
+        if (PMINFO_R_OK != ret) {
+            LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                    "pkgmgrinfo_appinfo_destroy_appinfo()",
+                    ApplicationUtil::getApplicationPkgmgrinfoMessage).c_str());
+        }
+    }
+
+    event->setType(EventApplicationAppInfoEventListener::OnUpdated);
+    m_installedApplicationsEmitters.emit(event);
+}
+
+void ApplicationManager::initialize()
+{
+    LOGD("Entered");
+    if (!m_initialized) {
+        std::lock_guard<std::mutex> lock(m_initializationMutex);
+        if (!m_initialized) {
+
+        }
+    }
+}
+
+}
+}
diff --git a/src/Application/ApplicationManager.h b/src/Application/ApplicationManager.h
new file mode 100755 (executable)
index 0000000..df5ee12
--- /dev/null
@@ -0,0 +1,292 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_PLATFORM_APPLICATION_H_
+#define TIZENAPIS_PLATFORM_APPLICATION_H_
+
+#include <map>
+#include <set>
+#include <list>
+#include <Commons/Emitters.h>
+#include <Logger.h>
+
+#include "IApplicationManager.h"
+#include "ApplicationFactory.h"
+#include "Application.h"
+#include "ApplicationContext.h"
+#include "ApplicationInformation.h"
+#include "ApplicationCert.h"
+#include "ApplicationMetaData.h"
+
+//#include <app_manager.h>
+#include <app_control.h>
+
+#include "AppManagerWrapper.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationManager: public IApplicationManager, public IAppManagerAppListChangedCallbacks {
+    friend class ApplicationFactory;
+
+public:
+    ApplicationManager();
+    virtual ~ApplicationManager();
+    virtual void launch(const EventApplicationLaunchPtr& event);
+    virtual void kill(const EventApplicationKillPtr& event);
+    virtual void launchAppControl(const EventApplicationLaunchAppControlPtr& event);
+    virtual void findAppControl(const EventApplicationFindAppControlPtr& event);
+    virtual void getAppsContext(const EventApplicationGetAppsContextPtr& event);
+    virtual void getAppsInfo(const EventApplicationGetAppsInfoPtr& event);
+    virtual void addAppInfoEventListener(
+            const EventApplicationAddAppInfoEventListenerPtr& event);
+    virtual void removeAppInfoEventListener(
+            const EventApplicationRemoveAppInfoEventListenerPtr& event);
+
+    void invokeManualAnswerLaunchAppControl(app_control_h request,
+            app_control_h reply,
+            app_control_result_e result,
+            EventApplicationLaunchAppControlReplyPtr &event);
+    void invokeManualAnswerKill(int pid);
+
+    static bool service_extra_data_callback(app_control_h service,
+            const char *key,
+            void* user_data);
+
+    static ApplicationPtr getCurrentApplication();
+    static ApplicationContextPtr getAppContext(const std::string id);
+    static ApplicationInformationPtr getAppInfo(const std::string id);
+    static ApplicationCertArrayPtr getAppCerts(const std::string id);
+    static std::string getAppSharedURI(const std::string appId);
+    static ApplicationMetaDataArrayPtr getAppMetaData(const std::string id);
+
+protected:
+    virtual void OnRequestReceived(const EventApplicationLaunchPtr& event);
+    virtual void OnRequestReceived(const EventApplicationKillPtr& event);
+    virtual void OnRequestReceived(const EventApplicationLaunchAppControlPtr& event);
+    virtual void OnRequestReceived(const EventApplicationLaunchAppControlReplyPtr& event);
+    virtual void OnRequestReceived(const EventApplicationFindAppControlPtr& event);
+    virtual void OnRequestReceived(const EventApplicationGetAppsContextPtr& event);
+    virtual void OnRequestReceived(const EventApplicationGetAppsInfoPtr& event);
+    virtual void OnRequestReceived(const EventApplicationAddAppInfoEventListenerPtr& event);
+    virtual void OnRequestReceived(const EventApplicationRemoveAppInfoEventListenerPtr& event);
+
+    // inherited from IAppManagerAppListChangedCallbacks
+    virtual void onAppManagerEventInstalled(const char *appId);
+    virtual void onAppManagerEventUninstalled(const char *appId);
+    virtual void onAppManagerEventUpdated(const char *appId);
+
+private:
+    void initialize();
+
+    std::mutex m_initializationMutex;
+    bool m_initialized;
+
+    std::map<int, EventApplicationKillPtr> m_killEventMap;
+    mutable std::mutex m_killMapLock;
+
+    typedef WrtDeviceApis::Commons::Emitters<EventApplicationAppInfoEventListenerEmitter> EventApplicationAppInfoEventListenerEmitters;
+    typedef std::map<long, EventApplicationAppInfoEventListenerEmitter::IdType> WatchIdMap;
+
+    EventApplicationAppInfoEventListenerEmitters m_installedApplicationsEmitters;
+    WatchIdMap      m_watchIdMap;
+
+};
+
+class LaunchAppControlPendingEvent
+{
+public:
+    LaunchAppControlPendingEvent(void *thisObject,
+            const EventApplicationLaunchAppControlReplyPtr &event) :
+        m_thisObject(thisObject),
+        m_event(event)
+    {
+        LOGD("Entered");
+    }
+
+    virtual ~LaunchAppControlPendingEvent()
+    {
+        LOGD("Entered");
+    }
+
+    void* getThisObject() const
+    {
+        LOGD("Entered");
+        return m_thisObject;
+    }
+    EventApplicationLaunchAppControlReplyPtr getEvent() const
+    {
+        LOGD("Entered");
+        return m_event;
+    }
+
+private:
+    void *m_thisObject;
+    EventApplicationLaunchAppControlReplyPtr m_event;
+};
+
+
+template <class KeyType, class DataType>
+class KeyMultiMap
+{
+public:
+    typedef unsigned int                                DataKeyType;
+    typedef DataType *                                  DataPtrType;
+    typedef std::pair<KeyType, DataPtrType>             KeyDataPairType;
+    typedef std::map<DataKeyType, KeyDataPairType>      DataMapType;
+    typedef std::set<DataKeyType>                       DataKeySetType;
+    typedef std::map<KeyType, DataKeySetType>           KeyMapType;
+    typedef std::list<DataPtrType>                      DataPtrListType;
+
+    KeyMultiMap() :
+        m_keyAcc(0)
+    {
+        LOGD("Entered");
+    }
+
+    DataKeyType insert(const KeyType &key, const DataPtrType &dataPtr)
+    {
+        LOGD("Entered");
+        DataKeyType dataKey = ++m_keyAcc;
+
+        KeyDataPairType pair(key, dataPtr);
+        m_dataMap.insert(std::pair<DataKeyType, KeyDataPairType>(dataKey, pair));
+
+        typename KeyMapType::iterator keyMapIter = m_keyMap.find(key);
+        if (keyMapIter == m_keyMap.end())
+        {
+            DataKeySetType newKeySet;
+            m_keyMap.insert(std::pair<KeyType, DataKeySetType>(key, newKeySet));
+            keyMapIter = m_keyMap.find(key);
+        }
+
+        DataKeySetType &dataKeySet = keyMapIter->second;
+
+        dataKeySet.insert(dataKey);
+
+        return dataKey;
+    }
+
+    DataPtrType getData(const DataKeyType &dataKey) const
+    {
+        LOGD("Entered");
+        typename DataMapType::const_iterator dataMapIter = m_dataMap.find(dataKey);
+
+        if (dataMapIter == m_dataMap.end())
+            return static_cast<DataPtrType>(NULL);
+
+        return dataMapIter->second.second;
+    }
+
+    DataPtrListType getDataPtrList(const KeyType &key)
+    {
+        LOGD("Entered");
+        DataPtrListType dataPtrList;
+
+        typename KeyMapType::const_iterator keyMapIter = m_keyMap.find(key);
+        if (keyMapIter == m_keyMap.end())
+            return dataPtrList;
+
+        DataKeySetType keySet = keyMapIter->second;
+        DataKeySetType::iterator keySetIter = keySet.begin();
+        for (; keySetIter != keySet.end(); keySetIter++)
+        {
+            DataPtrType dataPtr = getData(*keySetIter);
+            if (dataPtr == NULL)
+            {
+                LOGD("No data for %u", *keySetIter);
+                break;
+            }
+
+            dataPtrList.push_back(dataPtr);
+        }
+
+        return dataPtrList;
+    }
+
+    void eraseData(const DataKeyType &dataKey)
+    {
+        LOGD("Entered");
+        typename DataMapType::iterator dataKeyIter = m_dataMap.find(dataKey);
+
+        if (dataKeyIter == m_dataMap.end())
+        {
+            LOGD("No data for %u", dataKey);
+            return;
+        }
+
+        KeyType key = dataKeyIter->second.first;
+
+        m_dataMap.erase(dataKeyIter);
+
+        typename KeyMapType::iterator keyMapIter = m_keyMap.find(key);
+        if (keyMapIter == m_keyMap.end())
+        {
+            LOGD("No data for Key");
+            return;
+        }
+
+        DataKeySetType &keySet = keyMapIter->second;
+        DataKeySetType::iterator keySetIter = keySet.find(dataKey);
+        if (keySetIter == keySet.end())
+        {
+            LOGD("No data for %u", dataKey);
+            return;
+        }
+
+        keySet.erase(keySetIter);
+    }
+
+    void eraseKey(const KeyType &key)
+    {
+        LOGD("Entered");
+        typename KeyMapType::iterator keyMapIter = m_keyMap.find(key);
+        if (keyMapIter == m_keyMap.end())
+        {
+            LOGD("No data to erase.");
+            return;
+        }
+
+        DataKeySetType &keySet = keyMapIter->second;
+        DataKeySetType::iterator keySetIter = keySet.begin();
+        for (; keySetIter != keySet.end(); keySetIter++)
+        {
+            typename DataMapType::iterator dataKeyIter = m_dataMap.find(*keySetIter);
+            if (dataKeyIter == m_dataMap.end())
+            {
+                LOGD("No data to erase.");
+                break;
+            }
+
+            m_dataMap.erase(dataKeyIter);
+        }
+
+        m_keyMap.erase(keyMapIter);
+    }
+
+private:
+    DataKeyType m_keyAcc;
+
+    DataMapType m_dataMap;
+    KeyMapType m_keyMap;
+};
+
+}
+}
+
+#endif
diff --git a/src/Application/ApplicationMetaData.cpp b/src/Application/ApplicationMetaData.cpp
new file mode 100644 (file)
index 0000000..3653ce4
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ApplicationMetaData.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+ApplicationMetaData::ApplicationMetaData()
+{
+    LOGD("Entered");
+}
+
+ApplicationMetaData::~ApplicationMetaData()
+{
+    LOGD("Entered");
+}
+
+std::string ApplicationMetaData::getKey() const
+{
+    LOGD("Entered");
+    return m_key;
+}
+
+void ApplicationMetaData::setKey(const std::string &key)
+{
+    LOGD("Entered");
+    m_key = key;
+}
+
+std::string ApplicationMetaData::getValue() const
+{
+    LOGD("Entered");
+    return m_value;
+}
+
+void ApplicationMetaData::setValue(const std::string &value)
+{
+    LOGD("Entered");
+    m_value = value;
+}
+
+}
+}
diff --git a/src/Application/ApplicationMetaData.h b/src/Application/ApplicationMetaData.h
new file mode 100644 (file)
index 0000000..5a268b8
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_META_DATA_H_
+#define TIZENAPIS_API_APPLICATION_META_DATA_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+class ApplicationMetaData;
+typedef std::shared_ptr<ApplicationMetaData> ApplicationMetaDataPtr;
+
+typedef std::vector<ApplicationMetaDataPtr> ApplicationMetaDataArray;
+typedef std::shared_ptr<ApplicationMetaDataArray> ApplicationMetaDataArrayPtr;
+
+
+class ApplicationMetaData
+{
+  public:
+    ApplicationMetaData();
+    ~ApplicationMetaData();
+
+    std::string getKey() const;
+    void setKey(const std::string &key);
+    std::string getValue() const;
+    void setValue(const std::string &value);
+
+  private:
+    std::string m_key;
+    std::string m_value;
+};
+}
+}
+#endif
diff --git a/src/Application/ApplicationUtil.cpp b/src/Application/ApplicationUtil.cpp
new file mode 100755 (executable)
index 0000000..0e383e4
--- /dev/null
@@ -0,0 +1,269 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ApplicationUtil.h"
+#include <app.h>
+#include <app_info.h>
+#include <app_manager.h>
+#include <pkgmgr-info.h>
+#include <package_manager.h>
+#include <aul.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+ApplicationUtil::ApplicationUtil(JSContextRef context,
+        JSValueRef* exception) :
+    m_context(context),
+    m_exception(exception)
+{
+    LOGD("Entered");
+}
+
+ApplicationUtil::~ApplicationUtil()
+{
+    LOGD("Entered");
+}
+
+bool ApplicationUtil::isObject(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    return !JSValueIsNull(m_context, arg) &&
+           !JSValueIsUndefined(m_context, arg) &&
+           JSValueIsObject(m_context, arg);
+}
+
+bool ApplicationUtil::isString(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    return !JSValueIsNull(m_context, arg) &&
+           !JSValueIsUndefined(m_context, arg) &&
+           JSValueIsString(m_context, arg);
+}
+
+bool ApplicationUtil::isFunction(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    Converter converter(m_context);
+    return !JSValueIsNull(m_context, arg) &&
+            !JSValueIsUndefined(m_context, arg) &&
+            JSObjectIsFunction(m_context, converter.toJSObjectRef(arg));
+}
+
+bool ApplicationUtil::isArray(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    Converter converter(m_context);
+    return !JSValueIsNull(m_context, arg) &&
+           !JSValueIsUndefined(m_context, arg) &&
+           JSIsArrayValue(m_context, arg);
+}
+
+bool ApplicationUtil::isNullOrString(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    return !JSValueIsUndefined(m_context, arg) &&
+           (JSValueIsNull(m_context, arg) ||
+           JSValueIsString(m_context, arg));
+}
+
+bool ApplicationUtil::isNullOrObject(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    return !JSValueIsUndefined(m_context, arg) &&
+           (JSValueIsNull(m_context, arg) ||
+           JSValueIsObject(m_context, arg));
+}
+
+bool ApplicationUtil::isNullOrFunction(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    Converter converter(m_context);
+    return !JSValueIsUndefined(m_context, arg) &&
+           (JSValueIsNull(m_context, arg) ||
+           JSObjectIsFunction(m_context, converter.toJSObjectRef(arg)));
+}
+
+bool ApplicationUtil::isNullOrArray(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    Converter converter(m_context);
+    return !JSValueIsUndefined(m_context, arg) &&
+           (JSValueIsNull(m_context, arg) ||
+           JSIsArrayValue(m_context, arg));
+}
+
+bool ApplicationUtil::isNullOrUndefined(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    return (JSValueIsNull(m_context, arg) ||
+            JSValueIsUndefined(m_context, arg));
+}
+
+bool ApplicationUtil::isNullOrUndefinedOrString(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    return (JSValueIsNull(m_context, arg) ||
+           JSValueIsUndefined(m_context, arg) ||
+           JSValueIsString(m_context, arg));
+}
+
+bool ApplicationUtil::isNullOrUndefinedOrObject(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    return (JSValueIsNull(m_context, arg) ||
+           JSValueIsUndefined(m_context, arg) ||
+           JSValueIsObject(m_context, arg));
+}
+
+bool ApplicationUtil::isNullOrUndefinedOrFunction(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    Converter converter(m_context);
+    return (JSValueIsNull(m_context, arg) ||
+           JSValueIsUndefined(m_context, arg) ||
+           JSObjectIsFunction(m_context, converter.toJSObjectRef(arg)));
+}
+
+bool ApplicationUtil::isNullOrUndefinedOrArray(const JSValueRef& arg)
+{
+    LOGD("Entered");
+    Converter converter(m_context);
+    return (JSValueIsNull(m_context, arg) ||
+           JSValueIsUndefined(m_context, arg) ||
+           JSIsArrayValue(m_context, arg));
+}
+
+std::string ApplicationUtil::getApplicationMessage(const int errorCode)
+{
+    LOGD("Entered");
+    switch(errorCode) {
+        case APP_CONTROL_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case APP_CONTROL_ERROR_OUT_OF_MEMORY:
+            return  "Out of memory";
+        case APP_CONTROL_ERROR_APP_NOT_FOUND:
+            return "The application is not found";
+        case APP_CONTROL_ERROR_KEY_NOT_FOUND:
+            return "Specified key is not found";
+        case APP_CONTROL_ERROR_KEY_REJECTED:
+            return "Key is not available";
+        case APP_CONTROL_ERROR_INVALID_DATA_TYPE:
+            return "Invalid data type";
+        case APP_CONTROL_ERROR_LAUNCH_REJECTED:
+            return "The application cannot be launched now";
+        case APP_CONTROL_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case APP_CONTROL_ERROR_LAUNCH_FAILED:
+            return "Internal launch error";
+        case APP_CONTROL_ERROR_TIMED_OUT:
+            return "Time out";
+        default:
+            return "Unknown Error";
+    }
+}
+
+std::string ApplicationUtil::getApplicationManagerMessage(const int errorCode)
+{
+    LOGD("Entered");
+    switch(errorCode) {
+        case APP_MANAGER_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case APP_MANAGER_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case APP_MANAGER_ERROR_IO_ERROR:
+            return "Internal I/O error";
+        case APP_MANAGER_ERROR_NO_SUCH_APP:
+            return "No such application";
+        case APP_MANAGER_ERROR_DB_FAILED:
+            return "Database error";
+        case APP_MANAGER_ERROR_INVALID_PACKAGE:
+            return "Invalid package name";
+        case APP_MANAGER_ERROR_APP_NO_RUNNING:
+            return  "App is not running";
+        case APP_MANAGER_ERROR_REQUEST_FAILED:
+            return "Internal aul request error";
+        case APP_MANAGER_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        default:
+            return "Unknown Error";
+    }
+}
+
+std::string ApplicationUtil::getApplicationPkgmgrinfoMessage(const int errorCode)
+{
+    LOGD("Entered");
+    switch(errorCode) {
+        case PMINFO_R_EINVAL:
+            return "invalid argument";
+        case PMINFO_R_ERROR:
+            return "internal error";
+        default:
+            return "Unknown Error";
+    }
+}
+
+std::string ApplicationUtil::getApplicationPackageManagerMessage(const int errorCode)
+{
+    LOGD("Entered");
+    switch(errorCode) {
+        case PACKAGE_MANAGER_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case PACKAGE_MANAGER_ERROR_IO_ERROR:
+            return "Internal I/O error";
+        case PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE:
+            return "No such package";
+        case PACKAGE_MANAGER_ERROR_SYSTEM_ERROR:
+            return "Severe system error";
+        case PACKAGE_MANAGER_ERROR_PERMISSION_DENIED:
+            return "Permisson denied";
+        default:
+            return "Unknown Error";
+    }
+}
+
+std::string ApplicationUtil::getApplicationAulMessage(const int errorCode)
+{
+    LOGD("Entered");
+    switch(errorCode) {
+        case AUL_R_EINVAL:
+            return "Invaild package name";
+        case AUL_R_ECOMM:
+            return "Internal AUL IPC error";
+        case AUL_R_ERROR:
+            return "General error";
+        default:
+            return "Unknown Error";
+    }
+}
+
+std::string ApplicationUtil::getApplicationErrorMessage(const int errorCode,
+        const std::string &hint,
+        std::string (*function)(const int))
+{
+    LOGD("Entered");
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << function(errorCode) << ", " << errorCode;
+    return ss.str();
+}
+
+}
+}
diff --git a/src/Application/ApplicationUtil.h b/src/Application/ApplicationUtil.h
new file mode 100755 (executable)
index 0000000..d764e10
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_PLATFORM_APPLICATION_UTIL_H_
+#define TIZENAPIS_PLATFORM_APPLICATION_UTIL_H_
+
+#include <CommonsJavaScript/Converter.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+class ApplicationUtil
+{
+  public:
+    explicit ApplicationUtil(JSContextRef context,
+            JSValueRef* exception = NULL);
+    virtual ~ApplicationUtil();
+
+    bool isObject(const JSValueRef& arg);
+    bool isString(const JSValueRef& arg);
+    bool isFunction(const JSValueRef& arg);
+    bool isArray(const JSValueRef& arg);
+    bool isNullOrString(const JSValueRef& arg);
+    bool isNullOrObject(const JSValueRef& arg);
+    bool isNullOrFunction(const JSValueRef& arg);
+    bool isNullOrArray(const JSValueRef& arg);
+    bool isNullOrUndefined(const JSValueRef& arg);
+    bool isNullOrUndefinedOrString(const JSValueRef& arg);
+    bool isNullOrUndefinedOrObject(const JSValueRef& arg);
+    bool isNullOrUndefinedOrFunction(const JSValueRef& arg);
+    bool isNullOrUndefinedOrArray(const JSValueRef& arg);
+
+    static std::string getApplicationMessage(const int errorCode);
+    static std::string getApplicationManagerMessage(const int errorCode);
+    static std::string getApplicationPkgmgrinfoMessage(const int errorCode);
+    static std::string getApplicationPackageManagerMessage(const int errorCode);
+    static std::string getApplicationAulMessage(const int errorCode);
+
+    static std::string getApplicationErrorMessage(const int errorCode,
+            const std::string &hint,
+            std::string (*function)(const int));
+
+    template <class T>
+    static void throwApplicationException(
+              const int errorCode,
+              const std::string &hint,
+              std::string (*function)(const int))
+    {
+        LOGD("Entered");
+        std::string ss = getApplicationErrorMessage(errorCode, hint, function);
+        LOGE("%s", ss.c_str());
+        ThrowMsg(T, ss.c_str());
+    }
+
+  protected:
+    JSContextRef m_context;
+    JSValueRef* m_exception;
+};
+
+}
+} //
+
+#endif
+
diff --git a/src/Application/CMakeLists.txt b/src/Application/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3439b0b
--- /dev/null
@@ -0,0 +1,82 @@
+SET(TARGET_NAME ${application_target})
+SET(DESTINATION_NAME ${application_dest})
+SET(TARGET_IMPL_NAME ${application_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_application REQUIRED
+       capi-appfw-app-manager
+       capi-appfw-application
+       capi-appfw-package-manager
+       pkgmgr
+       pkgmgr-info
+       wrt-plugins-ipc-message
+)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+INCLUDE_DIRECTORIES(
+       ${INCLUDE_COMMON}
+       ${TOP}/Application
+       ${platform_pkgs_application_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+       ${CMAKE_INSTALL_RPATH}
+       ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+       ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+       ApplicationContext.cpp
+       ApplicationControl.cpp
+       ApplicationControlData.cpp
+       RequestedApplicationControl.cpp
+       ApplicationFactory.cpp
+       ApplicationInformation.cpp
+       ApplicationCert.cpp
+       ApplicationMetaData.cpp
+       IApplicationManager.cpp
+       ApplicationManager.cpp
+       AppManagerWrapper.cpp
+       Application.cpp
+       ApplicationAsyncCallbackManager.cpp
+       ApplicationController.cpp
+       ApplicationConverter.cpp
+       ApplicationListenerManager.cpp
+       ApplicationUtil.cpp
+       JSApplication.cpp
+       JSApplicationManager.cpp
+       JSApplicationContext.cpp
+       JSApplicationControl.cpp
+       JSApplicationControlData.cpp
+       JSRequestedApplicationControl.cpp
+       JSApplicationEventCallbackManager.cpp
+       JSApplicationInformation.cpp
+       JSApplicationCert.cpp
+       JSApplicationMetaData.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+       ${LIBS_COMMON}
+       ${tizen_impl}
+       ${platform_pkgs_application_LIBRARIES}
+)
+
+SET(SRCS
+       plugin_config.cpp
+       plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+       ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+       DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/application
+       FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Application/EventApplicationAddAppInfoEventListener.h b/src/Application/EventApplicationAddAppInfoEventListener.h
new file mode 100755 (executable)
index 0000000..1f172ef
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_ADD_APP_INFO_EVENT_LISTENER_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_ADD_APP_INFO_EVENT_LISTENER_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "EventApplicationAppInfoEventListener.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationAddAppInfoEventListener :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationAddAppInfoEventListener>
+{
+private:
+    /* parameter */
+    EventApplicationAppInfoEventListenerEmitterPtr m_emitter;
+
+    /* result */
+    long m_watchId;
+
+public:
+    void setEmitter(EventApplicationAppInfoEventListenerEmitterPtr &value)
+    {
+        LOGD("Entered");
+        m_emitter = value;
+    }
+
+    EventApplicationAppInfoEventListenerEmitterPtr getEmitter() const
+    {
+        LOGD("Entered");
+        return m_emitter;
+    }
+
+    void setWatchId(long watchId)
+    {
+        LOGD("Entered");
+        m_watchId = watchId;
+    }
+
+    long getWatchId() const
+    {
+        LOGD("Entered");
+        return m_watchId;
+    }
+};
+
+typedef std::shared_ptr<EventApplicationAddAppInfoEventListener> EventApplicationAddAppInfoEventListenerPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_ADD_APP_INFO_EVENT_LISTENER_H_
diff --git a/src/Application/EventApplicationAppInfoEventListener.h b/src/Application/EventApplicationAppInfoEventListener.h
new file mode 100755 (executable)
index 0000000..26b6a99
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_APP_INFO_EVENT_LISTENER_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_APP_INFO_EVENT_LISTENER_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include <Commons/ListenerEvent.h>
+#include <Commons/ListenerEventEmitter.h>
+#include <Commons/Emitters.h>
+#include "ApplicationInformation.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationAppInfoEventListener :
+        public WrtDeviceApis::Commons::ListenerEvent<EventApplicationAppInfoEventListener>
+{
+public:
+    enum CallbackType
+    {
+        OnError,
+        OnInstalled,
+        OnUpdated,
+        OnUninstalled
+    };
+
+private:
+    CallbackType m_type;
+
+    std::string m_appId;
+    ApplicationInformationPtr m_appInfo;
+
+public:
+    void setAppId(const std::string &appId)
+    {
+        LOGD("Entered");
+        m_appId = appId;
+    }
+
+    std::string getAppId() const
+    {
+        LOGD("Entered");
+        return m_appId;
+    }
+
+    void setAppInfo(const ApplicationInformationPtr &appInfo)
+    {
+        LOGD("Entered");
+        m_appInfo = appInfo;
+    }
+
+    ApplicationInformationPtr getAppInfo() const
+    {
+        LOGD("Entered");
+        return m_appInfo;
+    }
+
+    void setType(CallbackType type)
+    {
+        LOGD("Entered");
+        m_type = type;
+    }
+
+    int getType() const
+    {
+        LOGD("Entered");
+        return m_type;
+    }
+
+    EventApplicationAppInfoEventListener() :
+        m_type(OnError),
+        m_appInfo(static_cast<ApplicationInformation*>(NULL))
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationAppInfoEventListener> EventApplicationAppInfoEventListenerPtr;
+typedef WrtDeviceApis::Commons::ListenerEventEmitter<EventApplicationAppInfoEventListener> EventApplicationAppInfoEventListenerEmitter;
+typedef std::shared_ptr<EventApplicationAppInfoEventListenerEmitter> EventApplicationAppInfoEventListenerEmitterPtr;
+typedef WrtDeviceApis::Commons::Emitters<EventApplicationAppInfoEventListenerEmitter> EventApplicationAppInfoEventListenerEmitters;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_APP_INFO_EVENT_LISTENER_H_
diff --git a/src/Application/EventApplicationFindAppControl.h b/src/Application/EventApplicationFindAppControl.h
new file mode 100755 (executable)
index 0000000..648ad20
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_FIND_APP_CONTROL_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_FIND_APP_CONTROL_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "ApplicationInformation.h"
+#include "ApplicationControl.h"
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationFindAppControl :
+    public WrtDeviceApis::Commons::IEvent<EventApplicationFindAppControl>,
+    public DeviceAPI::Common::SecurityAccessor
+{
+private:
+    /* parameter */
+    ApplicationControlPtr m_appControl;
+
+    /* result */
+    ApplicationInformationArrayPtr m_appInfoArray;
+
+public:
+    void setAppControl(ApplicationControlPtr &appControl)
+    {
+        LOGD("Entered");
+        m_appControl = appControl;
+    }
+
+    ApplicationControlPtr getAppControl() const
+    {
+        LOGD("Entered");
+        return m_appControl;
+    }
+
+    void setAppInfos(ApplicationInformationArrayPtr &appInfos)
+    {
+        LOGD("Entered");
+        m_appInfoArray = appInfos;
+    }
+
+    ApplicationInformationArrayPtr getAppInfos() const
+    {
+        LOGD("Entered");
+        return m_appInfoArray;
+    }
+
+    EventApplicationFindAppControl() :
+        m_appControl(static_cast<ApplicationControl*>(NULL)),
+        m_appInfoArray(static_cast<ApplicationInformationArray*>(NULL))
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationFindAppControl> EventApplicationFindAppControlPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_FIND_APP_CONTROL_H_
diff --git a/src/Application/EventApplicationGetAppCerts.h b/src/Application/EventApplicationGetAppCerts.h
new file mode 100644 (file)
index 0000000..1bd72a6
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_GET_APP_CERTS_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_GET_APP_CERTS_H_
+
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "ApplicationCert.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationGetAppCerts :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationGetAppCerts>
+{
+private:
+    std::string m_appId;
+    ApplicationCertArrayPtr  m_certs;
+
+public:
+    void setAppId(std::string appId)
+    {
+        LOGD("Entered");
+        m_appId = appId;
+    }
+
+    std::string getAppId()
+    {
+        LOGD("Entered");
+        return m_appId;
+    }
+
+    void setAppCerts(ApplicationCertArrayPtr &certs)
+    {
+        LOGD("Entered");
+        m_certs = certs;
+    }
+
+    ApplicationCertArrayPtr getAppCerts() const
+    {
+        LOGD("Entered");
+        return m_certs;
+    }
+
+    void addAppCert(ApplicationCertPtr cert)
+    {
+        LOGD("Entered");
+        m_certs->push_back(cert);
+    }
+
+    EventApplicationGetAppCerts() :
+        m_certs(new ApplicationCertArray())
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationGetAppCerts> EventApplicationGetAppCertsPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_GET_APP_CERTS_H_
diff --git a/src/Application/EventApplicationGetAppContext.h b/src/Application/EventApplicationGetAppContext.h
new file mode 100755 (executable)
index 0000000..4cdcd3b
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_GET_APP_CONTEXT_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_GET_APP_CONTEXT_H_
+
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "ApplicationContext.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationGetAppContext :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationGetAppContext>
+{
+private:
+    /* parameter */
+    std::string  m_appContextId;
+
+    /* result */
+    ApplicationContextPtr m_appContext;
+
+public:
+    void setAppContextId(std::string appContextId)
+    {
+        LOGD("Entered");
+        m_appContextId = appContextId;
+    }
+
+    std::string getAppContextId() const
+    {
+        LOGD("Entered");
+        return m_appContextId;
+    }
+
+    void setAppContext(const ApplicationContextPtr appContext)
+    {
+        LOGD("Entered");
+        m_appContext = appContext;
+    }
+
+    ApplicationContextPtr getAppContext() const
+    {
+        LOGD("Entered");
+        return m_appContext;
+    }
+
+    EventApplicationGetAppContext() :
+        m_appContext(static_cast<m_appContext*>(NULL))
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationGetAppContext> EventApplicationGetAppContextPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_GET_APP_CONTEXT_H_
diff --git a/src/Application/EventApplicationGetAppInfo.h b/src/Application/EventApplicationGetAppInfo.h
new file mode 100755 (executable)
index 0000000..ac7fcb0
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_GET_APP_INFO_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_GET_APP_INFO_H_
+
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "ApplicationInformation.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationGetAppInfo :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationGetAppInfo>
+{
+private:
+    /* parameter */
+    std::string  m_appId;
+
+    /* result */
+    ApplicationInformationPtr m_appInfo;
+
+public:
+    void setAppId(std::string appId)
+    {
+        LOGD("Entered");
+        m_appId = appId;
+    }
+
+    std::string getAppId() const
+    {
+        LOGD("Entered");
+        return m_appId;
+    }
+
+    void setAppInfo(const ApplicationInformationPtr appInfo)
+    {
+        LOGD("Entered");
+        m_appInfo = appInfo;
+    }
+
+    ApplicationInformationPtr getAppInfo() const
+    {
+        LOGD("Entered");
+        return m_appInfo;
+    }
+
+    EventApplicationGetAppInfo() :
+        m_appInfo(static_cast<m_appInfo*>(NULL))
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationGetAppInfo> EventApplicationGetAppInfoPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_GET_APP_INFO_H_
diff --git a/src/Application/EventApplicationGetAppSharedURI.h b/src/Application/EventApplicationGetAppSharedURI.h
new file mode 100644 (file)
index 0000000..6a3dbcf
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_GET_APP_SHARED_URI_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_GET_APP_SHARED_URI_H_
+
+
+#include <Commons/IEvent.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationGetAppSharedURI :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationGetAppSharedURI>
+{
+private:
+    std::string m_appId;
+    std::string m_sharedURI;
+
+public:
+    void setAppId(std::string appId)
+    {
+        LOGD("Entered");
+        m_appId = appId;
+    }
+
+    std::string getAppId()
+    {
+        LOGD("Entered");
+        return m_appId;
+    }
+
+    void setSharedURI(std::string &sharedURI)
+    {
+        LOGD("Entered");
+        m_sharedURI = sharedURI;
+    }
+
+    std::string getSharedURI() const
+    {
+        LOGD("Entered");
+        return m_sharedURI;
+    }
+
+    EventApplicationGetAppSharedURI()
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationGetAppSharedURI> EventApplicationGetAppSharedURIPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_GET_APP_SHARED_URI_H_
diff --git a/src/Application/EventApplicationGetAppsContext.h b/src/Application/EventApplicationGetAppsContext.h
new file mode 100755 (executable)
index 0000000..aef6eb5
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_GET_APPS_CONTEXT_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_GET_APPS_CONTEXT_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "ApplicationContext.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationGetAppsContext :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationGetAppsContext>
+{
+private:
+    /* result */
+    ApplicationContextArrayPtr m_appContextArray;
+
+public:
+    void addAppContext(const ApplicationContextPtr appContext)
+    {
+        LOGD("Entered");
+        m_appContextArray->push_back(appContext);
+    }
+
+    const ApplicationContextArrayPtr getAppContextArray() const
+    {
+        LOGD("Entered");
+        return m_appContextArray;
+    }
+
+    void setAppContextArray(ApplicationContextArrayPtr appContextArray)
+    {
+        LOGD("Entered");
+        m_appContextArray = appContextArray;
+    }
+
+    EventApplicationGetAppsContext() :
+        m_appContextArray(new ApplicationContextArray())
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationGetAppsContext> EventApplicationGetAppsContextPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_GET_APPS_CONTEXT_H_
diff --git a/src/Application/EventApplicationGetAppsInfo.h b/src/Application/EventApplicationGetAppsInfo.h
new file mode 100755 (executable)
index 0000000..745cd2b
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_GET_APPS_INFO_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_GET_APPS_INFO_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "ApplicationInformation.h"
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationGetAppsInfo :
+    public WrtDeviceApis::Commons::IEvent<EventApplicationGetAppsInfo>,
+    public DeviceAPI::Common::SecurityAccessor
+{
+private:
+    /* result */
+    ApplicationInformationArrayPtr m_appInfoArray;
+
+public:
+    void addAppInfo(const ApplicationInformationPtr appInfo)
+    {
+        LOGD("Entered");
+        m_appInfoArray->push_back(appInfo);
+    }
+
+    const ApplicationInformationArrayPtr getAppInfoArray() const
+    {
+        LOGD("Entered");
+        return m_appInfoArray;
+    }
+
+    void setAppInfoArray(ApplicationInformationArrayPtr appInfoArray)
+    {
+        LOGD("Entered");
+        m_appInfoArray = appInfoArray;
+    }
+
+    EventApplicationGetAppsInfo() :
+        m_appInfoArray(new ApplicationInformationArray())
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationGetAppsInfo> EventApplicationGetAppsInfoPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_GET_APPS_INFO_H_
diff --git a/src/Application/EventApplicationGetCurrApp.h b/src/Application/EventApplicationGetCurrApp.h
new file mode 100755 (executable)
index 0000000..73410a1
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_GET_CURR_APP_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_GET_CURR_APP_H_
+
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "Application.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationGetCurrApp :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationGetCurrApp>
+{
+private:
+    /* result */
+    ApplicationPtr m_app;
+
+public:
+    void setApp(const ApplicationPtr app)
+    {
+        LOGD("Entered");
+        m_app = app;
+    }
+
+    ApplicationPtr getApp() const
+    {
+        LOGD("Entered");
+        return m_app;
+    }
+
+    EventApplicationGetCurrApp() :
+        m_app(static_cast<m_app*>(NULL))
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationGetCurrApp> EventApplicationGetCurrAppPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_GET_CURR_APP_H_
diff --git a/src/Application/EventApplicationGetRequestedAppControl.h b/src/Application/EventApplicationGetRequestedAppControl.h
new file mode 100755 (executable)
index 0000000..58d0997
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_GET_REQUESTED_APP_CONTROL_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_GET_REQUESTED_APP_CONTROL_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "RequestedApplicationControl.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationGetRequestedAppControl :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationGetRequestedAppControl>
+{
+private:
+    /* result */
+    RequestedApplicationControlPtr   m_reqAppControl;
+
+    std::string             m_encodedBundle;
+
+public:
+    void setRequestedAppControl(RequestedApplicationControlPtr &reqAppControl)
+    {
+        LOGD("Entered");
+        m_reqAppControl = reqAppControl;
+    }
+
+    RequestedApplicationControlPtr getRequestedAppControl() const
+    {
+        LOGD("Entered");
+        return m_reqAppControl;
+    }
+
+    void setEncodedBundle(std::string encodedBundle)
+    {
+        LOGD("Entered");
+        m_encodedBundle = encodedBundle;
+    }
+
+    std::string getEncodedBundle() const
+    {
+        LOGD("Entered");
+        return m_encodedBundle;
+    }
+
+    EventApplicationGetRequestedAppControl() :
+        m_reqAppControl(static_cast<RequestedApplicationControl*>(NULL))
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationGetRequestedAppControl> EventApplicationGetRequestedAppControlPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_GET_REQUESTED_APP_CONTROL_H_
diff --git a/src/Application/EventApplicationKill.h b/src/Application/EventApplicationKill.h
new file mode 100755 (executable)
index 0000000..8dfd1aa
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_KILL_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_KILL_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationKill : public WrtDeviceApis::Commons::IEvent<EventApplicationKill>
+{
+private:
+    /* parameter */
+    std::string m_contextId;
+
+public:
+    void setContextId(std::string contextId)
+    {
+        LOGD("Entered");
+        m_contextId = contextId;
+    }
+
+    std::string getContextId() const
+    {
+        LOGD("Entered");
+        return m_contextId;
+    }
+
+    EventApplicationKill()
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationKill> EventApplicationKillPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_KILL_H_
diff --git a/src/Application/EventApplicationLaunch.h b/src/Application/EventApplicationLaunch.h
new file mode 100755 (executable)
index 0000000..459beee
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_LAUNCH_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_LAUNCH_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationLaunch :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationLaunch>
+{
+private:
+    /* parameter */
+    std::string m_appId;
+
+public:
+    void setAppId(std::string appId)
+    {
+        LOGD("Entered");
+        m_appId = appId;
+    }
+
+    std::string getAppId() const
+    {
+        LOGD("Entered");
+        return m_appId;
+    }
+};
+
+typedef std::shared_ptr<EventApplicationLaunch> EventApplicationLaunchPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_LAUNCH_H_
diff --git a/src/Application/EventApplicationLaunchAppControl.h b/src/Application/EventApplicationLaunchAppControl.h
new file mode 100755 (executable)
index 0000000..5f4498b
--- /dev/null
@@ -0,0 +1,129 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_LAUNCH_APP_CONTROL_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_LAUNCH_APP_CONTROL_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "ApplicationControl.h"
+#include "ApplicationControlData.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationLaunchAppControlReply;
+typedef std::shared_ptr<EventApplicationLaunchAppControlReply> EventApplicationLaunchAppControlReplyPtr;
+
+class EventApplicationLaunchAppControl :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationLaunchAppControl>
+{
+private:
+    /* parameters */
+    ApplicationControlPtr   m_appControl;
+    std::string             m_appId;
+
+    EventApplicationLaunchAppControlReplyPtr   m_eventReply;
+
+public:
+    void setAppControl(ApplicationControlPtr &appControl)
+    {
+        LOGD("Entered");
+        m_appControl = appControl;
+    }
+
+    ApplicationControlPtr getAppControl() const
+    {
+        LOGD("Entered");
+        return m_appControl;
+    }
+
+    void setAppId(std::string appId)
+    {
+        LOGD("Entered");
+        m_appId = appId;
+    }
+
+    std::string getAppId()
+    {
+        LOGD("Entered");
+        return m_appId;
+    }
+
+    void setEventReply(EventApplicationLaunchAppControlReplyPtr &eventReply)
+    {
+        LOGD("Entered");
+        m_eventReply = eventReply;
+    }
+
+    EventApplicationLaunchAppControlReplyPtr getEventReply() const
+    {
+        LOGD("Entered");
+        return m_eventReply;
+    }
+
+    EventApplicationLaunchAppControl() :
+        m_appControl(static_cast<ApplicationControl*>(NULL)),
+        m_eventReply(static_cast<EventApplicationLaunchAppControlReply*>(NULL))
+    {
+        LOGD("Entered");
+    }
+};
+
+typedef std::shared_ptr<EventApplicationLaunchAppControl> EventApplicationLaunchAppControlPtr;
+
+class EventApplicationLaunchAppControlReply :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationLaunchAppControlReply>
+{
+private:
+    ApplicationControlDataArrayPtr m_appControlDataArray;
+
+public:
+    void addAppControlData(std::string &key, std::vector<std::string> &value)
+    {
+        LOGD("Entered");
+        ApplicationControlDataPtr appControlData(new ApplicationControlData());
+        appControlData->setKey(key);
+        appControlData->setValue(value);
+
+        m_appControlDataArray->push_back(appControlData);
+    }
+
+    void setAppControlDataArray(ApplicationControlDataArrayPtr &appControlDataArray)
+    {
+        LOGD("Entered");
+        m_appControlDataArray = appControlDataArray;
+    }
+
+    ApplicationControlDataArrayPtr getAppControlDataArray() const
+    {
+        LOGD("Entered");
+        return m_appControlDataArray;
+    }
+
+    EventApplicationLaunchAppControlReply() :
+        m_appControlDataArray(new ApplicationControlDataArray())
+    {
+        LOGD("Entered");
+    }
+};
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_LAUNCH_APP_CONTROL_H_
diff --git a/src/Application/EventApplicationRemoveAppInfoEventListener.h b/src/Application/EventApplicationRemoveAppInfoEventListener.h
new file mode 100755 (executable)
index 0000000..e25ed3f
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_REMOVE_APP_INFO_EVENT_LISTENER_H_
+#define TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_REMOVE_APP_INFO_EVENT_LISTENER_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+class EventApplicationRemoveAppInfoEventListener :
+        public WrtDeviceApis::Commons::IEvent<EventApplicationRemoveAppInfoEventListener>
+{
+private:
+    /* result */
+    long m_watchId;
+
+public:
+    void setWatchId(long watchId)
+    {
+        LOGD("Entered");
+        m_watchId = watchId;
+    }
+
+    long getWatchId() const
+    {
+        LOGD("Entered");
+        return m_watchId;
+    }
+};
+
+typedef std::shared_ptr<EventApplicationRemoveAppInfoEventListener> EventApplicationRemoveAppInfoEventListenerPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_EVENT_APPLICATION_ADD_APP_INFO_EVENT_LISTENER_H_
diff --git a/src/Application/IApplicationManager.cpp b/src/Application/IApplicationManager.cpp
new file mode 100644 (file)
index 0000000..4866bf7
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "IApplicationManager.h"
+
+namespace DeviceAPI {
+namespace Application{
+
+using namespace WrtDeviceApis::Commons;
+
+IApplicationManager::IApplicationManager() :
+        EventRequestReceiver<EventApplicationLaunch>(ThreadEnum::APPLICATION_THREAD),
+        EventRequestReceiver<EventApplicationKill>(ThreadEnum::APPLICATION_THREAD),
+        EventRequestReceiver<EventApplicationLaunchAppControl>(ThreadEnum::APPLICATION_THREAD),
+        EventRequestReceiver<EventApplicationLaunchAppControlReply>(ThreadEnum::APPLICATION_THREAD),
+        EventRequestReceiver<EventApplicationFindAppControl>(ThreadEnum::APPLICATION_THREAD),
+        EventRequestReceiver<EventApplicationGetAppsContext>(ThreadEnum::APPLICATION_THREAD),
+        EventRequestReceiver<EventApplicationGetAppsInfo>(ThreadEnum::APPLICATION_THREAD),
+        EventRequestReceiver<EventApplicationAddAppInfoEventListener>(ThreadEnum::APPLICATION_THREAD),
+        EventRequestReceiver<EventApplicationRemoveAppInfoEventListener>(ThreadEnum::APPLICATION_THREAD)
+{
+}
+
+IApplicationManager::~IApplicationManager()
+{
+}
+
+} // Application
+} // DeviceAPI
diff --git a/src/Application/IApplicationManager.h b/src/Application/IApplicationManager.h
new file mode 100644 (file)
index 0000000..178b574
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_APPLICATION_IAPPLICATION_MANAGER_H_
+#define TIZENAPIS_API_APPLICATION_IAPPLICATION_MANAGER_H_
+
+#include <memory>
+#include <Commons/ThreadPool.h>
+#include "EventApplicationLaunch.h"
+#include "EventApplicationKill.h"
+#include "EventApplicationLaunchAppControl.h"
+#include "EventApplicationFindAppControl.h"
+#include "EventApplicationGetAppsContext.h"
+#include "EventApplicationGetAppsInfo.h"
+#include "EventApplicationAddAppInfoEventListener.h"
+#include "EventApplicationRemoveAppInfoEventListener.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class IApplicationManager :
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventApplicationLaunch>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventApplicationKill>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventApplicationLaunchAppControl>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventApplicationLaunchAppControlReply>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventApplicationFindAppControl>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventApplicationGetAppsContext>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventApplicationGetAppsInfo>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventApplicationAddAppInfoEventListener>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventApplicationRemoveAppInfoEventListener>
+{
+public:
+    virtual ~IApplicationManager();
+    virtual void launch(const EventApplicationLaunchPtr& event) = 0;
+    virtual void kill(const EventApplicationKillPtr& event) = 0;
+    virtual void launchAppControl(const EventApplicationLaunchAppControlPtr& event) = 0;
+    virtual void findAppControl(const EventApplicationFindAppControlPtr& event) = 0;
+    virtual void getAppsContext(const EventApplicationGetAppsContextPtr& event) = 0;
+    virtual void getAppsInfo(const EventApplicationGetAppsInfoPtr& event) = 0;
+    virtual void addAppInfoEventListener(const EventApplicationAddAppInfoEventListenerPtr& event) = 0;
+    virtual void removeAppInfoEventListener(const EventApplicationRemoveAppInfoEventListenerPtr& event) = 0;
+
+protected:
+    IApplicationManager();
+
+    virtual void OnRequestReceived(const EventApplicationLaunchPtr& event) = 0;
+    virtual void OnRequestReceived(const EventApplicationKillPtr& event) = 0;
+    virtual void OnRequestReceived(const EventApplicationLaunchAppControlPtr& event) = 0;
+    virtual void OnRequestReceived(const EventApplicationLaunchAppControlReplyPtr& event) = 0;
+    virtual void OnRequestReceived(const EventApplicationFindAppControlPtr& event) = 0;
+    virtual void OnRequestReceived(const EventApplicationGetAppsContextPtr& event) = 0;
+    virtual void OnRequestReceived(const EventApplicationGetAppsInfoPtr& event) = 0;
+    virtual void OnRequestReceived(const EventApplicationAddAppInfoEventListenerPtr& event) = 0;
+    virtual void OnRequestReceived(const EventApplicationRemoveAppInfoEventListenerPtr& event) = 0;
+ };
+
+typedef std::shared_ptr<IApplicationManager> IApplicationManagerPtr;
+
+} // Application
+} // DeviceAPI
+
+#endif // TIZENAPIS_API_APPLICATION_IAPPLICATION_MANAGER_H_
diff --git a/src/Application/JSApplication.cpp b/src/Application/JSApplication.cpp
new file mode 100755 (executable)
index 0000000..0d8f82b
--- /dev/null
@@ -0,0 +1,240 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <memory>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Converter.h>
+#include <Commons/Exception.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+#include <JSWebAPIErrorFactory.h>
+
+#include "ApplicationController.h"
+#include "ApplicationConverter.h"
+#include "plugin_config.h"
+#include "JSApplication.h"
+
+#include <TimeTracer.h>
+#include <Export.h>
+#include <Logger.h>
+
+#include <plugins-ipc-message/ipc_message_support.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace DeviceAPI::Common;
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+JSClassRef JSApplication::m_classRef = NULL;
+
+JSClassDefinition JSApplication::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_INTERFACE_APPLICATION,
+    0,
+    NULL,
+    m_function,
+    initialize,
+    finalize,
+    NULL,     //HasProperty,
+    NULL,   //GetProperty,
+    NULL,     //SetProperty,
+    NULL,     //DeleteProperty,
+    NULL,     //GetPropertyNames,
+    NULL,     //CallAsFunction,
+    NULL,     //CallAsConstructor,
+    NULL,
+    NULL,     //ConvertToType
+};
+
+JSStaticFunction JSApplication::m_function[] = {
+        { APPLICATION_FUNCTION_API_EXIT,
+                JSApplication::exit, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_HIDE,
+                JSApplication::hide, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_GET_REQUESTED_APP_CONTROL,
+                JSApplication::getRequestedAppControl, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+
+JSClassRef DLL_EXPORT JSApplication::getClassRef() {
+    LOGD("Entered");
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+void JSApplication::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSApplication::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationPriv* priv = static_cast<JSApplicationPriv*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    LOGD("Deleting JSApplication object");
+    delete priv;
+}
+
+JSValueRef JSApplication::makeObject(JSContextRef ctx,
+        const ApplicationPtr value,
+        const SecurityAccessor *accessor)
+{
+    LOGD("Entered");
+    if (value.get() == NULL) {
+        throw TypeMismatchException("Private object is NULL.");
+    }
+
+    JSApplicationPriv* priv = new JSApplicationPriv(ctx, value);
+    JSObjectRef target = JSObjectMake(ctx, getClassRef(), priv);
+
+    ApplicationConverter converter(ctx, accessor);
+    JSUtil::setProperty(ctx,
+            target,
+            TIZEN_APPLICATION_APP_INFO,
+            converter.toJSValueRefFromApplicationInformation(value->getAppInfo()),
+            kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete);
+    JSUtil::setProperty(ctx,
+            target,
+            TIZEN_APPLICATION_APP_CONTEXT_ID,
+            converter.toJSValueRef(value->getContextId()),
+            kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete);
+    return target;
+}
+
+JSValueRef JSApplication::exit(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        IPCMessageSupport::sendAsyncMessageToUiProcess(
+                IPCMessageSupport::TIZEN_EXIT, NULL, NULL, NULL);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSApplication::hide(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        IPCMessageSupport::sendAsyncMessageToUiProcess(
+                IPCMessageSupport::TIZEN_HIDE, NULL, NULL, NULL);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplication::getRequestedAppControl(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    JSApplicationPriv *priv = static_cast<JSApplicationPriv*>(JSObjectGetPrivate(thisObject));
+
+
+    try {
+        if (!priv) {
+            throw TypeMismatchException("No private object.");
+        }
+
+        ApplicationConverterFactory::ConverterType converter
+        = ApplicationConverterFactory::getConverter(context);
+        EventApplicationGetRequestedAppControlPtr event(
+                new EventApplicationGetRequestedAppControl());
+        ApplicationPtr app = priv->getObject();
+
+        JSObjectRef windowObject = JSContextGetGlobalObject(context);
+        JSValueRef encodedBundle = JSObjectGetProperty(context,
+                                                    windowObject,
+                                                    ScopedJSStringRef(
+                                                            JSStringCreateWithUTF8CString(
+                                                                    "__bundle")).get(),
+                                                                    exception);
+        if (JSValueIsUndefined(context, encodedBundle) ||
+                JSValueIsNull(context, encodedBundle)) {
+            return JSValueMakeNull(context);
+        }
+
+        event->setEncodedBundle(converter->toString(encodedBundle));
+        app->getRequestedAppControl(event);
+
+        if (event->getExceptionCode() ==
+                WrtDeviceApis::Commons::ExceptionCodes::NotFoundException) {
+            throw NotFoundException("No application control request found.");
+        } else if (event->getExceptionCode() ==
+                WrtDeviceApis::Commons::ExceptionCodes::UnknownException) {
+            return JSValueMakeNull(context);
+        }
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return converter->toJSValueRef(event->getRequestedAppControl());
+
+     } catch (const BasePlatformException &err) {
+         return JSWebAPIErrorFactory::postException(context, exception, err);
+     } catch (...) {
+         DeviceAPI::Common::UnknownException err(""
+                 "Unknown Error in ApplicationManager.getAppSharedURI().");
+         return JSWebAPIErrorFactory::postException(context, exception, err);
+     }
+}
+
+}
+}
diff --git a/src/Application/JSApplication.h b/src/Application/JSApplication.h
new file mode 100644 (file)
index 0000000..7617c6b
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_TIZEN_JS_APPLICATION_H_
+#define TIZENAPIS_TIZEN_JS_APPLICATION_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <memory>
+#include <Security.h>
+#include "Application.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+#define TIZEN_INTERFACE_APPLICATION "Application"
+
+#define TIZEN_APPLICATION_APP_INFO "appInfo"
+#define TIZEN_APPLICATION_APP_CONTEXT_ID "contextId"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<ApplicationPtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> JSApplicationPriv;
+
+class JSApplication {
+public:
+    /*
+    * This initializes this JS class in the JS Engine.
+    */
+    static JSClassRef getClassRef();
+
+    static JSValueRef makeObject(JSContextRef ctx,
+            const ApplicationPtr value,
+            const DeviceAPI::Common::SecurityAccessor *accessor);
+
+
+    /**
+     * hide the application based on application context.
+     */
+    static JSValueRef hide(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * exit current application
+     */
+    static JSValueRef exit(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * get request application control
+     */
+    static JSValueRef getRequestedAppControl(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+   /**
+    * The callback invoked when an object is first created.
+    */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+   /**
+    * The callback invoked when an object is finalized.
+    */
+    static void finalize(JSObjectRef object);
+
+   /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+   /**
+    * This structure describes a statically declared function property.
+    */
+    static JSStaticFunction m_functions[];
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_classRef;
+
+};
+
+}
+}
+#endif  //TIZENAPIS_TIZEN_JS_APPLICATION_H_
diff --git a/src/Application/JSApplicationCert.cpp b/src/Application/JSApplicationCert.cpp
new file mode 100644 (file)
index 0000000..db6db4c
--- /dev/null
@@ -0,0 +1,136 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <memory>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Converter.h>
+
+//#include <Commons/Exception.h>
+#include <JSWebAPIErrorFactory.h>
+
+#include "ApplicationCert.h"
+#include "JSApplicationCert.h"
+#include <Export.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace WrtDeviceApis;
+using namespace DeviceAPI::Common;
+
+
+JSClassRef JSApplicationCert::m_classRef = NULL;
+
+JSClassDefinition JSApplicationCert::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_INTERFACE_APPLICATION_CERT,
+    0,
+    m_property,
+    0,
+    initialize,
+    finalize,
+    NULL,     //HasProperty,
+    NULL,   //GetProperty,
+    NULL,     //SetProperty,
+    NULL,     //DeleteProperty,
+    NULL,     //GetPropertyNames,
+    NULL,     //CallAsFunction,
+    NULL,     //CallAsConstructor,
+    NULL,
+    NULL,     //ConvertToType
+};
+
+JSStaticValue JSApplicationCert::m_property[] = {
+    { TIZEN_APPLICATION_CERT_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_CERT_VALUE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef DLL_EXPORT JSApplicationCert::getClassRef() {
+    LOGD("Entered");
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+
+void JSApplicationCert::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSApplicationCert::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationCertPriv* priv = static_cast<JSApplicationCertPriv*>(
+            JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+bool JSApplicationCert::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+ApplicationCertPtr JSApplicationCert::getPrivData(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationCertPriv *priv = static_cast<JSApplicationCertPriv*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    ApplicationCertPtr result = priv->getObject();
+    if (!result) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return result;
+}
+
+
+JSValueRef JSApplicationCert::getProperty(JSContextRef context,
+    JSObjectRef object,
+    JSStringRef propertyName,
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CommonsJavaScript::Converter converter(context);
+        ApplicationCertPtr privateData = getPrivData(object);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CERT_TYPE)) {
+            return converter.toJSValueRef(privateData->getType());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CERT_VALUE)) {
+            return converter.toJSValueRef(privateData->getValue());
+        }
+    } catch (...) {
+        LOGE("Exception occured while get property");
+        return JSValueMakeUndefined(context);
+    }
+
+    /* do not return undefined object to find method */
+    return NULL;
+}
+
+}
+}
diff --git a/src/Application/JSApplicationCert.h b/src/Application/JSApplicationCert.h
new file mode 100755 (executable)
index 0000000..4d1edf2
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_TIZEN_JS_APPLICATION_CERT_H_
+#define TIZENAPIS_TIZEN_JS_APPLICATION_CERT_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+#define TIZEN_INTERFACE_APPLICATION_CERT "ApplicationCert"
+
+#define TIZEN_APPLICATION_CERT_TYPE     "type"
+#define TIZEN_APPLICATION_CERT_VALUE    "value"
+
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<ApplicationCertPtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> JSApplicationCertPriv;
+
+class JSApplicationCert {
+public:
+    /*
+    * This initializes this JS class in the JS Engine.
+    */
+    static JSClassRef getClassRef();
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+private:
+   /**
+    * The callback invoked when an object is first created.
+    */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+   /**
+    * The callback invoked when an object is finalized.
+    */
+    static void finalize(JSObjectRef object);
+
+   /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_classRef;
+
+    static ApplicationCertPtr getPrivData(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception);
+
+};
+
+}
+}
+#endif
diff --git a/src/Application/JSApplicationContext.cpp b/src/Application/JSApplicationContext.cpp
new file mode 100644 (file)
index 0000000..1e8ef4b
--- /dev/null
@@ -0,0 +1,176 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <memory>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Converter.h>
+#include "ApplicationContext.h"
+#include <JSWebAPIErrorFactory.h>
+#include "JSApplicationContext.h"
+#include <Export.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace WrtDeviceApis;
+using namespace DeviceAPI::Common;
+
+JSClassRef JSApplicationContext::m_classRef = NULL;
+
+JSClassDefinition JSApplicationContext::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_INTERFACE_APPLICATION_CONTEXT,
+    0,
+    m_property,
+    0,
+    initialize,
+    finalize,
+    NULL,     //HasProperty,
+    NULL,   //GetProperty,
+    NULL,    //SetProperty,
+    NULL,     //DeleteProperty,
+    NULL,     //GetPropertyNames,
+    NULL,     //CallAsFunction,
+    NULL,     //CallAsConstructor,
+    NULL,
+    NULL,     //ConvertToType
+};
+
+JSStaticValue JSApplicationContext::m_property[] = {
+    { TIZEN_APPLICATION_CONTEXT_ID, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_CONTEXT_APP_ID, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef DLL_EXPORT JSApplicationContext::getClassRef() {
+    LOGD("Entered");
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+JSValueRef JSApplicationContext::createJSObject(JSContextRef context,
+    const std::string &appId,
+    const std::string &contextId)
+{
+    LOGD("Entered");
+    ApplicationContextPtr privateData = ApplicationContextPtr(new ApplicationContext());
+    privateData->setAppId(appId);
+    privateData->setContextId(contextId);
+
+    JSApplicationContextPriv *priv = new JSApplicationContextPriv(context, privateData);
+
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    return jsValueRef;
+}
+
+void JSApplicationContext::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSApplicationContext::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationContextPriv* priv = static_cast<JSApplicationContextPriv*>(
+            JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+bool JSApplicationContext::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+ApplicationContextPtr JSApplicationContext::getPrivData(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationContextPriv *priv = static_cast<JSApplicationContextPriv*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+
+    ApplicationContextPtr result = priv->getObject();
+    if (!result) {
+        throw TypeMismatchException("Private object is null");
+    }
+
+    return result;
+}
+
+ApplicationContextPtr JSApplicationContext::getApplicationContext(JSContextRef context,
+        JSValueRef value)
+{
+    LOGD("Entered");
+    if (!isObjectOfClass(context, value)) {
+        throw TypeMismatchException("is not a object class");
+    }
+
+    JSObjectRef object = JSValueToObject(context, value, NULL);
+    if (!object) {
+        throw TypeMismatchException("Private object is null");
+    }
+
+    JSApplicationContextPriv *priv = static_cast<JSApplicationContextPriv*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+
+    return priv->getObject();
+}
+
+
+JSValueRef JSApplicationContext::getProperty(JSContextRef context,
+    JSObjectRef object,
+    JSStringRef propertyName,
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CommonsJavaScript::Converter converter(context);
+        ApplicationContextPtr privateData = getPrivData(context, object);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CONTEXT_APP_ID)) {
+            return converter.toJSValueRef(privateData->getAppId());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CONTEXT_ID)) {
+            return converter.toJSValueRef(privateData->getContextId());
+        }
+    } catch (...) {
+        LOGE("Exception occured while get property");
+        return JSValueMakeUndefined(context);
+    }
+
+    /* do not return undefined object to find method */
+    return NULL;
+}
+
+
+}
+}
diff --git a/src/Application/JSApplicationContext.h b/src/Application/JSApplicationContext.h
new file mode 100755 (executable)
index 0000000..c5d0701
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_TIZEN_JS_APPLICATION_CONTEXT_H_
+#define TIZENAPIS_TIZEN_JS_APPLICATION_CONTEXT_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <memory>
+#include "ApplicationContext.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+#define TIZEN_INTERFACE_APPLICATION_CONTEXT "ApplicationContext"
+
+#define TIZEN_APPLICATION_CONTEXT_ID "id"
+#define TIZEN_APPLICATION_CONTEXT_APP_ID "appId"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<ApplicationContextPtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> JSApplicationContextPriv;
+
+class JSApplicationContext {
+public:
+    /*
+    * This initializes this JS class in the JS Engine.
+    */
+    static JSClassRef getClassRef();
+
+    static JSValueRef createJSObject(JSContextRef context,
+            const std::string &appId,
+            const std::string &contextId);
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+    static ApplicationContextPtr getApplicationContext(JSContextRef context,
+            JSValueRef value);
+
+private:
+   /**
+    * The callback invoked when an object is first created.
+    */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+   /**
+    * The callback invoked when an object is finalized.
+    */
+    static void finalize(JSObjectRef object);
+
+   /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+   /**
+    * This structure describes a statically declared function property.
+    */
+    static JSStaticFunction m_functions[];
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_classRef;
+
+    static ApplicationContextPtr getPrivData(JSContextRef context, JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception);
+
+};
+
+}
+}
+#endif
diff --git a/src/Application/JSApplicationControl.cpp b/src/Application/JSApplicationControl.cpp
new file mode 100755 (executable)
index 0000000..1ad1050
--- /dev/null
@@ -0,0 +1,334 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <memory>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/JSDOMExceptionFactory.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <Export.h>
+
+//#include <Commons/Exception.h>
+#include <JSWebAPIErrorFactory.h>
+
+#include "plugin_config.h"
+
+#include "ApplicationConverter.h"
+#include "ApplicationUtil.h"
+#include "JSApplicationControl.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Application {
+
+JSClassRef JSApplicationControl::m_jsClassRef = NULL;
+
+JSClassDefinition JSApplicationControl::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_INTERFACE_APPLICATION_CONTROL,
+    0,
+    m_property,
+    NULL,
+    initialize,
+    finalize,
+    NULL,     //HasProperty,
+    NULL,
+    NULL,     //SetProperty,
+    NULL,     //DeleteProperty,
+    NULL,     //GetPropertyNames,
+    NULL,     //CallAsFunction,
+    NULL,     //CallAsConstructor,
+    NULL,
+    NULL,     //ConvertToType
+};
+
+JSStaticValue JSApplicationControl::m_property[] = {
+    { TIZEN_APPLICATION_CONTROL_OPERATION, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_APPLICATION_CONTROL_URI, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_APPLICATION_CONTROL_MIME, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_APPLICATION_CONTROL_CATEGORY, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_APPLICATION_CONTROL_DATA, getProperty, setProperty, kJSPropertyAttributeNone },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSApplicationControl::getClassInfo()
+{
+    LOGD("Entered");
+    return &m_classInfo;
+}
+
+const JSClassRef DLL_EXPORT JSApplicationControl::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+
+    return m_jsClassRef;
+}
+
+JSObjectRef JSApplicationControl::createJSObject(JSContextRef context,
+        const ApplicationControlPtr &appsvc,
+        JSValueRef jsValueData)
+{
+    LOGD("Entered");
+    JSApplicationControlPriv *priv = new JSApplicationControlPriv(context, appsvc);
+    if (!priv) {
+        LOGE("Failed to alloc memory");
+        return NULL;
+    }
+
+    JSObjectRef jsObjectRef = JSObjectMake(context,
+            getClassRef(),
+            static_cast<void*>(priv));
+    if (NULL == jsObjectRef)
+    {
+        LOGE("object creation error");
+        return NULL;
+    }
+
+    const ScopedJSStringRef jsStrData(JSStringCreateWithUTF8CString(
+            TIZEN_APPLICATION_CONTROL_DATA_INTERNAL));
+
+    JSObjectSetProperty(context, jsObjectRef, jsStrData.get(), jsValueData,
+            kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+
+    return jsObjectRef;
+}
+
+
+ApplicationControlPtr DLL_EXPORT JSApplicationControl::getApplicationControl(
+        JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    if (!isObjectOfClass(context, value)) {
+        throw TypeMismatchException("is not a object class");
+    }
+
+    JSObjectRef object = JSValueToObject(context, value, NULL);
+    if (!object) {
+        throw TypeMismatchException("Private object is null");
+    }
+
+    JSApplicationControlPriv *priv = static_cast<JSApplicationControlPriv*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return priv->getObject();
+}
+
+void JSApplicationControl::initialize(JSContextRef context,JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSApplicationControl::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationControlPriv* priv = static_cast<JSApplicationControlPriv*>(
+            JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+JSObjectRef DLL_EXPORT JSApplicationControl::constructor(JSContextRef context,
+    JSObjectRef constructor,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    ApplicationControlPtr appsvc = ApplicationControlPtr(new ApplicationControl());
+
+    JSValueRef jsValueData = NULL;
+
+    try {
+        appsvc->setOperation(validator.toString(0));
+        appsvc->setUri(validator.toString(1, true, ""));
+        appsvc->setMime(validator.toString(2, true, ""));
+        appsvc->setCategory(validator.toString(3, true, ""));
+
+        JSObjectRef dataArray = validator.toArrayObject(4, true);
+        if (dataArray) {
+            ApplicationConverterFactory::ConverterType converter =
+                    ApplicationConverterFactory::getConverter(context);
+            std::vector<ApplicationControlDataPtr> appControlDataArray =
+                    converter->toApplicationControlDataArray(dataArray);
+            appsvc->setAppControlDataArray(appControlDataArray);
+            jsValueData = dataArray;
+        }
+    } catch (const BasePlatformException& err) {
+        LOGD("Exception occured while creating constructor : %s", err.getMessage().c_str());
+    } catch (const ConversionException& err) {
+        LOGD("Exception occured while creating constructor : %s", err.GetMessage().c_str());
+    }
+
+    if (jsValueData == NULL)
+    {
+        jsValueData = JSCreateArrayObject(context, 0, NULL);
+    }
+
+    JSObjectRef obj = createJSObject(context, appsvc, jsValueData);
+    if (obj == NULL)
+        return NULL;
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, obj, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    return obj;
+}
+
+
+bool JSApplicationControl::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+ApplicationControlPtr JSApplicationControl::getPrivData(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationControlPriv *priv = static_cast<JSApplicationControlPriv*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    ApplicationControlPtr result = priv->getObject();
+    if (!result) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return result;
+}
+
+
+JSValueRef JSApplicationControl::getProperty(JSContextRef context, JSObjectRef object,
+        JSStringRef propertyName, JSValueRef* exception)
+{
+    LOGD("Entered");
+    JSApplicationControlPriv *priv = static_cast<JSApplicationControlPriv*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        DeviceAPI::Common::TypeMismatchException err("TypeMismatchException occured");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    try {
+        ApplicationControlPtr appsvc = priv->getObject();
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName,
+                TIZEN_APPLICATION_CONTROL_OPERATION)) {
+            return converter->toJSValueRef(appsvc->getOperation());
+        } else if (JSStringIsEqualToUTF8CString(propertyName,
+                TIZEN_APPLICATION_CONTROL_URI)) {
+            std::string uri = appsvc->getUri();
+            if (uri.empty()) {
+                return JSValueMakeNull(context);
+            } else {
+                return converter->toJSValueRef(uri);
+            }
+        } else if (JSStringIsEqualToUTF8CString(propertyName,
+                TIZEN_APPLICATION_CONTROL_MIME)) {
+            std::string mime = appsvc->getMime();
+            if (mime.empty()) {
+                return JSValueMakeNull(context);
+            } else {
+                return converter->toJSValueRef(mime);
+            }
+        } else if (JSStringIsEqualToUTF8CString(propertyName,
+                TIZEN_APPLICATION_CONTROL_CATEGORY)) {
+            std::string category = appsvc->getCategory();
+            if (category.empty()) {
+                return JSValueMakeNull(context);
+            } else {
+                return converter->toJSValueRef(category);
+            }
+        } else if (JSStringIsEqualToUTF8CString(propertyName,
+                TIZEN_APPLICATION_CONTROL_DATA)) {
+            const ScopedJSStringRef jsStrData(JSStringCreateWithUTF8CString(
+                    TIZEN_APPLICATION_CONTROL_DATA_INTERNAL));
+            return JSObjectGetProperty(context, object, jsStrData.get(), NULL);
+        }
+
+    } catch (...) {
+        LOGE("Exception occured while get property");
+        return JSValueMakeUndefined(context);
+    }
+
+    /* do not return undefined object to find method */
+    return NULL;
+}
+
+bool JSApplicationControl::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ApplicationControlPtr privateData = getPrivData(context, object);
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CONTROL_OPERATION)) {
+            privateData->setOperation(converter->toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CONTROL_URI)) {
+            privateData->setUri(converter->toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CONTROL_MIME)) {
+            privateData->setMime(converter->toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CONTROL_CATEGORY)) {
+            privateData->setCategory(converter->toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CONTROL_DATA)) {
+            if (!JSIsArrayValue(context, value))
+                return true;
+
+            const ScopedJSStringRef jsStrData(
+                    JSStringCreateWithUTF8CString(TIZEN_APPLICATION_CONTROL_DATA_INTERNAL));
+            JSObjectSetProperty(context, object, jsStrData.get(), value,
+                    kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+
+            return true;
+        }
+
+    } catch (...) {
+        LOGE("Exception occured while set property");
+    }
+
+    return false;
+}
+
+}
+}
diff --git a/src/Application/JSApplicationControl.h b/src/Application/JSApplicationControl.h
new file mode 100755 (executable)
index 0000000..6b3b483
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_TIZEN_JS_APPLICATION_CONTROL_H_
+#define TIZENAPIS_TIZEN_JS_APPLICATION_CONTROL_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "ApplicationControl.h"
+#include "JSApplicationControlData.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+#define TIZEN_INTERFACE_APPLICATION_CONTROL "ApplicationControl"
+
+#define TIZEN_APPLICATION_CONTROL_OPERATION "operation"
+#define TIZEN_APPLICATION_CONTROL_URI "uri"
+#define TIZEN_APPLICATION_CONTROL_MIME "mime"
+#define TIZEN_APPLICATION_CONTROL_CATEGORY "category"
+#define TIZEN_APPLICATION_CONTROL_DATA "data"
+#define TIZEN_APPLICATION_CONTROL_DATA_INTERNAL "__tizen_data"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObjectT<ApplicationControlPtr>::Type JSApplicationControlPriv;
+
+class JSApplicationControl {
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    /**
+      * create an JSObject for callback function(onAnswerReceived).
+      */
+    static JSObjectRef createJSObject(JSContextRef context,
+               const ApplicationControlPtr &appsvc,
+               JSValueRef jsValueData);
+
+    /**
+     * The Constructor of ApplicationControl
+     */
+    static JSObjectRef constructor(JSContextRef ctx,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+    static ApplicationControlPtr getApplicationControl(JSContextRef context,
+            JSValueRef value);
+    /**
+      * return private data
+      */
+    //static ApplicationControlPtr getPrivateData(JSObjectRef object);
+
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+   /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static ApplicationControlPtr getPrivData(JSContextRef context, JSObjectRef object);
+
+  /**
+     * The callback invoked when getting a property's value.
+     */
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+  /**
+     * The callback invoked when setting a property's value.
+     */
+
+    static bool setProperty(JSContextRef context,
+          JSObjectRef object,
+          JSStringRef propertyName,
+          JSValueRef value,
+          JSValueRef* exception);
+
+  /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+  /**
+     * This structure describes a statically declared value property.
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //
+} //TizenApis
+
+#endif
diff --git a/src/Application/JSApplicationControlData.cpp b/src/Application/JSApplicationControlData.cpp
new file mode 100755 (executable)
index 0000000..0f504c1
--- /dev/null
@@ -0,0 +1,276 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <memory>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/JSDOMExceptionFactory.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+
+#include <ArgumentValidator.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include <Export.h>
+#include "JSApplicationControlData.h"
+#include "ApplicationConverter.h"
+#include "ApplicationUtil.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Application {
+
+JSClassRef JSApplicationControlData::m_classRef = NULL;
+
+JSClassDefinition JSApplicationControlData::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_INTERFACE_APPLICATION_CONTROL_DATA,
+    NULL,
+    m_property,
+    m_functions,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //getPropertyNames,
+    NULL,
+    NULL,
+    NULL,
+    NULL, //ConvertToType,
+};
+
+JSStaticValue JSApplicationControlData::m_property[] = {
+    { TIZEN_APPLICATION_CONTROL_DATA_KEY, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_APPLICATION_CONTROL_DATA_VALUE, getProperty, setProperty, kJSPropertyAttributeNone },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSApplicationControlData::m_functions[] =
+{
+    { 0, 0, 0 }
+};
+
+JSClassRef DLL_EXPORT JSApplicationControlData::getClassRef() {
+    LOGD("Entered");
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+JSObjectRef JSApplicationControlData::createJSObject(JSContextRef context,
+        const ApplicationControlDataPtr &appdata,
+        JSValueRef jsValueValue)
+{
+    LOGD("Entered");
+    JSApplicationControlDataPriv *priv = new JSApplicationControlDataPriv(context, appdata);
+
+    if (!priv) {
+        LOGE("Failed to alloc memory");
+        return NULL;
+    }
+
+    JSObjectRef jsObjectRef = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (NULL == jsObjectRef)
+    {
+        LOGE("object creation error");
+        return NULL;
+    }
+
+    const ScopedJSStringRef jsStrValue(JSStringCreateWithUTF8CString(
+            TIZEN_APPLICATION_CONTROL_DATA_VALUE_INTERNAL));
+
+    JSObjectSetProperty(context, jsObjectRef, jsStrValue.get(), jsValueValue,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+
+    return jsObjectRef;
+}
+
+JSObjectRef DLL_EXPORT JSApplicationControlData::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    ApplicationControlDataPtr appdata(new ApplicationControlData());
+
+    JSValueRef jsValueValue = NULL;
+
+    try {
+        appdata->setKey(validator.toString(0));
+        JSObjectRef jsObjectArray = validator.toArrayObject(1);
+        if (jsObjectArray) {
+            ApplicationConverterFactory::ConverterType converter =
+                    ApplicationConverterFactory::getConverter(context);
+            std::vector<std::string> valueArray = converter->toVectorOfStrings(jsObjectArray);
+            appdata->setValue(valueArray);
+            jsValueValue = jsObjectArray;
+        }
+
+    } catch (BasePlatformException &err) {
+        LOGE("Exception occured while creating constructor : %s", err.getMessage().c_str());
+    } catch (const ConversionException& err) {
+        LOGD("Exception occured while creating constructor : %s", err.GetMessage().c_str());
+    }
+
+    if (jsValueValue == NULL)
+    {
+        jsValueValue = JSCreateArrayObject(context, 0, NULL);
+    }
+
+    JSObjectRef obj = createJSObject(context, appdata, jsValueValue);
+    if (obj == NULL)
+        return NULL;
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, obj, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    return obj;
+}
+
+void JSApplicationControlData::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSApplicationControlData::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationControlDataPriv* priv = static_cast<JSApplicationControlDataPriv*>(
+            JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+bool JSApplicationControlData::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+ApplicationControlDataPtr JSApplicationControlData::getPrivData(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationControlDataPriv *priv = static_cast<JSApplicationControlDataPriv*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    ApplicationControlDataPtr result = priv->getObject();
+    if (!result) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return result;
+}
+
+ApplicationControlDataPtr JSApplicationControlData::getApplicationControlData(
+        JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    if (!isObjectOfClass(context, value)) {
+        throw TypeMismatchException("is not a object class");
+    }
+    JSObjectRef object = JSValueToObject(context, value, NULL);
+    if (!object) {
+        throw TypeMismatchException("Fail to get object");
+    }
+    JSApplicationControlDataPriv *priv = static_cast<JSApplicationControlDataPriv*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return priv->getObject();
+}
+
+
+JSValueRef JSApplicationControlData::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        WrtDeviceApis::CommonsJavaScript::Converter converter(context);
+        ApplicationControlDataPtr privateData = getPrivData(object);
+
+        if (JSStringIsEqualToUTF8CString(
+                propertyName, TIZEN_APPLICATION_CONTROL_DATA_KEY)) {
+            return converter.toJSValueRef(privateData->getKey());
+        } else if (JSStringIsEqualToUTF8CString(
+                propertyName, TIZEN_APPLICATION_CONTROL_DATA_VALUE)) {
+            const ScopedJSStringRef jsStrData(JSStringCreateWithUTF8CString(
+                            TIZEN_APPLICATION_CONTROL_DATA_VALUE_INTERNAL));
+            return JSObjectGetProperty(context, object, jsStrData.get(), NULL);
+        }
+    } catch (...) {
+        LOGE("Exception occured while get property");
+        return JSValueMakeUndefined(context);
+    }
+
+    /* do not return undefined object to find method */
+    return NULL;
+}
+
+
+bool JSApplicationControlData::setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+    const JSValueRef arguments[1] = {value};
+    ArgumentValidator validator(context, 1, arguments);
+
+    try {
+        ApplicationControlDataPtr privateData = getPrivData(object);
+
+        if (JSStringIsEqualToUTF8CString(propertyName,
+                TIZEN_APPLICATION_CONTROL_DATA_KEY)) {
+            privateData->setKey(JSUtil::JSValueToString(context, value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName,
+                TIZEN_APPLICATION_CONTROL_DATA_VALUE)) {
+            if (!JSIsArrayValue(context, value))
+                return true;
+
+            const ScopedJSStringRef jsStrData(JSStringCreateWithUTF8CString(
+                    TIZEN_APPLICATION_CONTROL_DATA_VALUE_INTERNAL));
+            JSObjectSetProperty(context, object, jsStrData.get(), value,
+                    kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+
+            return true;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("Setting property is failed %s", err.getMessage().c_str());
+    }
+
+    return false;
+}
+
+}
+}
diff --git a/src/Application/JSApplicationControlData.h b/src/Application/JSApplicationControlData.h
new file mode 100755 (executable)
index 0000000..e81379d
--- /dev/null
@@ -0,0 +1,108 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_TIZEN_JS_APPLICATION_CONTROL_DATA_H_
+#define TIZENAPIS_TIZEN_JS_APPLICATION_CONTROL_DATA_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <memory>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <Commons/IEvent.h>
+#include "ApplicationControlData.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+#define TIZEN_INTERFACE_APPLICATION_CONTROL_DATA "ApplicationControlData"
+
+#define TIZEN_APPLICATION_CONTROL_DATA_KEY "key"
+#define TIZEN_APPLICATION_CONTROL_DATA_VALUE "value"
+#define TIZEN_APPLICATION_CONTROL_DATA_VALUE_INTERNAL "__tizen_value"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<ApplicationControlDataPtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> JSApplicationControlDataPriv;
+
+class JSApplicationControlData {
+public:
+    /*
+    * This initializes this JS class in the JS Engine.
+    */
+    static JSClassRef getClassRef();
+
+    static JSObjectRef createJSObject(JSContextRef context,
+            const ApplicationControlDataPtr &appdata,
+            JSValueRef jsValueValue);
+
+    static JSObjectRef constructor(JSContextRef ctx,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+    static ApplicationControlDataPtr
+        getApplicationControlData(JSContextRef context, JSValueRef value);
+
+private:
+   /**
+    * The callback invoked when an object is first created.
+    */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+   /**
+    * The callback invoked when an object is finalized.
+    */
+    static void finalize(JSObjectRef object);
+
+   /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+   /**
+    * This structure describes a statically declared function property.
+    */
+    static JSStaticFunction m_functions[];
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_classRef;
+
+    static ApplicationControlDataPtr getPrivData(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+}
+}
+
+#endif
diff --git a/src/Application/JSApplicationEventCallbackManager.cpp b/src/Application/JSApplicationEventCallbackManager.cpp
new file mode 100755 (executable)
index 0000000..abacebd
--- /dev/null
@@ -0,0 +1,270 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSApplicationEventCallbackManager.h"
+#include <WebKitProxy.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+JSApplicationEventCallbackManagerPtr JSApplicationEventCallbackManager::createObject(JSContextRef context)
+{
+    return JSApplicationEventCallbackManagerPtr( new JSApplicationEventCallbackManager(context) );
+}
+
+JSApplicationEventCallbackManager::JSApplicationEventCallbackManager(JSContextRef context,
+        JSObjectRef onInstalled,
+        JSObjectRef onUpdated,
+        JSObjectRef onUninstalled,
+        JSObjectRef onError ) :
+        m_onInstalled(NULL),
+        m_onUpdated(NULL),
+        m_onUninstalled(NULL),
+        m_onError(NULL),
+        m_context(context),
+        m_object(NULL)
+{
+    LOGD("Entered");
+    setOnInstalled(onInstalled);
+    setOnUpdated(onUpdated);
+    setOnUninstalled(onUninstalled);
+    setOnError(onError);
+}
+
+JSApplicationEventCallbackManager::~JSApplicationEventCallbackManager()
+{
+    LOGD("Entered");
+    if (m_onInstalled)
+    {
+        JSValueUnprotect(m_context, m_onInstalled);
+    }
+
+    if (m_onUpdated)
+    {
+        JSValueUnprotect(m_context, m_onUpdated);
+    }
+
+    if (m_onUninstalled)
+    {
+        JSValueUnprotect(m_context, m_onUninstalled);
+    }
+
+    if (m_onError)
+    {
+        JSValueUnprotect(m_context, m_onError);
+    }
+}
+
+void JSApplicationEventCallbackManager::setOnInstalled( JSValueRef onInstalled )
+{
+    LOGD("Entered");
+    if (onInstalled)
+    {
+        if (m_onInstalled != NULL)
+        {
+            JSValueUnprotect(m_context, m_onInstalled);
+        }
+
+        m_onInstalled = JSValueToObject( m_context, onInstalled, NULL );
+
+        if (m_onInstalled != NULL)
+        {
+            JSValueProtect(m_context, m_onInstalled);
+        }
+    }
+}
+
+JSValueRef JSApplicationEventCallbackManager::getOnInstalled() const
+{
+    LOGD("Entered");
+    return m_onInstalled;
+}
+
+void JSApplicationEventCallbackManager::setOnUpdated( JSValueRef onUpdated )
+{
+    LOGD("Entered");
+    if (onUpdated)
+    {
+        if (m_onUpdated != NULL)
+        {
+            JSValueUnprotect(m_context, m_onUpdated);
+        }
+
+        m_onUpdated = JSValueToObject( m_context, onUpdated, NULL );
+
+        if (m_onUpdated != NULL)
+        {
+            JSValueProtect(m_context, m_onUpdated);
+        }
+    }
+}
+
+JSValueRef JSApplicationEventCallbackManager::getOnUpdated() const
+{
+    LOGD("Entered");
+    return m_onUpdated;
+}
+
+void JSApplicationEventCallbackManager::setOnUninstalled( JSValueRef onUninstalled )
+{
+    LOGD("Entered");
+    if (onUninstalled)
+    {
+        if (m_onUninstalled != NULL)
+        {
+            JSValueUnprotect(m_context, m_onUninstalled);
+        }
+
+        m_onUninstalled = JSValueToObject( m_context, onUninstalled, NULL );
+
+        if (m_onUninstalled != NULL)
+        {
+            JSValueProtect(m_context, m_onUninstalled);
+        }
+    }
+}
+
+JSValueRef JSApplicationEventCallbackManager::getOnUninstalled() const
+{
+    LOGD("Entered");
+    return m_onUninstalled;
+}
+
+void JSApplicationEventCallbackManager::setOnError( JSValueRef onError )
+{
+    LOGD("Entered");
+    if (onError)
+    {
+        if (m_onError != NULL)
+        {
+            JSValueUnprotect(m_context, m_onError);
+        }
+
+        m_onError = JSValueToObject( m_context, onError, NULL );
+
+        if (m_onError != NULL)
+        {
+            JSValueProtect(m_context, m_onError);
+        }
+    }
+}
+
+JSValueRef JSApplicationEventCallbackManager::getOnError() const
+{
+    LOGD("Entered");
+    return m_onError;
+}
+
+void JSApplicationEventCallbackManager::setContext( JSContextRef context )
+{
+    LOGD("Entered");
+    m_context = context;
+}
+
+void JSApplicationEventCallbackManager::setObject( JSObjectRef object )
+{
+    LOGD("Entered");
+    m_object = object;
+}
+
+JSObjectRef JSApplicationEventCallbackManager::getObject() const
+{
+    LOGD("Entered");
+    return m_object;
+}
+
+void JSApplicationEventCallbackManager::callOnInstalled( JSValueRef appInfo )
+{
+    LOGD("Entered");
+    if ( m_onInstalled == NULL )
+    {
+        return;
+    }
+    JSValueRef objParam[1] = { appInfo };
+    makeCallback( m_context, NULL, m_onInstalled, "oninstalled", objParam, 1 );
+}
+
+void JSApplicationEventCallbackManager::callOnUpdated( JSValueRef appInfo )
+{
+    LOGD("Entered");
+    if ( m_onUpdated == NULL )
+    {
+        return;
+    }
+    JSValueRef objParam[1] = { appInfo };
+    makeCallback( m_context, NULL, m_onUpdated, "onupdated", objParam, 1 );
+}
+
+void JSApplicationEventCallbackManager::callOnUninstalled( JSValueRef appId )
+{
+    LOGD("Entered");
+    if ( m_onUninstalled == NULL )
+    {
+        return;
+    }
+    JSValueRef objParam[1] = { appId };
+    makeCallback( m_context, NULL, m_onUninstalled, "onuninstalled", objParam, 1 );
+}
+
+void JSApplicationEventCallbackManager::callOnError( JSValueRef error )
+{
+    LOGD("Entered");
+    if ( m_onError == NULL )
+    {
+        return;
+    }
+    JSValueRef objParam[1] = { error };
+    makeCallback( m_context, NULL, m_onError, "onerror", objParam, 1 );
+}
+
+void JSApplicationEventCallbackManager::makeCallback(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef callback,
+        const char *szName,
+        JSValueRef argv[],
+        unsigned argc)
+{
+    LOGD("Entered");
+    if (callback == NULL)
+    {
+        LOGE("callback cannot be  NULL");
+        return;
+    }
+
+    if (JSObjectIsFunction(context, callback))
+    {
+        JSValueRef exception = NULL;
+
+        if (argc == 0)
+        {
+            JSObjectCallAsFunction(context, callback, object, 0, NULL, &exception);
+        }
+        else
+        {
+            JSObjectCallAsFunction(context, callback, object, argc, argv, &exception);
+        }
+
+        if (exception)
+            DeviceAPI::Common::WebKitProxy::reportException(context, exception);
+
+        return;
+    }
+}
+
+} // Application
+} // DeviceAPI
diff --git a/src/Application/JSApplicationEventCallbackManager.h b/src/Application/JSApplicationEventCallbackManager.h
new file mode 100755 (executable)
index 0000000..777c38b
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_APPLICATION_JS_APPLICATION_EVENT_CALLBACK_MANAGER_H_
+#define _TIZEN_APPLICATION_JS_APPLICATION_EVENT_CALLBACK_MANAGER_H_
+
+#include <memory>
+#include <Commons/IEvent.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+class JSApplicationEventCallbackManager;
+typedef std::shared_ptr<JSApplicationEventCallbackManager> JSApplicationEventCallbackManagerPtr;
+
+class JSApplicationEventCallbackManager :
+    public WrtDeviceApis::Commons::IEventPrivateData,
+    public DeviceAPI::Common::SecurityAccessor
+{
+private:
+    JSApplicationEventCallbackManager() {}
+    JSApplicationEventCallbackManager( JSContextRef context,
+            JSObjectRef onInstalled = NULL,
+            JSObjectRef onUpdated = NULL,
+            JSObjectRef onUninstalled = NULL,
+            JSObjectRef onError = NULL );
+
+public:
+    static JSApplicationEventCallbackManagerPtr createObject(JSContextRef context);
+
+    virtual ~JSApplicationEventCallbackManager();
+
+    void    setContext( JSContextRef context );
+    JSContextRef getContext() const { return m_context; }
+
+    void    setOnInstalled( JSValueRef onInstalled );
+    JSValueRef getOnInstalled() const;
+    void    setOnUpdated( JSValueRef onUpdated );
+    JSValueRef getOnUpdated() const;
+    void    setOnUninstalled( JSValueRef onUninstalled );
+    JSValueRef getOnUninstalled() const;
+    void    setOnError( JSValueRef onError );
+    JSValueRef getOnError() const;
+    void    setObject( JSObjectRef object );
+    JSObjectRef getObject() const;
+
+    void    callOnInstalled( JSValueRef contacts );
+    void    callOnUpdated( JSValueRef contacts );
+    void    callOnUninstalled( JSValueRef contactIds );
+    void    callOnError( JSValueRef error );
+
+private:
+    void    makeCallback(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef callback,
+            const char *szName,
+            JSValueRef argv[],
+            unsigned argc);
+
+    JSObjectRef  m_onInstalled;
+    JSObjectRef  m_onUpdated;
+    JSObjectRef  m_onUninstalled;
+    JSObjectRef  m_onError;
+    JSContextRef m_context;
+    JSObjectRef  m_object;
+};
+
+} // Application
+} // DeviceAPI
+
+#endif // _TIZEN_APPLICATION_JS_APPLICATION_EVENT_CALLBACK_MANAGER_H_
diff --git a/src/Application/JSApplicationInformation.cpp b/src/Application/JSApplicationInformation.cpp
new file mode 100755 (executable)
index 0000000..8a067ae
--- /dev/null
@@ -0,0 +1,281 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <memory>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Converter.h>
+#include <Commons/Exception.h>
+#include "ApplicationInformation.h"
+#include <JSWebAPIErrorFactory.h>
+#include "JSApplicationInformation.h"
+#include "AppManagerWrapper.h"
+#include "plugin_config_impl.h"
+#include <Export.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace WrtDeviceApis;
+using namespace DeviceAPI::Common;
+
+
+JSClassRef JSApplicationInformation::m_classRef = NULL;
+
+JSClassDefinition JSApplicationInformation::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_INTERFACE_APPLICATION_INFORMATION,
+    0,
+    m_property,
+    0,
+    initialize,
+    finalize,
+    NULL,     //HasProperty,
+    NULL,   //GetProperty,
+    NULL,     //SetProperty,
+    NULL,     //DeleteProperty,
+    NULL,     //GetPropertyNames,
+    NULL,     //CallAsFunction,
+    NULL,     //CallAsConstructor,
+    NULL,
+    NULL,     //ConvertToType
+};
+
+JSStaticValue JSApplicationInformation::m_property[] = {
+    { TIZEN_APPLICATION_INFORMATION_ID, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_INFORMATION_NAME, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_INFORMATION_ICONPATH, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_INFORMATION_VERSION, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_INFORMATION_SHOW, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_INFORMATION_CATEGORIES, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_INFORMATION_INSTALL_DATE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_INFORMATION_INSTALL_SIZE, getPropertySize, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_INFORMATION_PACKAGE_ID, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef DLL_EXPORT JSApplicationInformation::getClassRef() {
+    LOGD("Entered");
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+JSValueRef JSApplicationInformation::createJSObject(JSContextRef context,
+        const std::string &name,
+        const std::string &appId,
+        const std::string &iconPath,
+        const std::string &version,
+        const bool &show,
+        const std::vector<std::string> &categories,
+        const time_t &installDate,
+        const long &installSize,
+        const std::string &pkgId)
+{
+    LOGD("Entered");
+    ApplicationInformationPtr privateData = ApplicationInformationPtr(
+            new ApplicationInformation());
+    privateData->setName(name);
+    privateData->setAppId(appId);
+    privateData->setIconPath(iconPath);
+    privateData->setVersion(version);
+    privateData->setShow(show);
+    privateData->setCategories(categories);
+    privateData->setInstallDate(installDate);
+    privateData->setInstallSize(installSize);
+    privateData->setPackageId(pkgId);
+
+    JSApplicationInformationPriv *priv =
+            new JSApplicationInformationPriv(context, privateData);
+
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    return jsValueRef;
+}
+
+void JSApplicationInformation::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSApplicationInformation::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationInformationPriv* priv =
+            static_cast<JSApplicationInformationPriv*>(JSObjectGetPrivate(object));
+    if (priv == NULL)
+        return;
+
+    ApplicationInformationPtr privateData = priv->getObject();
+
+    JSValueRef installDateJSValue =
+            static_cast<JSValueRef>(privateData->getInstallDateJSValue());
+    if (installDateJSValue != NULL)
+        JSValueUnprotect(priv->getContext(), installDateJSValue);
+
+    JSValueRef categoriesJSValue =
+            static_cast<JSValueRef>(privateData->getCategoriesJSValue());
+    if (categoriesJSValue != NULL)
+        JSValueUnprotect(priv->getContext(), categoriesJSValue);
+
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+bool JSApplicationInformation::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+ApplicationInformationPtr JSApplicationInformation::getPrivData(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationInformationPriv *priv =
+            static_cast<JSApplicationInformationPriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    ApplicationInformationPtr result = priv->getObject();
+    if (!result) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return result;
+}
+
+ApplicationInformationPtr JSApplicationInformation::getApplicationInformation(JSContextRef context,
+        JSValueRef value)
+{
+    LOGD("Entered");
+    if (!isObjectOfClass(context, value)) {
+        throw TypeMismatchException("is not a object class");
+    }
+
+    JSObjectRef object = JSValueToObject(context, value, NULL);
+    if (!object) {
+        throw TypeMismatchException("Fail to get object");
+    }
+
+    JSApplicationInformationPriv *priv =
+            static_cast<JSApplicationInformationPriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+
+    return priv->getObject();
+}
+
+JSValueRef JSApplicationInformation::getProperty(JSContextRef context,
+    JSObjectRef object,
+    JSStringRef propertyName,
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CommonsJavaScript::Converter converter(context);
+        ApplicationInformationPtr privateData = getPrivData(context, object);
+        JSContextRef gContext =
+                static_cast<JSApplicationInformationPriv*>(JSObjectGetPrivate(object))->getContext();
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_INFORMATION_ID)) {
+            return converter.toJSValueRef(privateData->getAppId());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_INFORMATION_NAME)) {
+            return converter.toJSValueRef(privateData->getName());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_INFORMATION_ICONPATH)) {
+            return converter.toJSValueRef(privateData->getIconPath());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_INFORMATION_SHOW)) {
+            return converter.toJSValueRef(privateData->getShow());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_INFORMATION_CATEGORIES)) {
+            JSValueRef categoriesJSValue = static_cast<JSValueRef>(privateData->getCategoriesJSValue());
+            if (categoriesJSValue == NULL) {
+                categoriesJSValue = converter.toJSValueRef(privateData->getCategories());
+                JSValueProtect(gContext, categoriesJSValue);
+                privateData->setCategoriesJSValue(static_cast<const void *>(categoriesJSValue));
+            }
+            return categoriesJSValue;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_INFORMATION_PACKAGE_ID)) {
+            return converter.toJSValueRef(privateData->getPackageId());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_INFORMATION_VERSION)) {
+            return converter.toJSValueRef(privateData->getVersion());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_INFORMATION_INSTALL_DATE)) {
+            JSValueRef installDateJSValue = static_cast<JSValueRef>(privateData->getInstallDateJSValue());
+            if (installDateJSValue == NULL) {
+                installDateJSValue = converter.toJSValueRef(privateData->getInstallDate());
+                JSValueProtect(gContext, installDateJSValue);
+                privateData->setInstallDateJSValue(static_cast<const void *>(installDateJSValue));
+            }
+            return installDateJSValue;
+        }
+    } catch (...) {
+        LOGE("Exception occured while get property");
+        return JSValueMakeUndefined(context);
+    }
+
+    /* do not return undefined object to find method */
+    return NULL;
+}
+
+JSValueRef JSApplicationInformation::getPropertySize(JSContextRef context,
+    JSObjectRef object,
+    JSStringRef propertyName,
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    JSApplicationInformationPriv *priv =
+            static_cast<JSApplicationInformationPriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Private object is not exists.");
+        return JSValueMakeUndefined(context);
+    }
+
+    TIZEN_CHECK_ACCESS(context, exception, priv, APPLICATION_FUNCTION_API_SIZE);
+
+    ApplicationInformationPtr privateData = priv->getObject();
+    if (!privateData) {
+        LOGE("Private object is wrong");
+        return JSValueMakeUndefined(context);
+    }
+
+    try {
+        CommonsJavaScript::Converter converter(context);
+
+        if (!privateData->isInitialized()) {
+            AppManagerWrapperSingleton::Instance().initializeAppInfo(privateData);
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_INFORMATION_INSTALL_SIZE)) {
+            return converter.toJSValueRefLong(privateData->getInstallSize());
+        }
+
+    } catch (...) {
+        LOGE("Exception occured while get property");
+        return JSValueMakeUndefined(context);
+    }
+
+    /* do not return undefined object to find method */
+    return NULL;
+}
+
+}
+}
diff --git a/src/Application/JSApplicationInformation.h b/src/Application/JSApplicationInformation.h
new file mode 100755 (executable)
index 0000000..a643de2
--- /dev/null
@@ -0,0 +1,131 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_TIZEN_JS_APPLICATION_INFORMATION_H_
+#define TIZENAPIS_TIZEN_JS_APPLICATION_INFORMATION_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <memory>
+#include <Security.h>
+#include "ApplicationInformation.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+#define TIZEN_INTERFACE_APPLICATION_INFORMATION "ApplicationInformation"
+
+#define TIZEN_APPLICATION_INFORMATION_ID "id"
+#define TIZEN_APPLICATION_INFORMATION_NAME "name"
+#define TIZEN_APPLICATION_INFORMATION_ICONPATH "iconPath"
+#define TIZEN_APPLICATION_INFORMATION_VERSION "version"
+#define TIZEN_APPLICATION_INFORMATION_SHOW "show"
+#define TIZEN_APPLICATION_INFORMATION_CATEGORIES "categories"
+#define TIZEN_APPLICATION_INFORMATION_INSTALL_DATE "installDate"
+#define TIZEN_APPLICATION_INFORMATION_INSTALL_SIZE "size"
+#define TIZEN_APPLICATION_INFORMATION_PACKAGE_ID "packageId"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<ApplicationInformationPtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> JSApplicationInformationPrivObject;
+
+class JSApplicationInformationPriv :
+    public JSApplicationInformationPrivObject,
+    public DeviceAPI::Common::SecurityAccessor
+{
+public:
+    JSApplicationInformationPriv(JSContextRef context, ApplicationInformationPtr appinfo) :
+        JSApplicationInformationPrivObject(context, appinfo),
+        DeviceAPI::Common::SecurityAccessor()
+    {
+        LOGD("Entered");
+    }
+
+    virtual ~JSApplicationInformationPriv()
+    {
+        LOGD("Entered");
+    }
+};
+
+class JSApplicationInformation {
+public:
+    /*
+    * This initializes this JS class in the JS Engine.
+    */
+    static JSClassRef getClassRef();
+
+    static JSValueRef createJSObject(JSContextRef context,
+            const std::string &name,
+            const std::string &package,
+            const std::string &iconPath,
+            const std::string &version,
+            const bool &show,
+            const std::vector<std::string> &categories,
+            const time_t &installDate,
+            const long &installSize,
+            const std::string &pkgId);
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+    static ApplicationInformationPtr
+        getApplicationInformation(JSContextRef context, JSValueRef value);
+
+private:
+   /**
+    * The callback invoked when an object is first created.
+    */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+   /**
+    * The callback invoked when an object is finalized.
+    */
+    static void finalize(JSObjectRef object);
+
+   /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+   /**
+    * This structure describes a statically declared function property.
+    */
+    static JSStaticFunction m_functions[];
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_classRef;
+
+    static ApplicationInformationPtr getPrivData(JSContextRef context, JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception);
+
+    static JSValueRef getPropertySize(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception);
+
+};
+
+}
+}
+#endif
diff --git a/src/Application/JSApplicationManager.cpp b/src/Application/JSApplicationManager.cpp
new file mode 100755 (executable)
index 0000000..fe16895
--- /dev/null
@@ -0,0 +1,1043 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+//#include <memory>
+
+#include <CommonsJavaScript/Converter.h>
+
+//#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSUtils.h>
+
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+#include <SecurityExceptions.h>
+//#include <Commons/Exception.h>
+#include <JSWebAPIErrorFactory.h>
+
+#include "ApplicationFactory.h"
+#include "plugin_config_impl.h"
+#include "ApplicationController.h"
+#include "JSApplicationManager.h"
+#include "ApplicationConverter.h"
+#include "ApplicationUtil.h"
+#include "JSApplicationControl.h"
+#include "ApplicationAsyncCallbackManager.h"
+#include "ApplicationListenerManager.h"
+#include "ApplicationInformationEventPrivateData.h"
+#include "JSApplicationEventCallbackManager.h"
+#include "JSApplication.h"
+#include "ApplicationManager.h"
+
+#include <TimeTracer.h>
+#include <Export.h>
+#include <Logger.h>
+#include <Security.h>
+
+#include <plugins-ipc-message/ipc_message_support.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace DeviceAPI::Common;
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+JSClassRef JSApplicationManager::m_jsClassRef = NULL;
+
+JSClassDefinition JSApplicationManager::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_INTERFACE_APPLICATION_MANAGER,
+        NULL,
+        NULL,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL,
+        NULL,
+        NULL,
+        NULL
+};
+
+JSStaticFunction JSApplicationManager::m_function[] = {
+        { APPLICATION_FUNCTION_API_GET_CURRENT_APP,
+                JSApplicationManager::getCurrentApplication, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_LAUNCH,
+                JSApplicationManager::launch, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_KILL,
+                JSApplicationManager::kill, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_SET_USER_AGENT,
+                JSApplicationManager::setUserAgent, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_GET_APPS_INFO,
+                JSApplicationManager::getAppsInfo, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_GET_APPS_CONTEXT,
+                JSApplicationManager::getAppsContext, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_GET_APP_INFO,
+                JSApplicationManager::getAppInfo, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_GET_APP_CONTEXT,
+                JSApplicationManager::getAppContext, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_ADD_APP_INFO_EVENT_LISTENER,
+                JSApplicationManager::addAppInfoEventListener, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_REMOVE_APP_INFO_EVENT_LISTENER,
+                JSApplicationManager::removeAppInfoEventListener, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_LAUNCH_APP_CONTROL,
+                JSApplicationManager::launchAppControl, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_FIND_APP_CONTROL,
+                JSApplicationManager::findAppControl, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_GET_APP_CERTS,
+                JSApplicationManager::getAppCerts, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_GET_APP_SHARED_URI,
+                JSApplicationManager::getAppSharedURI, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_GET_APP_META_DATA,
+                JSApplicationManager::getAppMetaData, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSApplicationManager::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSApplicationManager::getClassInfo()
+{
+    LOGD("Entered");
+    return &m_classInfo;
+}
+
+void JSApplicationManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+    ApplicationController* priv =
+            static_cast<ApplicationController*>(JSObjectGetPrivate(object));
+
+    if (!priv) {
+        IApplicationManagerPtr applications(ApplicationFactory::getInstance().createApplication());
+        priv = new ApplicationController(context, applications);
+
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    } else {
+        LOGD("private date is already exist");
+    }
+}
+
+void JSApplicationManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ApplicationController* priv =
+            static_cast<ApplicationController*> (JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+JSValueRef JSApplicationManager::getCurrentApplication(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        ApplicationController *controller =
+                static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        JSContextRef gContext = controller->getContext();
+
+        ApplicationPtr result = ApplicationManager::getCurrentApplication();
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSApplication::makeObject(gContext, result, controller);
+
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.getCurrentApplication().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplicationManager::launch(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIME_TRACER_ITEM_BEGIN("launch(async)", 0);
+
+    try {
+        IApplicationManagerPtr appmgr;
+        JSContextRef gContext;
+        ApplicationController *controller;
+
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        appmgr = controller->getObject();
+        gContext = controller->getContext();
+
+        TIME_TRACER_ITEM_BEGIN("launch(ACE)", 0);
+        TIZEN_CHECK_ACCESS(context, exception, controller, APPLICATION_FUNCTION_API_LAUNCH);
+        TIME_TRACER_ITEM_END("launch(ACE)", 0);
+
+        EventApplicationLaunchPtr event(new EventApplicationLaunch());
+        JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // id
+        std::string id = validator.toString(0);
+        event->setAppId(id);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(1, true);
+        if (successCallback)
+            callbackManager->setOnSuccess(successCallback);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+        if (errorCallback)
+            callbackManager->setOnError(errorCallback);
+
+        callbackManager->setObject(thisObject);
+        ApplicationAsyncCallbackManagerSingleton::Instance().registerCallbackManager(
+                callbackManager, gContext);
+
+        event->setPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        event->setForAsynchronousCall(controller);
+
+        appmgr->launch(event);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.launch().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSApplicationManager::kill(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIME_TRACER_ITEM_BEGIN("kill(async)", 0);
+
+    try {
+        IApplicationManagerPtr appmgr;
+        JSContextRef gContext;
+        ApplicationController *controller;
+
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        appmgr = controller->getObject();
+        gContext = controller->getContext();
+
+        TIME_TRACER_ITEM_BEGIN("kill(ACE)", 0);
+        TIZEN_CHECK_ACCESS(context, exception, controller, APPLICATION_FUNCTION_API_KILL);
+        TIME_TRACER_ITEM_END("kill(ACE)", 0);
+
+        EventApplicationKillPtr event(new EventApplicationKill());
+        JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // contextId
+       std::string contextId = validator.toString(0);
+        event->setContextId(contextId);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(1, true);
+        if (successCallback)
+            callbackManager->setOnSuccess(successCallback);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+        if (errorCallback)
+            callbackManager->setOnError(errorCallback);
+
+        callbackManager->setObject(thisObject);
+        ApplicationAsyncCallbackManagerSingleton::Instance().registerCallbackManager(
+                callbackManager, gContext);
+
+        event->setPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        event->setForAsynchronousCall(controller);
+
+        appmgr->kill(event);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.kill().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplicationManager::setUserAgent(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // UserAgent
+        std::string userAgent = validator.toString(0);
+
+        // perform
+        IPCMessageSupport::sendAsyncMessageToUiProcess(
+                IPCMessageSupport::TIZEN_CHANGE_USERAGENT, userAgent.c_str(), NULL, NULL);
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.removeAppInfoEventListener().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplicationManager::launchAppControl(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIME_TRACER_ITEM_BEGIN("launchAppControlReply", 0);
+    TIME_TRACER_ITEM_BEGIN("launchAppControl(async)", 0);
+    TIME_TRACER_ITEM_BEGIN("launchAppControlReply(async)", 0);
+
+    try {
+        IApplicationManagerPtr appmgr;
+        JSContextRef gContext;
+        ApplicationController *controller;
+
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        appmgr = controller->getObject();
+        gContext = controller->getContext();
+
+        TIME_TRACER_ITEM_BEGIN("launchAppControl(ACE)", 0);
+        TIZEN_CHECK_ACCESS(context, exception, controller,
+                APPLICATION_FUNCTION_API_LAUNCH_APP_CONTROL);
+        TIME_TRACER_ITEM_END("launchAppControl(ACE)", 0);
+
+        EventApplicationLaunchAppControlPtr event(new EventApplicationLaunchAppControl());
+        JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // appControl
+        JSObjectRef appControlObj = validator.toObject(0);
+        ApplicationControlPtr appControl = converter->toApplicationControl(appControlObj);
+        if (!appControl) {
+            throw TypeMismatchException("ApplicationControl's private object is NULL.");
+        }
+        event->setAppControl(appControl);
+
+        // id
+        std::string id = validator.toString(1, true, "");
+        event->setAppId(id);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(2, true);
+        if (successCallback)
+            callbackManager->setOnSuccess(successCallback);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(3, true);
+        if (errorCallback)
+            callbackManager->setOnError(errorCallback);
+
+        callbackManager->setObject(thisObject);
+        ApplicationAsyncCallbackManagerSingleton::Instance().registerCallbackManager(
+                callbackManager, gContext);
+
+        // replyCallback
+        JSCallbackManagerPtr callbackManagerReply;
+        JSObjectRef replyCallbackObj = validator.toCallbackObject(4,
+                true, "onsuccess", "onfailure", NULL);
+
+        if (replyCallbackObj) {
+            callbackManagerReply = JSCallbackManager::createObject(gContext);
+
+            // onsuccess
+            JSValueRef onsuccess = JSUtil::getProperty(context,
+                    replyCallbackObj, "onsuccess", exception);
+            if (!JSValueIsUndefined(context, onsuccess)) {
+                callbackManagerReply->setOnSuccess(onsuccess);
+            }
+
+            // onfailure
+            JSValueRef onfailure = JSUtil::getProperty(context,
+                    replyCallbackObj, "onfailure", exception);
+            if (!JSValueIsUndefined(context, onfailure)) {
+                callbackManagerReply->setOnError(onfailure);
+            }
+
+            callbackManagerReply->setObject(thisObject);
+            ApplicationAsyncCallbackManagerSingleton::Instance().registerCallbackManager(
+                    callbackManagerReply, gContext);
+
+            EventApplicationLaunchAppControlReplyPtr eventReply(new EventApplicationLaunchAppControlReply());
+            eventReply->setPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManagerReply));
+            eventReply->setForAsynchronousCall(controller);
+
+            event->setEventReply(eventReply);
+        }
+
+        event->setPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        event->setForAsynchronousCall(controller);
+
+        appmgr->launchAppControl(event);
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        TIME_TRACER_ITEM_END("launchAppControlReply", 0);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(""
+                "Unknown Error in ApplicationManager.launchAppControl().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+
+JSValueRef JSApplicationManager::findAppControl(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIME_TRACER_ITEM_BEGIN("findAppControl(async)", 0);
+    try {
+
+        IApplicationManagerPtr appmgr;
+        JSContextRef gContext;
+        ApplicationController *controller;
+
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        appmgr = controller->getObject();
+        gContext = controller->getContext();
+
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+        EventApplicationFindAppControlPtr event(new EventApplicationFindAppControl());
+        JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // appControl
+        JSObjectRef appControlObj = validator.toObject(0);
+
+        ApplicationControlPtr appControl = converter->toApplicationControl(appControlObj);
+        if (!appControl) {
+            throw TypeMismatchException("ApplicationControl's private object is NULL.");
+        }
+        event->setAppControl(appControl);
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(1);
+        if (successCallbackObj) {
+            callbackManager->setOnSuccess(successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+        if (errorCallback) {
+            callbackManager->setOnError(errorCallback);
+        }
+
+        callbackManager->setObject(thisObject);
+        ApplicationAsyncCallbackManagerSingleton::Instance().registerCallbackManager(
+                callbackManager, gContext);
+
+        event->setPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        event->setForAsynchronousCall(controller);
+        event->copyAceCheckAccessFunction(controller);
+
+        appmgr->findAppControl(event);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.findAppControl().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplicationManager::getAppsContext(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIME_TRACER_ITEM_BEGIN("getAppsContext(async)", 0);
+
+    try {
+        IApplicationManagerPtr appmgr;
+        JSContextRef gContext;
+        ApplicationController *controller;
+
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        appmgr = controller->getObject();
+        gContext = controller->getContext();
+
+        EventApplicationGetAppsContextPtr event(new EventApplicationGetAppsContext());
+        JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(0);
+        callbackManager->setOnSuccess(successCallbackObj);
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(1, true);
+        if (errorCallbackObj)
+            callbackManager->setOnError(errorCallbackObj);
+
+        callbackManager->setObject(thisObject);
+        ApplicationAsyncCallbackManagerSingleton::Instance().registerCallbackManager(
+                callbackManager, gContext);
+
+        event->setPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        event->setForAsynchronousCall(controller);
+
+        appmgr->getAppsContext(event);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("BasePlatformException");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("etc...");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.getAppsContext().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplicationManager::getAppContext(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        ApplicationContextPtr result = ApplicationManager::getAppContext(
+                validator.toString(0, true, ""));
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return converter->toJSValueRefFromApplicationContext(result);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const WrtDeviceApis::Commons::NotFoundException& ex) {
+       return JSWebAPIErrorFactory::postException(context, exception,
+               JSWebAPIErrorFactory::NOT_FOUND_ERROR, ex.GetMessage());
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.getAppContext().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplicationManager::getAppsInfo(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIME_TRACER_ITEM_BEGIN("getAppsInfo(async)", 0);
+
+    try {
+        IApplicationManagerPtr appmgr;
+        JSContextRef gContext;
+        ApplicationController *controller;
+
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        appmgr = controller->getObject();
+        gContext = controller->getContext();
+
+        EventApplicationGetAppsInfoPtr event(new EventApplicationGetAppsInfo());
+        JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(0);
+        callbackManager->setOnSuccess(successCallbackObj);
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(1, true);
+        if (errorCallbackObj) {
+            callbackManager->setOnError(errorCallbackObj);
+        }
+
+        callbackManager->setObject(thisObject);
+        ApplicationAsyncCallbackManagerSingleton::Instance().registerCallbackManager(
+                callbackManager, gContext);
+
+        event->setPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        event->setForAsynchronousCall(controller);
+        event->copyAceCheckAccessFunction(controller);
+
+        appmgr->getAppsInfo(event);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.getAppsInfo().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplicationManager::getAppInfo(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        ApplicationController *controller =
+                static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        JSContextRef gContext = controller->getContext();
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        ApplicationInformationPtr result = ApplicationManager::getAppInfo(
+                validator.toString(0, true, ""));
+        ApplicationConverter converter(gContext, controller);
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return converter.toJSValueRefFromApplicationInformation(result);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const WrtDeviceApis::Commons::NotFoundException& ex) {
+       return JSWebAPIErrorFactory::postException(context,
+               exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, ex.GetMessage());
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.getAppInfo().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSApplicationManager::addAppInfoEventListener(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        IApplicationManagerPtr appmgr;
+        JSContextRef gContext;
+        ApplicationController *controller;
+
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        appmgr = controller->getObject();
+        gContext = controller->getContext();
+
+        EventApplicationAddAppInfoEventListenerPtr event(
+                new EventApplicationAddAppInfoEventListener());
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // eventCallback
+        JSObjectRef eventCBObj = validator.toCallbackObject(0,
+                false, "oninstalled", "onupdated", "onuninstalled", NULL);
+        JSApplicationEventCallbackManagerPtr callbackManager = JSApplicationEventCallbackManager::createObject(gContext);
+        callbackManager->copyAceCheckAccessFunction(controller);
+
+        JSValueRef oninstalled = JSUtil::getProperty(context,
+                eventCBObj, "oninstalled", exception);
+        if (!JSValueIsUndefined(context, oninstalled)) {
+            callbackManager->setOnInstalled(oninstalled);
+        }
+
+        JSValueRef onupdated = JSUtil::getProperty(context,
+                eventCBObj, "onupdated", exception);
+        if (!JSValueIsUndefined(context, onupdated)) {
+            callbackManager->setOnUpdated(onupdated);
+        }
+
+        JSValueRef onuninstalled = JSUtil::getProperty(context,
+                eventCBObj, "onuninstalled", exception);
+        if (!JSValueIsUndefined(context, onuninstalled)) {
+            callbackManager->setOnUninstalled(onuninstalled);
+        }
+
+        EventApplicationAppInfoEventListenerEmitterPtr emitter(
+                new EventApplicationAppInfoEventListenerEmitter());
+
+        emitter->setEventPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        emitter->setListener(controller);
+
+        event->setEmitter(emitter);
+        event->setForSynchronousCall();
+
+        appmgr->addAppInfoEventListener(event);
+
+        if (event->getExceptionCode() != ExceptionCodes::None) {
+            throw UnknownException("Unknown Exception Occured");
+        }
+
+        unsigned long id = event->getWatchId();
+
+        ApplicationListenerCancellerPtr canceller =
+                ApplicationListenerCancellerPtr(
+                        new ApplicationListenerCanceller(gContext, thisObject, id));
+        DeviceAPI::Common::IListenerItemPtr listenerItem =
+                std::static_pointer_cast<DeviceAPI::Common::IListenerItem>(canceller);
+        ApplicationListenerManagerSingleton::Instance().registerListener(listenerItem, gContext);
+
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return converter->toJSValueRef(id);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.addAppInfoEventListener().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSApplicationManager::removeAppInfoEventListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        IApplicationManagerPtr appmgr;
+        JSContextRef gContext;
+        ApplicationController *controller;
+
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+        appmgr = controller->getObject();
+        gContext = controller->getContext();
+
+        EventApplicationRemoveAppInfoEventListenerPtr event(
+                new EventApplicationRemoveAppInfoEventListener());
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // watchId
+        long watchId = validator.toLong(0);
+        event->setWatchId(watchId);
+
+        event->setForSynchronousCall();
+
+        appmgr->removeAppInfoEventListener(event);
+
+        ApplicationListenerCancellerPtr canceller =
+                ApplicationListenerCancellerPtr(
+                        new ApplicationListenerCanceller(gContext, thisObject, watchId));
+        DeviceAPI::Common::IListenerItemPtr listenerItem =
+                std::static_pointer_cast<DeviceAPI::Common::IListenerItem>(canceller);
+        ApplicationListenerManagerSingleton::Instance().unregisterListener(listenerItem);
+
+        if (event->getExceptionCode() == ExceptionCodes::NotFoundException) {
+            throw NotFoundException("Watch id not found");
+        }
+        else if (event->getExceptionCode() != ExceptionCodes::None) {
+            throw UnknownException("UnknownException Occured");
+        }
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.removeAppInfoEventListener().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplicationManager::getAppCerts(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        ApplicationController *controller;
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+
+        TIME_TRACER_ITEM_BEGIN("getAppCerts(ACE)", 0);
+        TIZEN_CHECK_ACCESS(context, exception, controller, APPLICATION_FUNCTION_API_GET_APP_CERTS);
+        TIME_TRACER_ITEM_END("getAppCerts(ACE)", 0);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        ApplicationCertArrayPtr result = ApplicationManager::getAppCerts(
+                validator.toString(0, true, ""));
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return converter->toJSValueRefFromApplicationCerts(result);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const WrtDeviceApis::Commons::NotFoundException& ex) {
+       return JSWebAPIErrorFactory::postException(context,
+               exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, ex.GetMessage());
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(""
+                "Unknown Error in ApplicationManager.getAppCerts().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSApplicationManager::getAppSharedURI(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::string result =
+                ApplicationManager::getAppSharedURI(validator.toString(0, true, ""));
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return converter->toJSValueRef(result);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const WrtDeviceApis::Commons::NotFoundException& ex) {
+       return JSWebAPIErrorFactory::postException(context,
+               exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, ex.GetMessage());
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSApplicationManager::getAppMetaData(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        ApplicationController *controller;
+        controller = static_cast<ApplicationController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            throw TypeMismatchException("No private object.");
+        }
+
+        TIME_TRACER_ITEM_BEGIN("getAppMetaData(ACE)", 0);
+        TIZEN_CHECK_ACCESS(context,
+                exception, controller, APPLICATION_FUNCTION_API_GET_APP_META_DATA);
+        TIME_TRACER_ITEM_END("getAppMetaData(ACE)", 0);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        ApplicationMetaDataArrayPtr result =
+                ApplicationManager::getAppMetaData(validator.toString(0, true, ""));
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return converter->toJSValueRefFromApplicationMetaDataArray(result);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const WrtDeviceApis::Commons::NotFoundException& ex) {
+       return JSWebAPIErrorFactory::postException(context,
+               exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, ex.GetMessage());
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in ApplicationManager.getAppCerts().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+/* scheme-callback using title is not working on iframe. So, use IPC API instead of below API.
+void JSApplicationManager::setTitleProperty(JSContextRef context, std::string propertyValue) {
+
+    WrtDeviceApis::CommonsJavaScript::Converter converter(context);
+    // get window object
+    JSObjectRef windowObject = JSContextGetGlobalObject(context);
+
+    // get title object
+    JSObjectRef documentObject = converter.toJSObjectRef(JSObjectGetProperty(context,
+            windowObject,
+            ScopedJSStringRef(JSStringCreateWithUTF8CString("document")).get(),
+            NULL));
+
+    JSObjectSetProperty(context,
+            documentObject,
+            ScopedJSStringRef(JSStringCreateWithUTF8CString("title")).get(),
+            JSValueMakeString(context, JSStringCreateWithUTF8CString("tizen://dummy#$#@##")),
+            kJSPropertyAttributeNone,
+            NULL);
+
+    JSObjectSetProperty(context,
+            documentObject,
+            ScopedJSStringRef(JSStringCreateWithUTF8CString("title")).get(),
+            JSValueMakeString(context, JSStringCreateWithUTF8CString(propertyValue.c_str())),
+            kJSPropertyAttributeNone,
+            NULL);
+}
+*/
+
+}
+}
diff --git a/src/Application/JSApplicationManager.h b/src/Application/JSApplicationManager.h
new file mode 100644 (file)
index 0000000..54b0397
--- /dev/null
@@ -0,0 +1,170 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_TIZEN_JS_APPLICATION_MANAGER_H_
+#define TIZENAPIS_TIZEN_JS_APPLICATION_MANAGER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "IApplicationManager.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+#define TIZEN_INTERFACE_APPLICATION_MANAGER "ApplicationManager"
+
+class JSApplicationManager {
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    //static void setTitleProperty(JSContextRef context, std::string propertyValue);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Gets a current application
+     */
+    static JSValueRef getCurrentApplication(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Launches a application with given application id
+     */
+    static JSValueRef launch(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Kills the application based on application context.
+     */
+    static JSValueRef kill(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+
+    /**
+     * exit current application
+     */
+    static JSValueRef setUserAgent(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Gets the list of installed packages.
+     */
+    static JSValueRef getAppsInfo(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Gets the list of running packages.
+     */
+    static JSValueRef getAppsContext(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Gets the application information of based on the package name.
+     */
+    static JSValueRef getAppInfo(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Gets the current application Context
+     */
+    static JSValueRef getAppContext(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Watch for changes on installed applicaiton.
+     */
+    static JSValueRef addAppInfoEventListener(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Unset installed Applications listener
+     */
+    static JSValueRef removeAppInfoEventListener(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Launch a application control
+     */
+    static JSValueRef launchAppControl(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Find application info list with application control
+     */
+    static JSValueRef findAppControl(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Get certificate information of given application
+     */
+    static JSValueRef getAppCerts(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Get shared directory URI of specific application
+     */
+    static JSValueRef getAppSharedURI(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Get meta data of specific application
+     */
+    static JSValueRef getAppMetaData(JSContextRef context,
+            JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+}
+}
+#endif
diff --git a/src/Application/JSApplicationMetaData.cpp b/src/Application/JSApplicationMetaData.cpp
new file mode 100644 (file)
index 0000000..5da13f3
--- /dev/null
@@ -0,0 +1,143 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <memory>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Converter.h>
+
+//#include <Commons/Exception.h>
+#include <JSWebAPIErrorFactory.h>
+
+#include "ApplicationMetaData.h"
+#include "JSApplicationMetaData.h"
+#include <Export.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace WrtDeviceApis;
+using namespace DeviceAPI::Common;
+
+
+JSClassRef JSApplicationMetaData::m_classRef = NULL;
+
+JSClassDefinition JSApplicationMetaData::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_INTERFACE_APPLICATION_META_DATA,
+    0,
+    m_property,
+    0,
+    initialize,
+    finalize,
+    NULL,     //HasProperty,
+    NULL,   //GetProperty,
+    NULL,     //SetProperty,
+    NULL,     //DeleteProperty,
+    NULL,     //GetPropertyNames,
+    NULL,     //CallAsFunction,
+    NULL,     //CallAsConstructor,
+    NULL,
+    NULL,     //ConvertToType
+};
+
+JSStaticValue JSApplicationMetaData::m_property[] = {
+    { TIZEN_APPLICATION_META_DATA_KEY, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_APPLICATION_META_DATA_VALUE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef DLL_EXPORT JSApplicationMetaData::getClassRef() {
+    LOGD("Entered");
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+
+void JSApplicationMetaData::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSApplicationMetaData::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationMetaDataPriv* priv =
+            static_cast<JSApplicationMetaDataPriv*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+bool JSApplicationMetaData::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+ApplicationMetaDataPtr JSApplicationMetaData::getPrivData(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSApplicationMetaDataPriv *priv =
+            static_cast<JSApplicationMetaDataPriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is null");
+    }
+    ApplicationMetaDataPtr result = priv->getObject();
+    if (!result) {
+        throw TypeMismatchException("Private object is null");
+    }
+    return result;
+}
+
+
+JSValueRef JSApplicationMetaData::getProperty(JSContextRef context,
+    JSObjectRef object,
+    JSStringRef propertyName,
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CommonsJavaScript::Converter converter(context);
+        ApplicationMetaDataPtr privateData = getPrivData(object);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_META_DATA_KEY)) {
+            return converter.toJSValueRef(privateData->getKey());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_META_DATA_VALUE)) {
+            std::string value = privateData->getValue();
+
+            // if value does not have value, return empty string.
+            if (value.compare("(null)") == 0) {
+                value.clear();
+            }
+
+            return converter.toJSValueRef(value);
+        }
+    } catch (...) {
+        LOGE("Exception occured while get property");
+        return JSValueMakeUndefined(context);
+    }
+
+    /* do not return undefined object to find method */
+    return NULL;
+}
+
+}
+}
diff --git a/src/Application/JSApplicationMetaData.h b/src/Application/JSApplicationMetaData.h
new file mode 100755 (executable)
index 0000000..1a52487
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_TIZEN_JS_APPLICATION_META_DATA_H_
+#define TIZENAPIS_TIZEN_JS_APPLICATION_META_DATA_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Application {
+
+#define TIZEN_INTERFACE_APPLICATION_META_DATA "ApplicationMetaData"
+
+#define TIZEN_APPLICATION_META_DATA_KEY     "key"
+#define TIZEN_APPLICATION_META_DATA_VALUE   "value"
+
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<ApplicationMetaDataPtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> JSApplicationMetaDataPriv;
+
+class JSApplicationMetaData{
+public:
+    /*
+    * This initializes this JS class in the JS Engine.
+    */
+    static JSClassRef getClassRef();
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+private:
+   /**
+    * The callback invoked when an object is first created.
+    */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+   /**
+    * The callback invoked when an object is finalized.
+    */
+    static void finalize(JSObjectRef object);
+
+   /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_classRef;
+
+    static ApplicationMetaDataPtr getPrivData(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception);
+
+};
+
+}
+}
+#endif
diff --git a/src/Application/JSRequestedApplicationControl.cpp b/src/Application/JSRequestedApplicationControl.cpp
new file mode 100644 (file)
index 0000000..e9d9bf2
--- /dev/null
@@ -0,0 +1,284 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <memory>
+
+#include <SecurityExceptions.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+
+#include "plugin_config.h"
+#include "ApplicationConverter.h"
+#include "ApplicationUtil.h"
+#include "JSRequestedApplicationControl.h"
+#include <Export.h>
+
+#include <TimeTracer.h>
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Application {
+
+using WrtDeviceApis::Commons::NotFoundException;
+
+JSClassRef JSRequestedApplicationControl::m_jsClassRef = NULL;
+
+JSClassDefinition JSRequestedApplicationControl::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_INTERFACE_REQUESTED_APPLICATION_CONTROL,
+    0,
+    m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL,     //HasProperty,
+    NULL,
+    NULL,     //SetProperty,
+    NULL,     //DeleteProperty,
+    NULL,     //GetPropertyNames,
+    NULL,     //CallAsFunction,
+    NULL,     //CallAsConstructor,
+    NULL,
+    NULL,     //ConvertToType
+};
+
+JSStaticValue JSRequestedApplicationControl::m_property[] = {
+    { TIZEN_APPLICATION_CONTROL, getProperty, NULL, kJSPropertyAttributeNone },
+    { TIZEN_CALLER_APP_ID, getProperty, NULL, kJSPropertyAttributeNone },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSRequestedApplicationControl::m_function[] = {
+        { APPLICATION_FUNCTION_API_REPLY_RESULT,
+                JSRequestedApplicationControl::replyResult, kJSPropertyAttributeNone },
+        { APPLICATION_FUNCTION_API_REPLY_FAILURE,
+                JSRequestedApplicationControl::replyFailure,kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSRequestedApplicationControl::getClassInfo()
+{
+    LOGD("Entered");
+    return &m_classInfo;
+}
+
+JSClassRef DLL_EXPORT JSRequestedApplicationControl::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+
+    return m_jsClassRef;
+}
+
+JSObjectRef JSRequestedApplicationControl::createJSObject(JSContextRef context,
+        const RequestedApplicationControlPtr &appsvc)
+{
+    LOGD("Entered");
+    JSRequestedApplicationControlPriv *priv = new JSRequestedApplicationControlPriv(context, appsvc);
+    if (!priv) {
+        ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Can not new an object");
+    }
+
+    return JSObjectMake(context, getClassRef(), priv);
+}
+
+void JSRequestedApplicationControl::initialize(JSContextRef context,JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSRequestedApplicationControl::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSRequestedApplicationControlPriv* priv =
+            static_cast<JSRequestedApplicationControlPriv*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+
+bool JSRequestedApplicationControl::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+RequestedApplicationControlPtr JSRequestedApplicationControl::getRequestedApplicationControl(
+        JSContextRef context,
+        JSValueRef value)
+{
+    LOGD("Entered");
+    if (!isObjectOfClass(context, value)) {
+        Throw(WrtDeviceApis::Commons::InvalidArgumentException);
+    }
+
+    JSObjectRef object = JSValueToObject(context, value, NULL);
+    if (!object) {
+        Throw(WrtDeviceApis::Commons::InvalidArgumentException);
+    }
+
+    JSRequestedApplicationControlPriv *priv =
+            static_cast<JSRequestedApplicationControlPriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        Throw(WrtDeviceApis::Commons::InvalidArgumentException);
+    }
+    return priv->getObject();
+}
+
+
+RequestedApplicationControlPtr JSRequestedApplicationControl::getPrivData(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSRequestedApplicationControlPriv *priv =
+            static_cast<JSRequestedApplicationControlPriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is null");
+    }
+    RequestedApplicationControlPtr result = priv->getObject();
+    if (!result) {
+        ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is null");
+    }
+    return result;
+}
+
+JSValueRef JSRequestedApplicationControl::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    JSRequestedApplicationControlPriv *priv =
+            static_cast<JSRequestedApplicationControlPriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Exception occured while get property");
+        return JSValueMakeUndefined(context);
+    }
+
+    try {
+        RequestedApplicationControlPtr providerMgr = priv->getObject();
+        ApplicationConverterFactory::ConverterType converter =
+                ApplicationConverterFactory::getConverter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_APPLICATION_CONTROL)) {
+            return converter->toJSValueRef(providerMgr->getAppControl());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_CALLER_APP_ID)) {
+            return converter->toJSValueRef(providerMgr->getCallerAppId());
+        }
+    } catch (...) {
+        LOGE("Exception occured while get property");
+        return JSValueMakeUndefined(context);
+    }
+
+    /* do not return undefined object to find method */
+    return NULL;
+}
+
+
+JSValueRef JSRequestedApplicationControl::replyResult(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    JSRequestedApplicationControlPriv *priv =
+            static_cast<JSRequestedApplicationControlPriv*>(JSObjectGetPrivate(thisObject));
+
+    try {
+        if (!priv) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef dataArrayObj = validator.toArrayObject(0, true);
+        std::vector<ApplicationControlDataPtr> dataArray;
+        if (dataArrayObj) {
+            ApplicationConverterFactory::ConverterType converter =
+                    ApplicationConverterFactory::getConverter(context);
+            dataArray = converter->toApplicationControlDataArray(arguments[0]);
+        }
+        RequestedApplicationControlPtr providerMgr = priv->getObject();
+        providerMgr->replyResult(dataArray);
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+    return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch(const ConversionException& err) {
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "");
+    } catch (const NotFoundException& ex) {
+       return JSWebAPIErrorFactory::postException(context, exception,
+               JSWebAPIErrorFactory::NOT_FOUND_ERROR, ex.GetMessage());
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in RequestedApplicationControl.replyResult().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSRequestedApplicationControl::replyFailure(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    JSRequestedApplicationControlPriv *priv =
+            static_cast<JSRequestedApplicationControlPriv*>(JSObjectGetPrivate(thisObject));
+
+    try {
+        if (!priv) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        RequestedApplicationControlPtr providerMgr = priv->getObject();
+        providerMgr->replyFailure();
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+
+    return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const NotFoundException& ex) {
+       return JSWebAPIErrorFactory::postException(context, exception,
+               JSWebAPIErrorFactory::NOT_FOUND_ERROR, ex.GetMessage());
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error in RequestedApplicationControl.replyFailure().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+}
+}
diff --git a/src/Application/JSRequestedApplicationControl.h b/src/Application/JSRequestedApplicationControl.h
new file mode 100644 (file)
index 0000000..3fb0b6f
--- /dev/null
@@ -0,0 +1,133 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_TIZEN_JS_REQUESTED_APPLICATION_CONTROL_H_
+#define TIZENAPIS_TIZEN_JS_REQUESTED_APPLICATION_CONTROL_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "ApplicationControl.h"
+#include "RequestedApplicationControl.h"
+#include "JSApplicationControl.h"
+#include "JSApplicationControlData.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+#define TIZEN_INTERFACE_REQUESTED_APPLICATION_CONTROL "RequestedApplicationControl"
+#define TIZEN_APPLICATION_CONTROL "appControl"
+#define TIZEN_CALLER_APP_ID "callerAppId"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObjectT<RequestedApplicationControlPtr>::Type JSRequestedApplicationControlPriv;
+
+class JSRequestedApplicationControl {
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    /**
+      * create an JSObject for callback function(onAnswerReceived).
+      */
+    static JSObjectRef createJSObject(JSContextRef context,
+               const RequestedApplicationControlPtr &appsvc);
+
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+    /**
+     * Send Success Result
+     */
+    static JSValueRef replyResult(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Send Failure Result
+     */
+    static JSValueRef replyFailure(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static RequestedApplicationControlPtr getRequestedApplicationControl(JSContextRef context,
+            JSValueRef value);
+
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+   /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static RequestedApplicationControlPtr getPrivData(JSObjectRef object);
+
+
+  /**
+     * The callback invoked when getting a property's value.
+     */
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+  /**
+     * The callback invoked when setting a property's value.
+     */
+
+    static bool setProperty(JSContextRef context,
+          JSObjectRef object,
+          JSStringRef propertyName,
+          JSValueRef value,
+          JSValueRef* exception);
+
+
+  /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+  /**
+     * This structure describes a statically declared value property.
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //
+} //TizenApis
+
+#endif
diff --git a/src/Application/RequestedApplicationControl.cpp b/src/Application/RequestedApplicationControl.cpp
new file mode 100755 (executable)
index 0000000..488cc16
--- /dev/null
@@ -0,0 +1,198 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/Exception.h>
+#include <app_control.h>
+#include <app_manager.h>
+#include <TimeTracer.h>
+#include <Logger.h>
+
+#include "RequestedApplicationControl.h"
+#include "ApplicationUtil.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+using namespace WrtDeviceApis::Commons;
+
+RequestedApplicationControl::RequestedApplicationControl() :
+    m_appControl(static_cast<ApplicationControl*>(NULL)),
+    m_appService(NULL)
+{
+    LOGD("Entered");
+}
+
+
+RequestedApplicationControl::~RequestedApplicationControl()
+{
+    LOGD("Entered");
+}
+
+ApplicationControlPtr RequestedApplicationControl::getAppControl() const
+{
+    LOGD("Entered");
+    return m_appControl;
+}
+
+// TODO: Should I add & or not?
+void RequestedApplicationControl::setAppControl(ApplicationControlPtr &appControl)
+{
+    LOGD("Entered");
+    m_appControl = appControl;
+}
+
+std::string RequestedApplicationControl::getCallerAppId() const
+{
+    LOGD("Entered");
+    return m_callerAppId;
+}
+
+void RequestedApplicationControl::setCallerAppId(const std::string &id)
+{
+    LOGD("Entered");
+    m_callerAppId = id;
+}
+
+void RequestedApplicationControl::replyResult(
+        std::vector<ApplicationControlDataPtr> &appControlDataArray)
+{
+    LOGD("Entered");
+    app_control_h reply;
+    int ret = app_control_create(&reply);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_create()",
+                ApplicationUtil::getApplicationMessage).c_str());
+    }
+
+    if (!appControlDataArray.empty())
+    {
+        const char** arr = NULL;
+
+        LOGD("appControlDataArray.size() : %u", appControlDataArray.size());
+        for (size_t i = 0; i < appControlDataArray.size(); ++i) {
+            std::vector<std::string> valueArray = appControlDataArray.at(i)->getValue();
+
+            arr = (const char**) calloc (sizeof(char*), valueArray.size());
+
+            if (arr != NULL) {
+                for (size_t j = 0; j < valueArray.size(); j++) {
+                    arr[j] = valueArray.at(j).c_str();
+                }
+            }
+            ret = app_control_add_extra_data_array(reply,
+                    appControlDataArray.at(i)->getKey().c_str(), arr, valueArray.size());
+            if (APP_CONTROL_ERROR_NONE != ret) {
+                LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                        "app_control_add_extra_data_array()",
+                        ApplicationUtil::getApplicationMessage).c_str());
+            }
+            if (arr) {
+                free (arr);
+            }
+        }
+    } else {
+        LOGE("[replyResult] appControlDataArray is empty");
+    }
+
+    // temporal code to check caller liveness
+    if (m_callerAppId.empty()) {
+        LOGE("m_callerAppId is empty. means caller is dead");
+        ThrowMsg(NotFoundException, "Cannot find caller");
+    } else {
+        bool running = false;
+        TIME_TRACER_ITEM_BEGIN("(replyResult)app_manager_is_running", 0);
+        ret = app_manager_is_running(m_callerAppId.c_str(), &running);
+        TIME_TRACER_ITEM_END("(replyResult)app_manager_is_running", 0);
+        if ((APP_MANAGER_ERROR_NONE != ret) || !running) {
+            LOGE("ret: %d", ret);
+            ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                    "app_manager_is_running()",
+                    ApplicationUtil::getApplicationManagerMessage);
+        }
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(replyResult)app_control_reply_to_launch_request", 0);
+    ret = app_control_reply_to_launch_request(reply,
+            m_appControl->getService_h(),
+            APP_CONTROL_RESULT_SUCCEEDED);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                "app_control_reply_to_launch_request()",
+                ApplicationUtil::getApplicationMessage);
+    }
+    TIME_TRACER_ITEM_END("(replyResult)app_control_reply_to_launch_request", 0);
+
+    ret = app_control_destroy(reply);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_destroy()",
+                ApplicationUtil::getApplicationMessage).c_str());
+    }
+}
+
+void RequestedApplicationControl::replyFailure()
+{
+    LOGD("Entered");
+    app_control_h reply;
+    int ret = app_control_create(&reply);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_create()",
+                ApplicationUtil::getApplicationMessage).c_str());
+    }
+
+    // temporal code to check caller liveness
+    if (m_callerAppId.empty()) {
+        LOGE("m_callerAppId is empty. means caller is dead");
+        ThrowMsg(NotFoundException, "Cannot find caller");
+    } else {
+        bool running = false;
+        TIME_TRACER_ITEM_BEGIN("(replyFailure)app_manager_is_running", 0);
+        int ret = app_manager_is_running(m_callerAppId.c_str(), &running);
+        TIME_TRACER_ITEM_END("(replyFailure)app_manager_is_running", 0);
+        if ((APP_MANAGER_ERROR_NONE != ret) || !running) {
+            LOGE("ret: %d", ret);
+            ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                    "app_manager_is_running()",
+                    ApplicationUtil::getApplicationManagerMessage);
+        }
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(replyFailure)app_control_reply_to_launch_request", 0);
+    ret = app_control_reply_to_launch_request(reply,
+            m_appControl->getService_h(),
+            APP_CONTROL_RESULT_FAILED);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ApplicationUtil::throwApplicationException<NotFoundException>(ret,
+                "app_control_reply_to_launch_request()",
+                ApplicationUtil::getApplicationMessage);
+    }
+    TIME_TRACER_ITEM_END("(replyFailure)app_control_reply_to_launch_request", 0);
+
+    ret = app_control_destroy(reply);
+    if (APP_CONTROL_ERROR_NONE != ret) {
+        LOGW("%s", ApplicationUtil::getApplicationErrorMessage(ret,
+                "app_control_destroy()",
+                ApplicationUtil::getApplicationMessage).c_str());
+    }
+}
+
+}
+}
diff --git a/src/Application/RequestedApplicationControl.h b/src/Application/RequestedApplicationControl.h
new file mode 100644 (file)
index 0000000..ea6c90b
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_API_REQUESTED_APPLICATION_CONTROL_H_
+#define TIZENAPIS_API_REQUESTED_APPLICATION_CONTROL_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include "ApplicationControl.h"
+#include "ApplicationControlData.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+class RequestedApplicationControl;
+typedef std::shared_ptr<RequestedApplicationControl> RequestedApplicationControlPtr;
+
+/* This object represents a single extra data for service request and reply */
+class RequestedApplicationControl
+{
+  public:
+    RequestedApplicationControl();
+    ~RequestedApplicationControl();
+
+    ApplicationControlPtr getAppControl() const;
+    void setAppControl(ApplicationControlPtr &appControl);
+
+    std::string getCallerAppId() const;
+    void setCallerAppId(const std::string &id);
+
+    void replyResult(std::vector<ApplicationControlDataPtr> &appControlDataArray);
+    void replyFailure();
+
+  private:
+    ApplicationControlPtr m_appControl;
+    app_control_h m_appService;
+    std::string m_callerAppId;
+};
+}
+}
+#endif
+
diff --git a/src/Application/config.xml b/src/Application/config.xml
new file mode 100755 (executable)
index 0000000..417d24c
--- /dev/null
@@ -0,0 +1,37 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+       <library-name>libwrt-plugins-tizen-application.so</library-name>
+       <feature-install-uri>application.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/application.launch</name>
+        <device-capability>application.launch</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/application.kill</name>
+        <device-capability>appmanager.kill</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/appmanager.kill</name>
+        <device-capability>appmanager.kill</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/appmanager.certificate</name>
+        <device-capability>appmanager.certificate</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/application.read</name>
+        <device-capability>appmanager.certificate</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/application.info</name>
+        <device-capability>application.info</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/Application/plugin_config.cpp b/src/Application/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..d20dc1e
--- /dev/null
@@ -0,0 +1,323 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <iostream>
+#include <Commons/Exception.h>
+#include <dpl/exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define APPLICATION_FEATURE_API_LAUNCH  "http://tizen.org/privilege/application.launch"
+#define APPLICATION_FEATURE_API_KILL    "http://tizen.org/privilege/application.kill"
+#define APPLICATION_FEATURE_API_KILL2   "http://tizen.org/privilege/appmanager.kill"
+#define APPLICATION_FEATURE_API_CERT    "http://tizen.org/privilege/appmanager.certificate"
+#define APPLICATION_FEATURE_API_INFO        "http://tizen.org/privilege/application.info"
+
+
+// for backword compatibility
+#define APPLICATION_FEATURE_API_READ    "http://tizen.org/privilege/application.read"
+//#define APPLICATION_FEATURE_API_INSTALL   "http://tizen.org/privilege/application.install"
+
+#define APPLICATION_DEVICE_CAP_LAUNCH   "application.launch"
+#define APPLICATION_DEVICE_CAP_KILL     "appmanager.kill"
+#define APPLICATION_DEVICE_CAP_CERT     "appmanager.certificate"
+#define APPLICATION_DEVICE_CAP_INFO     "application.info"
+
+//#define APPLICATION_DEVICE_CAP_READ       "application.read"
+//#define APPLICATION_DEVICE_CAP_INSTALL    "application.install"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Application {
+
+static FunctionMapping createApplicationFunctions();
+
+static FunctionMapping ApplicationFunctions =
+    createApplicationFunctions();
+
+DEFINE_FUNCTION_GETTER(Application, ApplicationFunctions);
+
+static FunctionMapping createApplicationFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_APPLICATION_LAUNCH, APPLICATION_DEVICE_CAP_LAUNCH);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_APPLICATION_KILL, APPLICATION_DEVICE_CAP_KILL);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_APPLICATION_CERT, APPLICATION_DEVICE_CAP_CERT);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_APPLICATION_INFO, APPLICATION_DEVICE_CAP_INFO);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_APPLICATION_LAUNCH);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_APPLICATION_KILL);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_APPLICATION_CERT);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_APPLICATION_INFO);
+
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_APPLICATION_LAUNCH, DEVICE_CAP_APPLICATION_LAUNCH);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_APPLICATION_KILL, DEVICE_CAP_APPLICATION_KILL);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_APPLICATION_CERT, DEVICE_CAP_APPLICATION_CERT);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_APPLICATION_INFO, DEVICE_CAP_APPLICATION_INFO);
+
+#if 0
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_APPLICATION_READ, APPLICATION_DEVICE_CAP_READ);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_APPLICATION_INSTALL, APPLICATION_DEVICE_CAP_INSTALL);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_APPLICATION_READ);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_APPLICATION_INSTALL);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_APPLICATION_READ, DEVICE_CAP_APPLICATION_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_APPLICATION_INSTALL, DEVICE_CAP_APPLICATION_INSTALL);
+#endif
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_APPLICATION_LAUNCH, APPLICATION_FEATURE_API_LAUNCH);
+    ACE_CREATE_FEATURE(FEATURE_APPLICATION_KILL, APPLICATION_FEATURE_API_KILL);
+    ACE_CREATE_FEATURE(FEATURE_APPLICATION_KILL2, APPLICATION_FEATURE_API_KILL2);
+    ACE_CREATE_FEATURE(FEATURE_APPLICATION_CERT, APPLICATION_FEATURE_API_CERT);
+    ACE_CREATE_FEATURE(FEATURE_APPLICATION_READ, APPLICATION_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_APPLICATION_INFO, APPLICATION_FEATURE_API_INFO);
+
+
+    ACE_CREATE_FEATURE_LIST(APPLICATION_FEATURES_APPLICATION_LAUNCH);
+    ACE_ADD_API_FEATURE(APPLICATION_FEATURES_APPLICATION_LAUNCH, FEATURE_APPLICATION_LAUNCH);
+
+    ACE_CREATE_FEATURE_LIST(APPLICATION_FEATURES_APPLICATION_KILL);
+    ACE_ADD_API_FEATURE(APPLICATION_FEATURES_APPLICATION_KILL, FEATURE_APPLICATION_KILL);
+    ACE_ADD_API_FEATURE(APPLICATION_FEATURES_APPLICATION_KILL, FEATURE_APPLICATION_KILL2);
+
+    ACE_CREATE_FEATURE_LIST(APPLICATION_FEATURES_APPLICATION_CERT);
+    ACE_ADD_API_FEATURE(APPLICATION_FEATURES_APPLICATION_CERT, FEATURE_APPLICATION_CERT);
+    ACE_ADD_API_FEATURE(APPLICATION_FEATURES_APPLICATION_CERT, FEATURE_APPLICATION_READ);
+
+    ACE_CREATE_FEATURE_LIST(APPLICATION_FEATURES_APPLICATION_INFO);
+    ACE_ADD_API_FEATURE(APPLICATION_FEATURES_APPLICATION_INFO, FEATURE_APPLICATION_INFO);
+
+
+#if 0
+    ACE_CREATE_FEATURE(FEATURE_APPLICATION_READ, APPLICATION_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_APPLICATION_INSTALL, APPLICATION_FEATURE_API_INSTALL);
+
+    ACE_CREATE_FEATURE_LIST(APPLICATION_FEATURES_APPLICATION_READ);
+    ACE_ADD_API_FEATURE(APPLICATION_FEATURES_APPLICATION_READ, FEATURE_APPLICATION_READ);
+
+    ACE_CREATE_FEATURE_LIST(APPLICATION_FEATURES_APPLICATION_INSTALL);
+    ACE_ADD_API_FEATURE(APPLICATION_FEATURES_APPLICATION_INSTALL, FEATURE_APPLICATION_INSTALL);
+#endif
+
+    /**
+     * Functions
+     */
+    FunctionMapping applicationMapping;
+
+    // launch
+    AceFunction launchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_LAUNCH,
+            APPLICATION_FUNCTION_API_LAUNCH,
+            APPLICATION_FEATURES_APPLICATION_LAUNCH,
+            DEVICE_LIST_APPLICATION_LAUNCH);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_LAUNCH,
+                               launchFunc));
+
+    // launchAppControl
+    AceFunction launchAppControlFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_LAUNCH_APP_CONTROL,
+            APPLICATION_FUNCTION_API_LAUNCH_APP_CONTROL,
+            APPLICATION_FEATURES_APPLICATION_LAUNCH,
+            DEVICE_LIST_APPLICATION_LAUNCH);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_LAUNCH_APP_CONTROL,
+                               launchAppControlFunc));
+
+    // kill
+    AceFunction killFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_KILL,
+            APPLICATION_FUNCTION_API_KILL,
+            APPLICATION_FEATURES_APPLICATION_KILL,
+            DEVICE_LIST_APPLICATION_KILL);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_KILL,
+                               killFunc));
+
+
+    // getAppCerts
+    AceFunction getAppCertsFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_APP_CERTS,
+            APPLICATION_FUNCTION_API_GET_APP_CERTS,
+            APPLICATION_FEATURES_APPLICATION_CERT,
+            DEVICE_LIST_APPLICATION_CERT);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_GET_APP_CERTS,
+                               getAppCertsFunc));
+
+        // getAppMetaData
+        AceFunction getAppMetaDataFunc = ACE_CREATE_FUNCTION(
+                FUNCTION_GET_APP_META_DATA,
+                APPLICATION_FUNCTION_API_GET_APP_META_DATA,
+                APPLICATION_FEATURES_APPLICATION_INFO,
+                DEVICE_LIST_APPLICATION_INFO);
+
+        applicationMapping.insert(std::make_pair(
+                                   APPLICATION_FUNCTION_API_GET_APP_META_DATA,
+                                   getAppMetaDataFunc));
+
+#if 0
+
+    // setUserAgent
+    AceFunction setUserAgentFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_USER_AGENT,
+            APPLICATION_FUNCTION_API_SET_USER_AGENT,
+            APPLICATION_FEATURES_APPLICATION_READ,
+            EMPTY_DEVICE_LIST);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_SET_USER_AGENT,
+                               setUserAgentFunc));
+
+    // getAppsInfo
+    AceFunction getAppsInfoFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_APPLICATION_INFORMATIONS,
+            APPLICATION_FUNCTION_API_GET_APPS_INFO,
+            APPLICATION_FEATURES_APPLICATION_READ,
+            DEVICE_LIST_APPLICATION_READ);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_GET_APPS_INFO,
+                               getAppsInfoFunc));
+
+    // getAppInfo
+    AceFunction getAppInfoFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_APPLICATION_INFORMATION,
+            APPLICATION_FUNCTION_API_GET_APP_INFO,
+            APPLICATION_FEATURES_APPLICATION_READ,
+            DEVICE_LIST_APPLICATION_READ);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_GET_APP_INFO,
+                               getAppInfoFunc));
+
+    // getAppsContext
+    AceFunction getAppsContextFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_RUNNING_APPLICATION_CONTEXTS,
+            APPLICATION_FUNCTION_API_GET_APPS_CONTEXT,
+            APPLICATION_FEATURES_APPLICATION_READ,
+            DEVICE_LIST_APPLICATION_READ);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_GET_APPS_CONTEXT,
+                               getAppsContextFunc));
+
+    // getAppContext
+    AceFunction getAppContextFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_CURRENT_APPLICATION_CONTEXT,
+            APPLICATION_FUNCTION_API_GET_APP_CONTEXT,
+            APPLICATION_FEATURES_APPLICATION_READ,
+            DEVICE_LIST_APPLICATION_READ);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_GET_APP_CONTEXT,
+                               getAppContextFunc));
+
+    // getAppsContext
+    AceFunction findAppControlFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_RUNNING_APPLICATION_CONTEXTS,
+            APPLICATION_FUNCTION_API_FIND_APP_CONTROL,
+            APPLICATION_FEATURES_APPLICATION_READ,
+            DEVICE_LIST_APPLICATION_READ);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_FIND_APP_CONTROL,
+                               findAppControlFunc));
+
+    // addAppInfoEventListener
+    AceFunction addAppInfoEventListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD_APPLICATION_INFORMATION_EVENT_LISTENER,
+            APPLICATION_FUNCTION_API_ADD_APP_INFO_EVENT_LISTENER,
+            APPLICATION_FEATURES_APPLICATION_READ,
+            DEVICE_LIST_APPLICATION_READ);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_ADD_APP_INFO_EVENT_LISTENER,
+                               addAppInfoEventListenerFunc));
+
+    // removeAppInfoEventListener
+    AceFunction removeAppInfoEventListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_APPLICATION_INFORMATION_EVENT_LISTENER,
+            APPLICATION_FUNCTION_API_REMOVE_APP_INFO_EVENT_LISTENER,
+            APPLICATION_FEATURES_APPLICATION_READ,
+            DEVICE_LIST_APPLICATION_READ);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_REMOVE_APP_INFO_EVENT_LISTENER,
+                               removeAppInfoEventListenerFunc));
+
+    // install
+    AceFunction installFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_INSTALL_APP,
+            APPLICATION_FUNCTION_API_INSTALL_APP,
+            APPLICATION_FEATURES_APPLICATION_INSTALL,
+            DEVICE_LIST_APPLICATION_INSTALL);
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_INSTALL_APP,
+                               installFunc));
+
+    // uninstall
+    AceFunction uninstallFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UNINSTALL_APP,
+            APPLICATION_FUNCTION_API_UNINSTALL_APP,
+            APPLICATION_FEATURES_APPLICATION_INSTALL,
+            DEVICE_LIST_APPLICATION_INSTALL);
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_UNINSTALL_APP,
+                               uninstallFunc));
+
+    // update
+    AceFunction updateFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UPDATE_APP,
+            APPLICATION_FUNCTION_API_UPDATE_APP,
+            APPLICATION_FEATURES_APPLICATION_INSTALL,
+            DEVICE_LIST_APPLICATION_INSTALL);
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_UPDATE_APP,
+                               updateFunc));
+#endif
+    // size
+    AceFunction sizeAttr = ACE_CREATE_FUNCTION(
+            ATTRIBUTE_SIZE,
+            APPLICATION_FUNCTION_API_SIZE,
+            APPLICATION_FEATURES_APPLICATION_INFO,
+            DEVICE_LIST_APPLICATION_INFO);
+
+    applicationMapping.insert(std::make_pair(
+                               APPLICATION_FUNCTION_API_SIZE,
+                               sizeAttr));
+
+    return applicationMapping;
+}
+
+}
+}
diff --git a/src/Application/plugin_config.h b/src/Application/plugin_config.h
new file mode 100755 (executable)
index 0000000..fa36426
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _APPLICATOIN_PLUGIN_CONFIG_H_
+#define _APPLICATOIN_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Application {
+
+DECLARE_FUNCTION_GETTER(Application);
+
+#define APPLICATION_CHECK_ACCESS(functionName)                     \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(     \
+        getApplicationFunctionData,                                \
+        functionName)
+
+}
+}
+#endif
+
diff --git a/src/Application/plugin_config_impl.h b/src/Application/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..8ff2b00
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _APPLICATOIN_PLUGIN_CONFIG_IMPL_H_
+#define _APPLICATOIN_PLUGIN_CONFIG_IMPL_H_
+
+// feature : launch
+#define APPLICATION_FUNCTION_API_LAUNCH                         "launch"
+#define APPLICATION_FUNCTION_API_LAUNCH_APP_CONTROL             "launchAppControl"
+
+// feature : kill - public candidate
+#define APPLICATION_FUNCTION_API_KILL                           "kill"
+
+// feature : certificate - public candidate
+#define APPLICATION_FUNCTION_API_GET_APP_CERTS                  "getAppCerts"
+
+// no feature required
+#define APPLICATION_FUNCTION_API_GET_APPS_INFO                  "getAppsInfo"
+#define APPLICATION_FUNCTION_API_GET_APP_INFO                   "getAppInfo"
+#define APPLICATION_FUNCTION_API_GET_APPS_CONTEXT               "getAppsContext"
+#define APPLICATION_FUNCTION_API_GET_APP_CONTEXT                "getAppContext"
+#define APPLICATION_FUNCTION_API_FIND_APP_CONTROL               "findAppControl"
+#define APPLICATION_FUNCTION_API_ADD_APP_INFO_EVENT_LISTENER    "addAppInfoEventListener"
+#define APPLICATION_FUNCTION_API_REMOVE_APP_INFO_EVENT_LISTENER "removeAppInfoEventListener"
+#define APPLICATION_FUNCTION_API_GET_CURRENT_APP                "getCurrentApplication"
+#define APPLICATION_FUNCTION_API_GET_REQUESTED_APP_CONTROL      "getRequestedAppControl"
+#define APPLICATION_FUNCTION_API_EXIT                           "exit"
+#define APPLICATION_FUNCTION_API_HIDE                           "hide"
+#define APPLICATION_FUNCTION_API_REPLY_RESULT                   "replyResult"
+#define APPLICATION_FUNCTION_API_REPLY_FAILURE                  "replyFailure"
+#define APPLICATION_FUNCTION_API_GET_APP_SHARED_URI             "getAppSharedURI"
+#define APPLICATION_FUNCTION_API_GET_APP_META_DATA              "getAppMetaData"
+#define APPLICATION_FUNCTION_API_SET_USER_AGENT                 "setUserAgent"
+#define APPLICATION_FUNCTION_API_SIZE                           "size"
+
+#endif
+
diff --git a/src/Application/plugin_initializer.cpp b/src/Application/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..d349882
--- /dev/null
@@ -0,0 +1,142 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <dpl/string.h>
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <TimeTracer.h>
+#include <Security.h>
+
+#include "JSApplicationManager.h"
+#include "JSApplicationControl.h"
+#include "ApplicationAsyncCallbackManager.h"
+#include "ApplicationListenerManager.h"
+#include "AppManagerWrapper.h"
+#include "plugin_config.h"
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Application {
+
+AceSecurityStatus applicationAceCheckAccessFunction(const char* functionName)
+{
+    return APPLICATION_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerApplicationSetter, ApplicationController, gSecurityAccessor);
+
+class_definition_options_t ApplicationOptions =
+{
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerApplicationSetter,
+    NULL,
+    NULL
+};
+
+class_definition_options_t ApplicationConstructorOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId) {
+    LOGD("[Tizen1_0\\Application] on_widget_start_callback (%d)", widgetId);
+    Try {
+        TIME_TRACER_INIT();
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } Catch(WrtDeviceApis::Commons::Exception) {
+        LOGE("WrtAccess initialization failed");
+    }
+
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, applicationAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId) {
+    LOGD("[Tizen1_0\\Application] on_widget_stop_callback (%d)", widgetId);
+    Try {
+        char buf[30];
+        sprintf(buf,"Application.%d",getpid());
+        TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,buf);
+        TIME_TRACER_RELEASE();
+       WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } Catch(WrtDeviceApis::Commons::Exception) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\application] on_frame_load_callback (%p)", context);
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\application] on_frame_unload_callback (%p)", context);
+
+    DeviceAPI::Application::ApplicationAsyncCallbackManagerSingleton::Instance().unregisterContext(static_cast<JSContextRef>(context));
+    DeviceAPI::Application::ApplicationListenerManagerSingleton::Instance().unregisterContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+    PLUGIN_CLASS_MAP_ADD_CLASS(
+        WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "application",
+        (js_class_template_getter)DeviceAPI::Application::JSApplicationManager::getClassRef,
+        &ApplicationOptions)
+
+    PLUGIN_CLASS_MAP_ADD_INTERFACE(
+        WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_INTERFACE_APPLICATION_CONTROL,
+        (js_class_template_getter)DeviceAPI::Application::JSApplicationControl::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSApplicationControl::constructor),
+        &ApplicationConstructorOptions)
+
+    PLUGIN_CLASS_MAP_ADD_INTERFACE(
+        WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_INTERFACE_APPLICATION_CONTROL_DATA,
+        (js_class_template_getter)DeviceAPI::Application::JSApplicationControlData::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSApplicationControlData::constructor),
+        &ApplicationConstructorOptions)
+
+PLUGIN_CLASS_MAP_END
+
+} //Application
+} //DeviceAPI
+
diff --git a/src/Archive/ArchiveCallbackData.cpp b/src/Archive/ArchiveCallbackData.cpp
new file mode 100755 (executable)
index 0000000..ee96226
--- /dev/null
@@ -0,0 +1,804 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ArchiveCallbackData.cpp
+ */
+
+#include <Logger.h>
+#include "ArchiveCallbackData.h"
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Path.h>
+#include <FilesystemExternalUtils.h>
+#include "ArchiveFile.h"
+#include "JSArchiveFileEntry.h"
+#include "ArchiveUtils.h"
+#include "JSArchiveFileEntry.h"
+#include "UnZip.h"
+#include "Zip.h"
+#include "Path.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+using namespace DeviceAPI::Common;
+
+namespace {
+const char* CALLBACK_SUCCESS = "success";
+const char* CALLBACK_ERROR = "error";
+const char* CALLBACK_PROGRESS = "progress";
+} //anonymous namespace
+
+//----------------------------------------------------------------------------------------
+//OperationCallbackData
+//----------------------------------------------------------------------------------------
+
+OperationCallbackData::OperationCallbackData(JSContextRef globalCtx,
+        ArchiveCallbackType callback_type) :
+    MultiCallbackUserData(globalCtx),
+    m_callback_type(callback_type),
+    m_op_id(0),
+    m_is_error(false),
+    m_is_canceled(false)
+{
+    LOGD("Entered");
+}
+
+OperationCallbackData::~OperationCallbackData()
+{
+    LOGD("Entered");
+    if(m_op_id > 0){
+        ArchiveManager::getInstance().eraseElementFromArchiveFileMap(m_op_id);
+    }
+}
+
+void OperationCallbackData::setError(const std::string &err_name,
+        const std::string &err_message)
+{
+    LOGD("Entered");
+    //store only first error
+    if (!m_is_error) {
+        m_err_name = err_name;
+        m_err_message = err_message;
+        m_is_error = true;
+    }
+}
+
+bool OperationCallbackData::isError() const
+{
+    LOGD("Entered");
+    return m_is_error;
+}
+
+bool OperationCallbackData::isCanceled() const
+{
+    return m_is_canceled;
+}
+
+void OperationCallbackData::setOperationId(long op_id)
+{
+    LOGD("Entered");
+    m_op_id = op_id;
+}
+
+long OperationCallbackData::getOperationId() const
+{
+    LOGD("Entered");
+    return m_op_id;
+}
+
+void OperationCallbackData::setIsCanceled(bool canceled)
+{
+    m_is_canceled = canceled;
+}
+
+const std::string& OperationCallbackData::getErrorName() const
+{
+    LOGD("Entered");
+    return m_err_name;
+}
+
+const std::string& OperationCallbackData::getErrorMessage() const
+{
+    LOGD("Entered");
+    return m_err_message;
+}
+
+ArchiveCallbackType OperationCallbackData::getCallbackType() const
+{
+    LOGD("Entered");
+    return m_callback_type;
+}
+
+ArchiveFilePtr OperationCallbackData::getArchiveFile() const
+{
+    return m_caller_instance;
+}
+
+void OperationCallbackData::setArchiveFile(ArchiveFilePtr caller)
+{
+    m_caller_instance = caller;
+}
+
+void OperationCallbackData::setSuccessCallback(JSValueRef on_success)
+{
+    LOGD("Entered");
+    auto ctx = getContext();
+    if(on_success && JSValueIsObject(ctx, on_success)) {
+        JSObjectRef success = JSValueToObject(ctx, on_success, NULL);
+        this->setCallback(CALLBACK_SUCCESS, success);
+    }
+}
+
+void OperationCallbackData::setErrorCallback(JSValueRef on_error)
+{
+    LOGD("Entered");
+    auto ctx = getContext();
+    if(on_error && JSValueIsObject(ctx, on_error)) {
+        JSObjectRef error = JSValueToObject(ctx, on_error, NULL);
+        this->setCallback(CALLBACK_ERROR, error);
+    }
+}
+
+void OperationCallbackData::callSuccessCallback()
+{
+    LOGD("Entered");
+    this->invokeCallback(CALLBACK_SUCCESS, 0, NULL);
+}
+
+void OperationCallbackData::callSuccessCallback(JSValueRef success)
+{
+    LOGD("Entered");
+    this->invokeCallback(CALLBACK_SUCCESS, success);
+}
+
+void OperationCallbackData::callErrorCallback(JSValueRef err)
+{
+    LOGD("Entered");
+    this->invokeCallback(CALLBACK_ERROR, err);
+}
+
+//----------------------------------------------------------------------------------------
+//OpenCallbackData
+//----------------------------------------------------------------------------------------
+
+OpenCallbackData::OpenCallbackData(JSContextRef globalCtx,
+        ArchiveCallbackType callback_type):
+    OperationCallbackData(globalCtx, callback_type)
+{
+    LOGD("Entered");
+}
+
+OpenCallbackData::~OpenCallbackData()
+{
+    LOGD("Entered");
+}
+
+void OpenCallbackData::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LOGE("Entered");
+
+    Filesystem::FilePtr file = archive_file_ptr->getFile();
+    if (!file) {
+        LOGE("File is null");
+        throw UnknownException("File is null");
+    }
+    Filesystem::NodePtr node = file->getNode();
+    if(!node) {
+        LOGE("Node is null");
+        throw UnknownException("Node is null");
+    }
+    const FileMode fm = archive_file_ptr->m_file_mode;
+    if (0 == node->getSize()) {
+        if(FileMode::READ_WRITE == fm ||
+                FileMode::WRITE == fm ||
+                FileMode::ADD == fm) {
+            LOGD("Empty file obtained for writing/appending");
+
+            // Do not create empty archive with minizip library - it will not be loaded
+            // by unzip.
+            //
+            // For explanation please see:
+            //    ArchiveFile.h m_created_as_new_empty_archive description
+            //
+            archive_file_ptr->setCreatedAsNewEmptyArchive(true);
+            archive_file_ptr->setEntryMap(ArchiveFileEntryPtrMapPtr(
+                    new ArchiveFileEntryPtrMap()));
+            archive_file_ptr->setIsOpen(true);
+        }
+        else {
+            LOGE("The file is empty throwing: InvalidValuesException - Invalid ZIP archive");
+            throw InvalidValuesException("Invalid ZIP archive");
+        }
+    }
+    else {
+        archive_file_ptr->setIsOpen(true);
+        archive_file_ptr->updateListOfEntries();
+    }
+
+    guint id = g_idle_add(ArchiveFile::openTaskCompleteCB, this);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        throw UnknownException("g_idle_add fails");
+    }
+}
+
+//----------------------------------------------------------------------------------------
+//GetEntriesCallbackData
+//----------------------------------------------------------------------------------------
+
+GetEntriesCallbackData::GetEntriesCallbackData(JSContextRef globalCtx,
+        ArchiveCallbackType callback_type):
+    OperationCallbackData(globalCtx, callback_type)
+{
+    LOGD("Entered");
+}
+GetEntriesCallbackData::~GetEntriesCallbackData()
+{
+    LOGD("Entered");
+}
+
+ArchiveFileEntryPtrMapPtr GetEntriesCallbackData::getEntries() const
+{
+    return m_entries;
+}
+
+void GetEntriesCallbackData::setEntries(ArchiveFileEntryPtrMapPtr entries)
+{
+    m_entries = entries;
+}
+
+void GetEntriesCallbackData::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LOGD("Entered");
+
+    setEntries(archive_file_ptr->getEntryMap());
+
+    guint id = g_idle_add(ArchiveFile::getEntriesTaskCompleteCB, this);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        throw UnknownException("g_idle_add fails");
+    }
+}
+
+//----------------------------------------------------------------------------------------
+//GetEntryByNameCallbackData
+//----------------------------------------------------------------------------------------
+
+GetEntryByNameCallbackData::GetEntryByNameCallbackData(JSContextRef globalCtx,
+        ArchiveCallbackType callback_type):
+    OperationCallbackData(globalCtx, callback_type)
+{
+    LOGD("Entered");
+}
+
+GetEntryByNameCallbackData::~GetEntryByNameCallbackData()
+{
+    LOGD("Entered");
+}
+
+const std::string& GetEntryByNameCallbackData::getName() const
+{
+    LOGD("Entered");
+    return m_name;
+}
+
+void GetEntryByNameCallbackData::setName(const std::string& name)
+{
+    LOGD("Entered");
+    m_name = name;
+}
+
+ArchiveFileEntryPtr GetEntryByNameCallbackData::getFileEntry() const
+{
+    return m_file_entry;
+}
+
+void GetEntryByNameCallbackData::setFileEntry(ArchiveFileEntryPtr entry)
+{
+    m_file_entry = entry;
+}
+
+void GetEntryByNameCallbackData::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LOGD("Entered");
+
+    ArchiveFileEntryPtrMapPtr entries = archive_file_ptr->getEntryMap();
+    auto it = entries->find(getName());
+
+    //Not found but if our name does not contain '/'
+    //try looking for directory with such name
+    //
+    if (it == entries->end() && !isDirectoryPath(getName())) {
+        const std::string try_directory = getName() + "/";
+        LOGD("GetEntryByName Trying directory: [%s]", try_directory.c_str());
+        it = entries->find(try_directory);
+    }
+
+    if (it == entries->end()) {
+        LOGE("GetEntryByName Entry with name: [%s] not found", getName().c_str());
+        LOGE("Throwing NotFoundException - Entry not found");
+        throw Common::NotFoundException("Entry not found");
+    }
+
+    setFileEntry(it->second);
+
+    guint id = g_idle_add(ArchiveFile::getEntryByNameTaskCompleteCB, this);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        throw UnknownException("g_idle_add fails");
+    }
+}
+
+//----------------------------------------------------------------------------------------
+//BaseProgressCallback
+//----------------------------------------------------------------------------------------
+
+BaseProgressCallback::BaseProgressCallback(JSContextRef globalCtx,
+        ArchiveCallbackType callback_type):
+    OperationCallbackData(globalCtx, callback_type),
+    m_overwrite(false)
+{
+    LOGD("Entered");
+}
+
+BaseProgressCallback::~BaseProgressCallback()
+{
+    LOGD("Entered");
+}
+
+bool BaseProgressCallback::getOverwrite() const
+{
+    LOGD("Entered");
+    return m_overwrite;
+}
+
+void BaseProgressCallback::setOverwrite(bool overwrite)
+{
+    LOGD("Entered");
+    m_overwrite = overwrite;
+}
+
+struct ProgressHolder
+{
+    ProgressHolder() :
+            callback(NULL)
+    {
+    };
+
+    double overall_progress;
+    ArchiveFileEntryPtr currently_processed_entry;
+    BaseProgressCallback* callback;
+};
+
+void BaseProgressCallback::callSuccessCallbackOnMainThread()
+{
+    guint id = g_idle_add(BaseProgressCallback::callSuccessCallbackCB,
+            static_cast<void*>(this));
+    if (!id) {
+        LOGE("g_idle_add fails - success callback will not be called");
+    }
+}
+
+gboolean BaseProgressCallback::callSuccessCallbackCB(void* data)
+{
+    BaseProgressCallback* callback = static_cast<BaseProgressCallback*>(data);
+    if (!callback) {
+        LOGE("callback pointer is NULL");
+        return false;
+    }
+
+    std::unique_ptr<BaseProgressCallback> cb_ptr(callback);
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context closed - unable to call success callback");
+        return false;
+    }
+
+    try {
+        callback->callSuccessCallback();
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    callback->setArchiveFile(ArchiveFilePtr());
+    ArchiveManager::getInstance().eraseElementFromArchiveFileMap(callback->m_op_id);
+
+    return false;
+}
+
+void BaseProgressCallback::setProgressCallback(JSValueRef on_progress)
+{
+    LOGD("Entered");
+    auto ctx = getContext();
+    if(on_progress && JSValueIsObject(ctx, on_progress)) {
+        JSObjectRef progress = JSValueToObject(ctx, on_progress, NULL);
+        this->setCallback(CALLBACK_PROGRESS, progress);
+    }
+}
+
+void BaseProgressCallback::callProgressCallback(long operationId,
+        double value,
+        const std::string& filename)
+{
+    LOGD("Entered");
+    auto ctx = getContext();
+    const int SIZE = 3;
+    JSValueRef parameters[SIZE] = {
+            JSUtil::toJSValueRef(ctx, operationId),
+            JSUtil::toJSValueRef(ctx, value),
+            JSUtil::toJSValueRef(ctx, filename)
+        };
+
+    this->invokeCallback(CALLBACK_PROGRESS, SIZE, parameters);
+}
+
+void BaseProgressCallback::callProgressCallbackOnMainThread(const double progress,
+        ArchiveFileEntryPtr current_entry)
+{
+    ProgressHolder* ph = new(std::nothrow) ProgressHolder();
+
+    if(ph) {
+        ph->overall_progress = progress;
+        ph->currently_processed_entry = current_entry;
+        ph->callback = this;
+
+        guint id = g_idle_add(BaseProgressCallback::callProgressCallbackCB,
+                static_cast<void*>(ph));
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete ph;
+            ph = NULL;
+        }
+    } else {
+        LOGE("Couldn't allocate ProgressHolder");
+    }
+}
+
+gboolean BaseProgressCallback::callProgressCallbackCB(void* data)
+{
+    ProgressHolder* ph = static_cast<ProgressHolder*>(data);
+    if (!ph) {
+        LOGE("ph is null");
+        return false;
+    }
+
+    std::unique_ptr<ProgressHolder> ph_ptr(ph);
+    if (!ph->callback) {
+        LOGE("ph->callback is null");
+        return false;
+    }
+
+    JSContextRef context = ph->callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        return false;
+    }
+    try {
+        //Error callback is being handled by ArchiveFile queue - see
+        //ArchiveFile::taskManagerThread function
+        //
+        ph->callback->callProgressCallback(
+                ph->callback->m_op_id,
+                ph->overall_progress,
+                ph->currently_processed_entry->getName());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    return false;
+}
+
+//----------------------------------------------------------------------------------------
+//AddProgressCallback
+//----------------------------------------------------------------------------------------
+
+AddProgressCallback::AddProgressCallback(JSContextRef globalCtx,
+        ArchiveCallbackType callback_type):
+    BaseProgressCallback(globalCtx, callback_type)
+{
+    LOGD("Entered");
+}
+
+AddProgressCallback::~AddProgressCallback()
+{
+    LOGD("Entered");
+}
+
+ArchiveFileEntryPtr AddProgressCallback::getFileEntry() const
+{
+    LOGD("Entered");
+    return m_file_entry;
+}
+
+void AddProgressCallback::setFileEntry(ArchiveFileEntryPtr file_entry)
+{
+    LOGD("Entered");
+    m_file_entry = file_entry;
+}
+
+void AddProgressCallback::setBasePath(const std::string& path)
+{
+    LOGD("Entered");
+    m_base_path = path;
+    m_base_virt_path = Filesystem::External::toVirtualPath(m_base_path);
+    std::string::size_type pos = m_base_virt_path.find(DeviceAPI::Filesystem::Path::getSeparator());
+    if (pos != std::string::npos)
+    {
+       m_base_virt_path = m_base_virt_path.substr(pos + 1);
+    } 
+    else
+    {
+        m_base_virt_path = "";
+    }
+}
+
+const std::string& AddProgressCallback::getBasePath()
+{
+    LOGD("Entered");
+    return m_base_path;
+}
+
+const std::string& AddProgressCallback::getBaseVirtualPath()
+{
+    LOGD("Entered");
+    return m_base_virt_path;
+}
+
+void AddProgressCallback::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LOGD("Entered");
+
+    if(!m_file_entry) {
+        LOGE("ArchiveFileEntry is not set in callback");
+        throw UnknownException("Could not add file to archive");
+    }
+
+    if(!archive_file_ptr) {
+        LOGE("archive_file_ptr is NULL");
+        throw UnknownException("Could not extract archive file entry");
+    }
+
+    AddProgressCallback* callback = this;
+
+    ZipPtr zip = archive_file_ptr->createZipObject();
+    zip->addFile(callback);
+    // Zip is no more needed but it locks file opening while
+    // it is needed to read entries from file
+    zip->close();
+
+    //We have just finished adding file to archive so now
+    //this archive file should be valid .zip archive and
+    //we can remove CreatedAsNewEmptyArchive flag
+    archive_file_ptr->setCreatedAsNewEmptyArchive(false);
+
+    LOGD("Update decompressed size and entry list");
+    // update informations about decompressed size and entry list
+    // TODO FIXME need to resolve problem with access to file by
+    // more than one thread
+    try{
+        archive_file_ptr->updateListOfEntries();
+    } catch(...){
+        LOGD("Unknown error during updating entries list inside archive");
+    }
+}
+
+//----------------------------------------------------------------------------------------
+//ExtractAllProgressCallback
+//----------------------------------------------------------------------------------------
+
+ExtractAllProgressCallback::ExtractAllProgressCallback(JSContextRef globalCtx,
+        ArchiveCallbackType callback_type):
+    BaseProgressCallback(globalCtx, callback_type),
+    m_files_to_extract(0),
+    m_files_extracted(0),
+    m_current_file_size(0),
+    m_current_file_extracted_bytes(0),
+    m_progress_overall(0),
+    m_overall_decompressed(0)
+{
+    LOGD("Entered");
+}
+
+ExtractAllProgressCallback::~ExtractAllProgressCallback()
+{
+    LOGD("Entered");
+}
+
+Filesystem::FilePtr ExtractAllProgressCallback::getDirectory() const
+{
+    return m_directory;
+}
+
+void ExtractAllProgressCallback::setDirectory(Filesystem::FilePtr directory)
+{
+    m_directory = directory;
+}
+
+void ExtractAllProgressCallback::startedExtractingFile(unsigned long current_file_size)
+{
+    m_current_file_size = current_file_size;
+    m_current_file_extracted_bytes = 0;
+}
+
+void ExtractAllProgressCallback::extractedPartOfFile(unsigned long bytes_decompressed)
+{
+    m_current_file_extracted_bytes += bytes_decompressed;
+    updateOverallProgress(bytes_decompressed);
+}
+
+void ExtractAllProgressCallback::finishedExtractingFile()
+{
+    m_current_file_size = 0;
+    m_current_file_extracted_bytes = 0;
+    ++m_files_extracted;
+    updateOverallProgress(0);
+}
+
+void ExtractAllProgressCallback::updateOverallProgress(unsigned long bytes_decompressed)
+{
+    m_overall_decompressed += bytes_decompressed;
+    m_progress_overall =
+            static_cast<double>(m_overall_decompressed + m_files_extracted) /
+            static_cast<double>(m_expected_decompressed_size + m_files_to_extract);
+
+    LOGD("%s of %s - %f%% (%d/%d files)",
+            bytesToReadableString(m_overall_decompressed).c_str(),
+            bytesToReadableString(m_expected_decompressed_size).c_str(),
+            m_progress_overall * 100.0,
+            m_files_extracted, m_files_to_extract);
+}
+
+double ExtractAllProgressCallback::getCurrentFileProgress() const
+{
+    if(m_current_file_size > 0) {
+        return static_cast<double>(m_current_file_extracted_bytes) /
+                static_cast<double>(m_current_file_size);
+    }
+    else {
+        return 1.0;
+    }
+}
+
+double ExtractAllProgressCallback::getOverallProgress() const
+{
+    return m_progress_overall;
+}
+
+void ExtractAllProgressCallback::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LOGD("Entered");
+    archive_file_ptr->extractAllTask(this);
+}
+
+void ExtractAllProgressCallback::setExpectedDecompressedSize(unsigned long exp_dec_size)
+{
+    m_expected_decompressed_size = exp_dec_size;
+}
+
+unsigned long ExtractAllProgressCallback::getExpectedDecompressedSize() const
+{
+    return m_expected_decompressed_size;
+}
+
+void ExtractAllProgressCallback::setNumberOfFilesToExtract(unsigned long files_count)
+{
+    m_files_to_extract = files_count;
+}
+
+unsigned long ExtractAllProgressCallback::getNumberOfFilesToExtract() const
+{
+    return m_files_to_extract;
+}
+
+//----------------------------------------------------------------------------------------
+//OperationCanceledException
+//----------------------------------------------------------------------------------------
+
+const char* OPERATION_CANCELED_EXCEPTION = "OperationCanceledException";
+
+OperationCanceledException::OperationCanceledException(const char* message):
+        BasePlatformException(OPERATION_CANCELED_EXCEPTION, message)
+{
+    LOGD("Entered");
+}
+
+OperationCanceledException::OperationCanceledException(JSContextRef ctx,
+        JSValueRef exception):
+    BasePlatformException(ctx, exception)
+{
+    mName = OPERATION_CANCELED_EXCEPTION;
+}
+
+//----------------------------------------------------------------------------------------
+//ExtractEntryProgressCallback
+//----------------------------------------------------------------------------------------
+
+ExtractEntryProgressCallback::ExtractEntryProgressCallback(JSContextRef globalCtx):
+        ExtractAllProgressCallback(globalCtx),
+        m_strip_name(false)
+{
+    LOGD("Entered");
+    m_callback_type = EXTRACT_ENTRY_PROGRESS_CALLBACK;
+}
+
+ExtractEntryProgressCallback::~ExtractEntryProgressCallback()
+{
+    LOGD("Entered");
+}
+
+ArchiveFileEntryPtr ExtractEntryProgressCallback::getArchiveFileEntry()
+{
+    return m_archive_file_entry;
+}
+
+void ExtractEntryProgressCallback::setArchiveFileEntry(ArchiveFileEntryPtr afentry)
+{
+    m_archive_file_entry = afentry;
+}
+
+void ExtractEntryProgressCallback::setStripName(bool strip_name)
+{
+    m_strip_name = strip_name;
+}
+
+bool ExtractEntryProgressCallback::getStripName() const
+{
+    return m_strip_name;
+}
+
+void ExtractEntryProgressCallback::setStripBasePath(
+        const std::string& strip_base_path)
+{
+    m_strip_base_path = strip_base_path;
+}
+
+const std::string& ExtractEntryProgressCallback::getStripBasePath() const
+{
+    return m_strip_base_path;
+}
+
+void ExtractEntryProgressCallback::executeOperation(ArchiveFilePtr archive_file_ptr)
+{
+    LOGD("Entered");
+
+    if(!m_archive_file_entry) {
+        LOGE("ArchiveFileEntry is not set in callback");
+        throw UnknownException("Could not extract archive file entry");
+    }
+
+    if(!archive_file_ptr) {
+        LOGE("archive_file_ptr is NULL");
+        throw UnknownException("Could not extract archive file entry");
+    }
+
+    UnZipPtr unzip = archive_file_ptr->createUnZipObject();
+    unzip->extractTo(this);
+}
+
+}
+}
diff --git a/src/Archive/ArchiveCallbackData.h b/src/Archive/ArchiveCallbackData.h
new file mode 100644 (file)
index 0000000..3e95194
--- /dev/null
@@ -0,0 +1,280 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ArchiveCallbackData.h
+ */
+
+#ifndef __ARCHIVE_CALLBACK_DATA_H__
+#define __ARCHIVE_CALLBACK_DATA_H__
+
+#include <string>
+#include <memory>
+
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include <File.h> //File from filesystem
+
+#include "ArchiveFileEntry.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+class ArchiveFileEntry;
+typedef std::shared_ptr<ArchiveFileEntry> ArchiveFileEntryPtr;
+
+enum ArchiveCallbackType {
+    OPERATION_CALLBACK_DATA = 0,
+    OPEN_CALLBACK_DATA = 1,
+    GET_ENTRIES_CALLBACK_DATA = 2,
+    GET_ENTRY_BY_NAME_CALLBACK_DATA = 3,
+    BASE_PROGRESS_CALLBACK = 4,
+    EXTRACT_ALL_PROGRESS_CALLBACK = 5,
+    EXTRACT_ENTRY_PROGRESS_CALLBACK = 6,
+    ADD_PROGRESS_CALLBACK = 7
+};
+
+class ArchiveFile;
+typedef std::shared_ptr<ArchiveFile> ArchiveFilePtr;
+
+class OperationCallbackData : public Common::MultiCallbackUserData
+{
+public:
+    OperationCallbackData(JSContextRef globalCtx,
+            ArchiveCallbackType callback_type = OPERATION_CALLBACK_DATA);
+    virtual ~OperationCallbackData();
+
+    void setSuccessCallback(JSValueRef on_success);
+    void setErrorCallback(JSValueRef on_error);
+
+    void callSuccessCallback();
+    void callSuccessCallback(JSValueRef err);
+    void callErrorCallback(JSValueRef err);
+
+    void setError(const std::string &err_name,
+            const std::string &err_message);
+    bool isError() const;
+    const std::string& getErrorName() const;
+    const std::string& getErrorMessage() const;
+
+    void setOperationId(long op_id);
+    long getOperationId() const;
+
+    ArchiveCallbackType getCallbackType() const;
+
+    virtual void executeOperation(ArchiveFilePtr archive_file_ptr);
+
+    bool isCanceled() const;
+    void setIsCanceled(bool is_cancel);
+
+    ArchiveFilePtr getArchiveFile() const;
+    void setArchiveFile(ArchiveFilePtr caller);
+
+protected:
+    ArchiveCallbackType m_callback_type;
+    long m_op_id;
+
+private:
+    bool m_is_error;
+    bool m_is_canceled;
+    std::string m_err_name;
+    std::string m_err_message;
+
+    ArchiveFilePtr m_caller_instance;
+};
+
+class OpenCallbackData : public OperationCallbackData
+{
+public:
+    OpenCallbackData(JSContextRef globalCtx,
+            ArchiveCallbackType callback_type = OPEN_CALLBACK_DATA);
+    virtual ~OpenCallbackData();
+
+    virtual void executeOperation(ArchiveFilePtr archive_file_ptr);
+};
+
+class GetEntriesCallbackData : public OperationCallbackData
+{
+public:
+    GetEntriesCallbackData(JSContextRef globalCtx,
+            ArchiveCallbackType callback_type = GET_ENTRIES_CALLBACK_DATA);
+    virtual ~GetEntriesCallbackData();
+
+    ArchiveFileEntryPtrMapPtr getEntries() const;
+    void setEntries(ArchiveFileEntryPtrMapPtr entries);
+
+    virtual void executeOperation(ArchiveFilePtr archive_file_ptr);
+
+private:
+    ArchiveFileEntryPtrMapPtr m_entries;
+};
+
+class GetEntryByNameCallbackData : public OperationCallbackData
+{
+public:
+    GetEntryByNameCallbackData(JSContextRef globalCtx,
+            ArchiveCallbackType callback_type = GET_ENTRY_BY_NAME_CALLBACK_DATA);
+    virtual ~GetEntryByNameCallbackData();
+
+    const std::string& getName() const;
+    void setName(const std::string& name);
+
+    ArchiveFileEntryPtr getFileEntry() const;
+    void setFileEntry(ArchiveFileEntryPtr entry);
+
+    virtual void executeOperation(ArchiveFilePtr archive_file_ptr);
+private:
+    std::string m_name;
+    ArchiveFileEntryPtr m_file_entry;
+
+};
+
+class BaseProgressCallback : public OperationCallbackData
+{
+public:
+    BaseProgressCallback(JSContextRef globalCtx,
+            ArchiveCallbackType callback_type  = BASE_PROGRESS_CALLBACK);
+    virtual ~BaseProgressCallback();
+
+    void setProgressCallback(JSValueRef on_progress);
+
+    bool getOverwrite() const;
+    void setOverwrite(bool overwrite);
+
+    void callProgressCallbackOnMainThread(const double progress,
+            ArchiveFileEntryPtr current_entry);
+    void callSuccessCallbackOnMainThread();
+
+    virtual void executeOperation(ArchiveFilePtr archive_file_ptr);
+
+protected:
+    void callProgressCallback(long operationId,
+            double value,
+            const std::string& filename);
+
+private:
+    static gboolean callProgressCallbackCB(void* data);
+    static gboolean callSuccessCallbackCB(void* data);
+
+    bool m_overwrite;
+};
+
+class AddProgressCallback : public BaseProgressCallback
+{
+public:
+    AddProgressCallback(JSContextRef globalCtx,
+            ArchiveCallbackType callback_type = ADD_PROGRESS_CALLBACK);
+    virtual ~AddProgressCallback();
+
+    virtual void executeOperation(ArchiveFilePtr archive_file_ptr);
+
+    void setBasePath(const std::string& path);
+    const std::string& getBasePath();
+    const std::string& getBaseVirtualPath();
+
+    ArchiveFileEntryPtr getFileEntry() const;
+    void setFileEntry(ArchiveFileEntryPtr file_entry);
+
+private:
+    ArchiveFileEntryPtr m_file_entry;
+    ArchiveFileEntryPtrMapPtr m_entry_map;
+    std::string m_base_path;
+    std::string m_base_virt_path;
+};
+
+class ExtractAllProgressCallback : public BaseProgressCallback
+{
+public:
+    ExtractAllProgressCallback(JSContextRef globalCtx,
+            ArchiveCallbackType callback_type = EXTRACT_ALL_PROGRESS_CALLBACK);
+    virtual ~ExtractAllProgressCallback();
+
+    Filesystem::FilePtr getDirectory() const;
+    void setDirectory(Filesystem::FilePtr directory);
+
+    void startedExtractingFile(unsigned long current_file_size);
+    void extractedPartOfFile(unsigned long bytes_decompressed);
+    void finishedExtractingFile();
+
+    double getCurrentFileProgress() const;
+    double getOverallProgress() const;
+
+    virtual void executeOperation(ArchiveFilePtr archive_file_ptr);
+
+    void setExpectedDecompressedSize(unsigned long exp_dec_size);
+    unsigned long getExpectedDecompressedSize() const;
+
+    void setNumberOfFilesToExtract(unsigned long files_count);
+    unsigned long getNumberOfFilesToExtract() const;
+
+private:
+    void updateOverallProgress(unsigned long bytes_decompressed);
+
+    Filesystem::FilePtr m_directory;
+
+    //
+    // Constant values set before extracting entries:
+    //
+    unsigned long m_files_to_extract;
+    unsigned long m_expected_decompressed_size;
+
+    //
+    // Values updated during extraction
+    //
+
+    unsigned long m_current_file_size;
+    unsigned long m_current_file_extracted_bytes;
+    unsigned long m_files_extracted;
+
+    double m_progress_overall;
+    unsigned long m_overall_decompressed;
+};
+
+class ExtractEntryProgressCallback : public ExtractAllProgressCallback
+{
+public:
+    ExtractEntryProgressCallback(JSContextRef globalCtx);
+    virtual ~ExtractEntryProgressCallback();
+
+    ArchiveFileEntryPtr getArchiveFileEntry();
+    void setArchiveFileEntry(ArchiveFileEntryPtr afentry);
+
+    void setStripName(bool strip_name);
+    bool getStripName() const;
+
+    void setStripBasePath(const std::string& strip_base_path);
+    const std::string& getStripBasePath() const;
+
+    virtual void executeOperation(ArchiveFilePtr archive_file_ptr);
+
+private:
+    ArchiveFileEntryPtr m_archive_file_entry;
+    bool m_strip_name;
+    std::string m_strip_base_path;
+};
+
+class OperationCanceledException : public Common::BasePlatformException {
+public:
+    OperationCanceledException(const char* message = "Operation Canceled");
+    OperationCanceledException(JSContextRef ctx, JSValueRef exception);
+};
+
+}
+}
+
+#endif //__ARCHIVE_CALLBACK_DATA_H__
diff --git a/src/Archive/ArchiveFile.cpp b/src/Archive/ArchiveFile.cpp
new file mode 100644 (file)
index 0000000..acea0a3
--- /dev/null
@@ -0,0 +1,748 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "ArchiveFile.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+#include <Path.h>
+
+#include "ArchiveManager.h"
+#include "JSArchiveFileEntry.h"
+#include "JSArchiveFile.h"
+#include "ArchiveUtils.h"
+#include "plugin_config_impl.h"
+#include "UnZip.h"
+#include "Zip.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+using namespace Common;
+
+Permission::Permission(bool r, bool w, bool rw, bool a){
+    permission[0] = r;
+    permission[1] = w;
+    permission[2] = rw;
+    permission[3] = a;
+}
+
+PermissionMap ArchiveFile::s_permission_map = {
+        {ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ADD,
+                Permission(NOT_ALLOWED, ALLOWED, ALLOWED, ALLOWED)},
+        {ARCHIVE_FUNCTION_API_ARCHIVE_FILE_EXTRACT_ALL,
+                Permission(ALLOWED, NOT_ALLOWED, ALLOWED, NOT_ALLOWED)},
+        {ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRIES,
+                Permission(ALLOWED, NOT_ALLOWED, ALLOWED, NOT_ALLOWED)},
+        {ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRY_BY_NAME,
+                Permission(ALLOWED, NOT_ALLOWED, ALLOWED, NOT_ALLOWED)}
+};
+
+ArchiveFile::ArchiveFile() :
+        enable_shared_from_this<ArchiveFile>(),
+        m_decompressed_size(0),
+        m_is_open(false),
+        m_overwrite(false),
+        m_created_as_new_empty_archive(false)
+{
+    LOGD("Entered");
+}
+
+ArchiveFile::ArchiveFile(FileMode file_mode) :
+        enable_shared_from_this<ArchiveFile>(),
+        m_decompressed_size(0),
+        m_is_open(false),
+        m_overwrite(false)
+{
+    m_file_mode = file_mode;
+}
+
+ArchiveFile::~ArchiveFile()
+{
+    LOGD("Entered");
+
+    if(m_entry_map) {
+        LOGD("Unlinking old m_entry_map: %d ArchiveFileEntries", m_entry_map->size());
+        for(auto it = m_entry_map->begin(); it != m_entry_map->end(); ++it) {
+            if(it->second) {
+                it->second->setArchiveFileNonProtectPtr(NULL);
+            }
+        }
+    }
+}
+
+gboolean ArchiveFile::openTaskCompleteCB(void *data)
+{
+    LOGD("Entered");
+    auto callback = static_cast<OperationCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            JSObjectRef result = JSArchiveFile::makeJSObject(context,
+                    callback->getArchiveFile());
+            callback->callSuccessCallback(result);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+gboolean ArchiveFile::callErrorCallback(void* data)
+{
+    LOGD("Entered");
+    auto callback = static_cast<OperationCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            LOGW("The success callback should be not be called in this case");
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* ArchiveFile::taskManagerThread(void *data)
+{
+    LOGD("Entered");
+    ArchiveFileHolder* archive_file_holder = static_cast<ArchiveFileHolder*>(data);
+    if (!archive_file_holder) {
+        LOGE("archive_file_holder is null");
+        return NULL;
+    }
+
+    if (!archive_file_holder->ptr){
+        LOGE("archive_file is null");
+        delete archive_file_holder;
+        archive_file_holder = NULL;
+        return NULL;
+    }
+
+    while(true){
+        OperationCallbackData* callback = NULL;
+        bool call_error_callback = false;
+        try{
+            {
+                std::lock_guard<std::mutex> lock(archive_file_holder->ptr->m_mutex);
+                if(archive_file_holder->ptr->m_task_queue.empty()){
+                    break;
+                }
+                callback = archive_file_holder->ptr->m_task_queue.back().second;
+            }
+            if(callback && !callback->isCanceled()){
+                callback->executeOperation(archive_file_holder->ptr);
+            }
+            {
+                std::lock_guard<std::mutex> lock(archive_file_holder->ptr->m_mutex);
+                archive_file_holder->ptr->m_task_queue.pop_back();
+            }
+        } catch (const OperationCanceledException &err) {
+            {
+                std::lock_guard<std::mutex> lock(archive_file_holder->ptr->m_mutex);
+                archive_file_holder->ptr->m_task_queue.pop_back();
+            }
+            delete callback;
+            callback = NULL;
+        } catch (const BasePlatformException &err) {
+            LOGE("taskManagerThread fails, %s: %s", err.getName().c_str(),
+                    err.getMessage().c_str());
+            callback->setError(err.getName().c_str(), err.getMessage().c_str());
+            call_error_callback = true;
+        } catch (...) {
+            LOGE("taskManagerThread fails");
+            callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "UnknownError.");
+            call_error_callback = true;
+        }
+        if(call_error_callback) {
+            {
+                std::lock_guard<std::mutex> lock(archive_file_holder->ptr->m_mutex);
+                archive_file_holder->ptr->m_task_queue.pop_back();
+            }
+            if (!g_idle_add(callErrorCallback, static_cast<void*>(callback))) {
+                LOGE("g_idle_add fails");
+                delete callback;
+                callback = NULL;
+            }
+        }
+    }
+
+    delete archive_file_holder;
+    archive_file_holder = NULL;
+
+    return NULL;
+}
+
+long ArchiveFile::addOperation(OperationCallbackData* callback)
+{
+    LOGD("Entered callback type:%d", callback->getCallbackType());
+
+    const long operation_id =
+            ArchiveManager::getInstance().getNextOperationId(shared_from_this());
+    callback->setOperationId(operation_id);
+    callback->setArchiveFile(shared_from_this());
+    std::size_t size = 0;
+    {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        m_task_queue.push_front(CallbackPair(operation_id, callback));
+        size = m_task_queue.size();
+    }
+    if(1 == size){
+        pthread_t thread;
+        ArchiveFileHolder* holder = new(std::nothrow) ArchiveFileHolder();
+        if(!holder){
+            LOGE("Memory allocation error");
+            throw UnknownException("Memory allocation error");
+        }
+        holder->ptr = shared_from_this();
+        if (pthread_create(&thread, NULL, taskManagerThread,
+                static_cast<void*>(holder))) {
+            LOGE("Thread creation failed");
+            delete holder;
+            holder = NULL;
+            throw UnknownException("Thread creation failed");
+        }
+
+        if (pthread_detach(thread)) {
+            LOGE("Thread detachment failed");
+        }
+    }
+    return operation_id;
+}
+
+void ArchiveFile::extractAllTask(ExtractAllProgressCallback* callback)
+{
+    Filesystem::FilePtr directory = callback->getDirectory();
+
+    if(!directory) {
+        LOGE("Directory is null");
+        throw UnknownException("Directory is null");
+    } else {
+        if(!directory->getNode()){
+            LOGE("Node in directory is null");
+            throw UnknownException("Node is null");
+        }
+    }
+
+    if(!m_file) {
+        LOGE("File is null");
+        throw UnknownException("File is null");
+    } else {
+        if(!m_file->getNode()){
+            LOGE("Node in file is null");
+            throw UnknownException("Node in file is null");
+        }
+    }
+
+    // For explanation please see:
+    //    ArchiveFile.h m_created_as_new_empty_archive description
+    //
+    if(m_file->getNode()->getSize() == 0) {
+        LOGD("Zip file: %s is empty",
+                m_file->getNode()->getPath()->getFullPath().c_str());
+
+        if(m_created_as_new_empty_archive) {
+            //We do not call progress callback since we do not have any ArchiveFileEntry
+            callback->callSuccessCallbackOnMainThread();
+            callback = NULL;
+            return;
+        }
+        else {
+            LOGW("m_created_as_new_empty_archive is false");
+            LOGE("Throwing InvalidStateException: File is not valid ZIP archive");
+            throw InvalidStateException("File is not valid ZIP archive");
+        }
+    }
+
+    UnZipPtr unzip = createUnZipObject();
+    unzip->extractAllFilesTo(directory->getNode()->getPath()->getFullPath(), callback);
+}
+
+long ArchiveFile::getEntries(GetEntriesCallbackData* callback)
+{
+    LOGD("Entered");
+    if(!callback) {
+        LOGE("callback is NULL");
+        throw UnknownException("Could not get list of files in archive");
+    }
+
+    throwInvalidStateErrorIfArchiveFileIsClosed();
+
+    return addOperation(callback);
+}
+
+gboolean ArchiveFile::getEntriesTaskCompleteCB(void *data)
+{
+    auto callback = static_cast<GetEntriesCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        ArchiveFileEntryPtrMapPtr entries = callback->getEntries();
+        unsigned int size = entries->size();
+
+        JSObjectRef objArray[size];
+        int i = 0;
+        for(auto it = entries->begin(); it != entries->end(); it++) {
+            objArray[i] = JSArchiveFileEntry::makeJSObject(context, it->second);
+            i++;
+        }
+
+        JSValueRef exception = NULL;
+        JSObjectRef jsResult = JSObjectMakeArray(context, size,
+                size > 0 ? objArray : NULL, &exception);
+        if (exception != NULL) {
+            throw Common::UnknownException(context, exception);
+        }
+
+        callback->callSuccessCallback(jsResult);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+long ArchiveFile::extractAll(ExtractAllProgressCallback *callback)
+{
+    LOGD("Entered");
+    if(!callback) {
+        LOGE("callback is NULL");
+        throw UnknownException("Could not extract all files from archive");
+    }
+
+    throwInvalidStateErrorIfArchiveFileIsClosed();
+
+    return addOperation(callback);
+}
+
+long ArchiveFile::extractEntryTo(ExtractEntryProgressCallback* callback)
+{
+    LOGD("Entered");
+    if(!callback) {
+        LOGE("callback is NULL");
+        throw UnknownException("Could not extract archive file entry");
+    }
+
+    // FIXME according to documentation:
+    // if archive was closed, any further operation attempt will make InvalidStateError
+    // but method extract() from ArchiveFileEntryObject is not permitted to throw above exception
+
+    // uncomment in case when this method have permission to throwing InvalidStateError
+    // throwInvalidStateErrorIfArchiveFileisClosed();
+    if(!m_is_open) {
+        LOGE("Archive is not opened");
+        throw UnknownException("Archive is not opened");
+    }
+
+    return addOperation(callback);
+}
+
+
+long ArchiveFile::add(AddProgressCallback *callback)
+{
+    LOGD("Entered");
+    if(!callback) {
+        LOGE("callback is NULL");
+        throw UnknownException("Could not add file to archive");
+    }
+    if(FileMode::READ == m_file_mode) {
+        LOGE("Trying to add file when READ access mode selected");
+        throw InvalidAccessException("Add not allowed for \"r\" access mode");
+    }
+
+    throwInvalidStateErrorIfArchiveFileIsClosed();
+
+    return addOperation(callback);
+}
+
+void ArchiveFile::close()
+{
+    LOGD("Entered");
+
+    if(!m_is_open){
+        LOGD("Archive already closed");
+    }
+    m_is_open = false;
+
+    return;
+}
+
+long ArchiveFile::getEntryByName(GetEntryByNameCallbackData* callback)
+{
+    LOGD("Entered");
+    if(!callback) {
+        LOGE("callback is NULL");
+        throw UnknownException("Could not get archive file entries by name");
+    }
+
+    throwInvalidStateErrorIfArchiveFileIsClosed();
+
+    return addOperation(callback);
+}
+
+gboolean ArchiveFile::getEntryByNameTaskCompleteCB(void *data)
+{
+    auto callback = static_cast<GetEntryByNameCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            JSObjectRef entry = JSArchiveFileEntry::makeJSObject(context,
+                    callback->getFileEntry());
+            callback->callSuccessCallback(entry);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+Filesystem::FilePtr ArchiveFile::getFile() const
+{
+    LOGD("Entered");
+    return m_file;
+}
+
+void ArchiveFile::setFile(Filesystem::FilePtr file)
+{
+    LOGD("Entered");
+    m_file = file;
+}
+
+bool ArchiveFile::isOverwrite() const
+{
+    return m_overwrite;
+}
+
+void ArchiveFile::setOverwrite(bool overwrite)
+{
+    LOGD("Entered");
+    m_overwrite = overwrite;
+}
+
+unsigned long ArchiveFile::getDecompressedSize() const
+{
+    LOGD("Entered");
+    return m_decompressed_size;
+}
+
+void ArchiveFile::setDecompressedSize(unsigned long decompressed_size)
+{
+    LOGD("Entered");
+    m_decompressed_size = decompressed_size;
+}
+
+bool ArchiveFile::isOpen() const
+{
+    LOGD("Entered");
+    return m_is_open;
+}
+
+void ArchiveFile::setIsOpen(bool is_open)
+{
+    LOGD("Entered");
+    m_is_open = is_open;
+}
+
+ArchiveFileEntryPtrMapPtr ArchiveFile::getEntryMap() const
+{
+    return m_entry_map;
+}
+
+void ArchiveFile::setEntryMap(ArchiveFileEntryPtrMapPtr entries)
+{
+    LOGD("Entered");
+
+    if(m_entry_map) {
+        LOGD("Unlinking old m_entry_map: %d ArchiveFileEntries", m_entry_map->size());
+        for(auto it = m_entry_map->begin(); it != m_entry_map->end(); ++it) {
+            if(it->second) {
+                it->second->setArchiveFileNonProtectPtr(NULL);
+            }
+        }
+    }
+
+    m_entry_map = entries;
+
+    LOGD("Linking new m_entry_map ArchiveFileEntries (%d) with ArchiveFile object",
+            m_entry_map->size());
+    for(auto it = m_entry_map->begin(); it != m_entry_map->end(); ++it) {
+        if(it->second) {
+            it->second->setArchiveFileNonProtectPtr(this);
+        }
+    }
+}
+
+UnZipPtr ArchiveFile::createUnZipObject()
+{
+    LOGD("Entered");
+    if(!m_is_open) {
+        LOGE("File is not opened");
+        throw UnknownException("File is not opened");
+    }
+
+    if (!m_file) {
+        LOGE("m_file is null");
+        throw UnknownException("File is null");
+    }
+
+    Filesystem::NodePtr node = m_file->getNode();
+    if(!node) {
+        LOGE("Node is null");
+        throw UnknownException("Node is null");
+    }
+
+    UnZipPtr unzip = UnZip::open(node->getPath()->getFullPath());
+    return unzip;
+}
+
+ZipPtr ArchiveFile::createZipObject()
+{
+    LOGD("Entered");
+    if(!m_is_open) {
+        LOGE("File is not opened");
+        throw UnknownException("File is not opened");
+    }
+
+    if (!m_file) {
+        LOGE("m_file is null");
+        throw UnknownException("File is null");
+    }
+
+    Filesystem::NodePtr node = m_file->getNode();
+    if(!node) {
+        LOGE("Node is null");
+        throw UnknownException("Node is null");
+    }
+
+    ZipPtr zip = Zip::open(node->getPath()->getFullPath());
+    return zip;
+
+}
+
+bool ArchiveFile::isAllowedOperation(const std::string& method_name)
+{
+    LOGD("Entered");
+    PermissionMap::iterator it = s_permission_map.find(method_name);
+    if (it != s_permission_map.end()) {
+        return it->second.permission[m_file_mode];
+    }
+    return false;
+}
+
+FileMode ArchiveFile::getFileMode() const
+{
+   LOGD("Entered");
+   return m_file_mode;
+}
+
+void ArchiveFile::setFileMode(FileMode file_mode)
+{
+    LOGD("Entered");
+    m_file_mode = file_mode;
+}
+
+void ArchiveFile::throwInvalidStateErrorIfArchiveFileIsClosed() const
+{
+    if(!m_is_open){
+        LOGE("ArchiveFile closed - operation not permitted");
+        throw InvalidStateException(
+            "ArchiveFile closed - operation not permitted");
+    }
+}
+
+void ArchiveFile::setCreatedAsNewEmptyArchive(bool new_and_empty)
+{
+    m_created_as_new_empty_archive = new_and_empty;
+}
+
+bool ArchiveFile::isCreatedAsNewEmptyArchive() const
+{
+    return m_created_as_new_empty_archive;
+}
+
+void ArchiveFile::updateListOfEntries()
+{
+    // For explanation please see:
+    //    ArchiveFile.h m_created_as_new_empty_archive description
+    //
+    if(m_file->getNode()->getSize() == 0) {
+        LOGD("Zip file: %s is empty",
+                m_file->getNode()->getPath()->getFullPath().c_str());
+
+        if(m_created_as_new_empty_archive) {
+            LOGD("OK this is empty archive = nothing to do yet");
+            return;
+        }
+        else {
+            LOGW("m_created_as_new_empty_archive is false");
+            LOGE("Throwing InvalidStateException: File is not valid ZIP archive");
+            throw InvalidStateException("File is not valid ZIP archive");
+        }
+    }
+
+    UnZipPtr unzip = createUnZipObject();
+    unsigned long decompressedSize = 0;
+    ArchiveFileEntryPtrMapPtr emap = unzip->listEntries(&decompressedSize);
+    setEntryMap(emap);
+    setDecompressedSize(decompressedSize);
+}
+
+bool ArchiveFile::isEntryWithNameInArchive(const std::string& name_in_zip,
+        bool* out_is_directory,
+        std::string* out_matching_name)
+{
+    if(!m_entry_map) {
+        LOGW("m_entry_map is NULL");
+        return false;
+    }
+
+    const bool name_in_zip_is_dir = isDirectoryPath(name_in_zip);
+    bool set_is_directory = false;
+    bool set_name_exists = false;
+
+    //Try exact name:
+    auto it = m_entry_map->find(name_in_zip);
+    if(it != m_entry_map->end()) {
+        set_is_directory = name_in_zip_is_dir;
+        set_name_exists = true;
+    }
+    else {
+        if(name_in_zip_is_dir) {
+            //If name_in_zip is pointing at directory try file
+            it = m_entry_map->find(removeTrailingDirectorySlashFromPath(name_in_zip));
+            set_is_directory = false;
+        } else {
+            //If name_in_zip is pointing at file try directory
+            it = m_entry_map->find(name_in_zip + "/");
+            set_is_directory = true;
+        }
+
+        if(it != m_entry_map->end()) {
+            set_name_exists = true;
+        }
+    }
+
+    if(!set_name_exists) {
+        return false;
+    }
+
+    if(out_is_directory) {
+        *out_is_directory = set_is_directory;
+    }
+    if(out_matching_name) {
+        *out_matching_name = it->first;
+    }
+
+    return true;
+}
+
+} // Archive
+} // DeviceAPI
diff --git a/src/Archive/ArchiveFile.h b/src/Archive/ArchiveFile.h
new file mode 100755 (executable)
index 0000000..b18b9fb
--- /dev/null
@@ -0,0 +1,188 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef _TIZEN_ARCHIVE_ARCHIVE_FILE_H_
+#define _TIZEN_ARCHIVE_ARCHIVE_FILE_H_
+
+#include <memory>
+#include <string>
+#include <deque>
+#include <File.h> // from filesystem
+
+#include "ArchiveCallbackData.h"
+#include "UnZip.h"
+#include "Zip.h"
+#include "ArchiveManager.h"
+
+
+namespace DeviceAPI {
+namespace Archive {
+
+class ArchiveFile;
+class ArchiveManager;
+class OperationCallbackData;
+class OpenCallbackData;
+class GetEntriesCallbackData;
+class GetEntryByNameCallbackData;
+class BaseProgressCallback;
+class AddProgressCallback;
+class ExtractAllProgressCallback;
+class UnZipExtractRequest;
+class ExtractEntryProgressCallback;
+class Zip;
+class ZipAddRequest;
+
+enum FileMode {
+    READ = 0,
+    WRITE,
+    READ_WRITE,
+    ADD
+};
+
+enum IsAllowed {
+    NOT_ALLOWED = false,
+    ALLOWED = true
+};
+
+struct Permission {
+    Permission(bool r, bool w, bool rw, bool a);
+    bool permission[4];
+};
+
+typedef std::shared_ptr<ArchiveFile> ArchiveFilePtr;
+typedef std::pair<long, OperationCallbackData*> CallbackPair;
+typedef std::vector<ArchiveFileEntryPtr> ArchiveFileEntryPtrVector;
+typedef std::map<std::string, Permission> PermissionMap;
+typedef std::pair<std::string, Permission> PermissionPair;
+
+struct ArchiveFileHolder{
+    ArchiveFilePtr ptr;
+};
+
+class ArchiveFile : public std::enable_shared_from_this<ArchiveFile> {
+public:
+    ArchiveFile();
+    ArchiveFile(FileMode file_mode);
+    virtual ~ArchiveFile();
+
+    long getEntries(GetEntriesCallbackData* callback);
+    long getEntryByName(GetEntryByNameCallbackData* callback);
+    long extractAll(ExtractAllProgressCallback *callback);
+    long add(AddProgressCallback *callback);
+    void close();
+
+    Filesystem::FilePtr getFile() const;
+    void setFile(Filesystem::FilePtr file);
+    bool isOverwrite() const;
+    void setOverwrite(bool overwrite);
+    unsigned long getDecompressedSize() const;
+    void setDecompressedSize(unsigned long decompressed_size);
+    bool isOpen() const;
+    void setIsOpen(bool is_open);
+
+    ArchiveFileEntryPtrMapPtr getEntryMap() const;
+    void setEntryMap(ArchiveFileEntryPtrMapPtr entries);
+    bool isEntryWithNameInArchive(const std::string& name_in_zip,
+            bool* out_is_directory = NULL,
+            std::string* out_matching_name = NULL);
+
+
+    //Used by ArchiveFileEntry
+    long extractEntryTo(ExtractEntryProgressCallback* callback);
+
+    bool isAllowedOperation(const std::string& method_name);
+    FileMode getFileMode() const;
+    void setFileMode(FileMode file_mode);
+
+    /**
+     *  \brief Throw InvalidStateError in case when ArchiveFile is closed
+     */
+    void throwInvalidStateErrorIfArchiveFileIsClosed() const;
+
+    void setCreatedAsNewEmptyArchive(bool new_and_empty);
+    bool isCreatedAsNewEmptyArchive() const;
+
+
+    void updateListOfEntries();
+private:
+    UnZipPtr createUnZipObject();
+    ZipPtr createZipObject();
+
+    std::deque<CallbackPair> m_task_queue;
+    std::mutex m_mutex;
+
+    Filesystem::FilePtr m_file;
+
+    FileMode m_file_mode;
+    static PermissionMap s_permission_map;
+
+    unsigned long m_decompressed_size;
+    bool m_is_open;
+    /**
+     * If set to true, during decompression archive will had permission to overwriting files.
+     * Warning: If decompressing file have got the same name as existing directory
+     * in place where file should be decompressed, directory will be deleted.
+    */
+    bool m_overwrite;
+    ArchiveFileEntryPtrMapPtr m_entry_map;
+
+
+    /**
+     * If we execute tizen.open(destFile , "w"/"rw"/ "a", ..., {overwrite: true}),
+     * destFile will be empty file with size = 0, which cannot be
+     * opened with minizip library.
+     *
+     * Zip file format restricts that at least one file / folder is compressed,
+     * threfore after creating new empty archive we cannot save it.
+     * Until we execute archive.add destFile is empty file with size 0 bytes.
+     *
+     * Unfortunately if we try to execute archive.getEntries or archive.extractAll
+     * minizip library will fail to open empty archive. To fix this issue we will
+     * use flag "created_as_new_empty_archive" which informs that this is new and
+     * empty archive threfore we should not try to open it.
+     *
+     * In extractAll we will just call success callback - there was nothing to extract
+     * but no error occured. In get entries we just should return empty list of entries.
+     */
+    bool m_created_as_new_empty_archive;
+
+    static gboolean openTaskCompleteCB(void *data);
+    static gboolean getEntriesTaskCompleteCB(void *data);
+    static gboolean getEntryByNameTaskCompleteCB(void *data);
+
+    static void* taskManagerThread(void *data);
+    long addOperation(OperationCallbackData* callback);
+    static gboolean callErrorCallback(void* data);
+
+    void extractAllTask(ExtractAllProgressCallback* callback);
+
+    friend class ExtractAllProgressCallback;
+    friend class UnZipExtractRequest;
+    friend class OpenCallbackData;
+    friend class GetEntriesCallbackData;
+    friend class GetEntryByNameCallbackData;
+    friend class ExtractEntryProgressCallback;
+    friend class ArchiveManager;
+    friend class AddProgressCallback;
+    friend class Zip;
+    friend class ZipAddRequest;
+    friend class BaseProgressCallback;
+};
+
+} // Archive
+} // DeviceAPI
+
+#endif /* _TIZEN_ARCHIVE_FILE_ENTRY_H_ */
diff --git a/src/Archive/ArchiveFileEntry.cpp b/src/Archive/ArchiveFileEntry.cpp
new file mode 100644 (file)
index 0000000..ce74e37
--- /dev/null
@@ -0,0 +1,175 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "ArchiveFileEntry.h"
+
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+#include <PlatformException.h>
+
+#include "ArchiveCallbackData.h"
+#include "ArchiveFile.h"
+#include "ArchiveUtils.h"
+
+namespace DeviceAPI {
+
+using namespace DeviceAPI::Common;
+
+namespace Archive {
+
+static const unsigned int s_default_compression_level = 5;
+
+ArchiveFileEntry::ArchiveFileEntry(Filesystem::FilePtr file) :
+        std::enable_shared_from_this<ArchiveFileEntry>(),
+        m_file(file),
+        m_archive(NULL),
+        m_striped(false),
+        m_size(0),
+        m_compressed_size(0),
+        m_modified(0),
+        m_compression_level(s_default_compression_level)
+{
+    LOGD("Entered");
+}
+
+ArchiveFileEntry::~ArchiveFileEntry()
+{
+    LOGD("Entered");
+}
+
+unsigned long ArchiveFileEntry::getCompressedSize() const
+{
+    return m_compressed_size;
+}
+
+void ArchiveFileEntry::setCompressedSize(unsigned long compressed_size)
+{
+    m_compressed_size = compressed_size;
+}
+
+Filesystem::FilePtr ArchiveFileEntry::getFile() const
+{
+    return m_file;
+}
+
+void ArchiveFileEntry::setFile(Filesystem::FilePtr file)
+{
+    m_file = file;
+}
+
+unsigned long ArchiveFileEntry::getSize() const
+{
+    return m_size;
+}
+
+void ArchiveFileEntry::setSize(unsigned long size)
+{
+    m_size = size;
+}
+
+const std::string& ArchiveFileEntry::getName() const
+{
+    return m_name;
+}
+
+void ArchiveFileEntry::setName(const std::string& name)
+{
+    m_name = name;
+}
+
+void ArchiveFileEntry::setModified(time_t time)
+{
+    m_modified = time;
+}
+
+time_t ArchiveFileEntry::getModified() const
+{
+    return m_modified;
+}
+
+const std::string& ArchiveFileEntry::getDestination() const
+{
+    return m_destination;
+}
+
+void ArchiveFileEntry::setDestination(const std::string& destination)
+{
+    m_destination = destination;
+}
+
+bool ArchiveFileEntry::getStriped() const
+{
+    return m_striped;
+}
+
+void ArchiveFileEntry::setStriped(bool striped)
+{
+    m_striped = striped;
+}
+
+void ArchiveFileEntry::setCompressionLevel(unsigned int level)
+{
+    m_compression_level = level;
+}
+unsigned int ArchiveFileEntry::getCompressionLevel() const
+{
+    return m_compression_level;
+}
+
+void ArchiveFileEntry::setArchiveFileNonProtectPtr(ArchiveFile* ptr)
+{
+    m_archive = ptr;
+}
+
+ArchiveFile* ArchiveFileEntry::getArchiveFileNonProtectPtr()
+{
+    return m_archive;
+}
+
+long ArchiveFileEntry::extractTo(ExtractEntryProgressCallback* callback)
+{
+    if(!m_archive) {
+        LOGE("m_archive is NULL");
+        throw UnknownException("Could not extract archive file entry");
+    }
+
+    //Callback should be associated with this instance of ArchiveFileEntry
+    callback->setArchiveFileEntry(shared_from_this());
+
+    //
+    // If strip name was set in JS layer we need to generate srip base path
+    //
+    if(callback->getStripName()) {
+
+        //Get base path - left side of last slash
+        std::string base_path_name = getBasePathFromPath(m_name);
+        if(!isDirectoryPath(base_path_name) && !base_path_name.empty()) {
+            base_path_name += "/";
+        }
+
+        LOGD("strip name is: true; archive file entry name is: [%s]; "
+                "stripBasePath will be: [%s]",
+                m_name.c_str(), base_path_name.c_str());
+
+        callback->setStripBasePath(base_path_name);
+    }
+
+    return m_archive->extractEntryTo(callback);
+}
+
+} // Archive
+} // DeviceAPI
diff --git a/src/Archive/ArchiveFileEntry.h b/src/Archive/ArchiveFileEntry.h
new file mode 100755 (executable)
index 0000000..51bf1c0
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_ARCHIVE_ARCHIVE_FILE_ENTRY_H_
+#define _TIZEN_ARCHIVE_ARCHIVE_FILE_ENTRY_H_
+
+#include <memory>
+#include <File.h> // from filesystem
+
+
+
+namespace DeviceAPI {
+namespace Archive {
+
+class ArchiveFile;
+
+class ArchiveFileEntry;
+typedef std::shared_ptr<ArchiveFileEntry> ArchiveFileEntryPtr;
+
+class ExtractEntryProgressCallback;
+
+typedef std::map<std::string, ArchiveFileEntryPtr> ArchiveFileEntryPtrMap;
+typedef std::shared_ptr<ArchiveFileEntryPtrMap> ArchiveFileEntryPtrMapPtr;
+
+class ArchiveFileEntry :  public std::enable_shared_from_this<ArchiveFileEntry> {
+public:
+    ArchiveFileEntry(Filesystem::FilePtr file = Filesystem::FilePtr());
+    ~ArchiveFileEntry();
+
+    unsigned long getCompressedSize() const;
+    void setCompressedSize(unsigned long compressedSize);
+    Filesystem::FilePtr getFile() const;
+    void setFile(Filesystem::FilePtr file);
+    unsigned long getSize() const;
+    void setSize(unsigned long size);
+    const std::string& getName() const;
+    void setName(const std::string& name);
+    void setModified(time_t time);
+    time_t getModified() const;
+    const std::string& getDestination() const;
+    void setDestination(const std::string& destination);
+    bool getStriped() const;
+    void setStriped(bool striped);
+    void setCompressionLevel(unsigned int level);
+    unsigned int getCompressionLevel() const;
+
+    void setArchiveFileNonProtectPtr(ArchiveFile* ptr);
+    ArchiveFile* getArchiveFileNonProtectPtr();
+
+    long extractTo(ExtractEntryProgressCallback* callback);
+
+private:
+    Filesystem::FilePtr m_file;
+    ArchiveFile* m_archive;
+    std::string m_name;
+    std::string m_destination;
+    bool m_striped;
+    unsigned long m_size;
+    unsigned long m_compressed_size;
+    time_t m_modified;
+    unsigned int m_compression_level;
+};
+
+} // Archive
+} // DeviceAPI
+
+#endif /* _TIZEN_ARCHIVE_FILE_ENTRY_H_ */
diff --git a/src/Archive/ArchiveManager.cpp b/src/Archive/ArchiveManager.cpp
new file mode 100644 (file)
index 0000000..ef57ab8
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "ArchiveManager.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Archive {
+
+ArchiveManager::ArchiveManager():
+    m_next_unique_id(0)
+{
+    LOGD("Initialize ArchiveManager");
+}
+
+ArchiveManager::~ArchiveManager()
+{
+    LOGD("Deinitialize ArchiveManager");
+}
+
+ArchiveManager& ArchiveManager::getInstance()
+{
+    LOGD("Entered");
+    static ArchiveManager instance;
+    return instance;
+}
+
+void ArchiveManager::abort(long operation_id)
+{
+    LOGD("Entered");
+    ArchiveFileMap::iterator it = m_archive_file_map.find(operation_id);
+    if (it != m_archive_file_map.end()) {
+        ArchiveFilePtr archive_file_ptr = it->second;
+        std::lock_guard<std::mutex> lock(archive_file_ptr->m_mutex);
+
+        std::size_t size = archive_file_ptr->m_task_queue.size();
+        for(int i = 0; i < size; ++i){
+            if(operation_id == archive_file_ptr->m_task_queue[i].first){
+                archive_file_ptr->m_task_queue[i].second->setIsCanceled(true);
+                return;
+            }
+        }
+    }
+    LOGD("The Operation Identifier not found");
+}
+
+long ArchiveManager::open(OpenCallbackData* callback)
+{
+    LOGD("Entered");
+
+    ArchiveFilePtr a_ptr = callback->getArchiveFile();
+    return a_ptr->addOperation(callback);
+}
+
+
+long ArchiveManager::getNextOperationId(ArchiveFilePtr archive_file_ptr)
+{
+    LOGD("Entered");
+    long op_id = ++m_next_unique_id;
+    m_archive_file_map.insert(ArchiveFilePair(op_id, archive_file_ptr));
+    return op_id;
+}
+
+void ArchiveManager::eraseElementFromArchiveFileMap(long operation_id)
+{
+    LOGD("Entered");
+    ArchiveFileMap::iterator it = m_archive_file_map.find(operation_id);
+    if (it != m_archive_file_map.end()) {
+        m_archive_file_map.erase(it);
+    }
+}
+
+} // Archive
+} // DeviceAPI
diff --git a/src/Archive/ArchiveManager.h b/src/Archive/ArchiveManager.h
new file mode 100755 (executable)
index 0000000..322e19a
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_ARCHIVE_ARCHIVE_MANAGER_H_
+#define _TIZEN_ARCHIVE_ARCHIVE_MANAGER_H_
+
+#include <string>
+#include "ArchiveFile.h"
+#include "ArchiveCallbackData.h"
+
+
+namespace DeviceAPI {
+namespace Archive {
+
+typedef std::map<long, ArchiveFilePtr> ArchiveFileMap;
+typedef std::pair<long, ArchiveFilePtr> ArchiveFilePair;
+
+class ArchiveManager {
+public:
+    static ArchiveManager& getInstance();
+    ~ArchiveManager();
+
+    void abort(long operation_id);
+    long getNextOperationId(ArchiveFilePtr archive_file_ptr);
+    void eraseElementFromArchiveFileMap(long operation_id);
+    long open(OpenCallbackData* callback);
+
+private:
+    ArchiveManager();
+    ArchiveManager(ArchiveManager const&);
+    void operator=(ArchiveManager const&);
+
+    ArchiveFileMap m_archive_file_map;
+
+    long m_next_unique_id;
+
+};
+
+} // Archive
+} // DeviceAPI
+
+#endif /* _TIZEN_ARCHIVE_ARCHIVE_MANAGER_H_ */
diff --git a/src/Archive/ArchiveUtils.cpp b/src/Archive/ArchiveUtils.cpp
new file mode 100644 (file)
index 0000000..5e3a6f3
--- /dev/null
@@ -0,0 +1,258 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ArchiveUtils.h"
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <JSFile.h>
+#include <Path.h>
+#include <FilesystemExternalUtils.h>
+#include <Logger.h>
+
+#include <sstream>
+#include <iomanip>
+
+namespace DeviceAPI {
+namespace Archive {
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Filesystem;
+
+std::string bytesToReadableString(const size_t num_bytes)
+{
+    std::stringstream ss;
+    static const size_t one_mb = 1024 * 1024;
+    static const size_t one_kb = 1024;
+    ss << std::setprecision(2) << std::fixed;
+
+    if(num_bytes >= one_mb) {
+        ss << (float)num_bytes / one_mb << " MB";
+    } else if(num_bytes >= one_kb) {
+        ss << (float)num_bytes / one_kb << " KB";
+    } else {
+        ss << num_bytes << " B";
+    }
+
+    return ss.str();
+}
+
+std::string fileModeToString(FileMode fm)
+{
+    switch(fm) {
+        case FileMode::READ:
+            return "r";
+        case FileMode::WRITE:
+            return "w";
+        case FileMode::READ_WRITE:
+            return "rw";
+        case FileMode::ADD:
+            return "a";
+        default:
+            throw UnknownException("Unknown file mode");
+    }
+}
+
+FileMode stringToFileMode(std::string fmString)
+{
+    if (!fmString.compare("r")) {
+        return FileMode::READ;
+    }
+    else if (!fmString.compare("w")) {
+        return FileMode::WRITE;
+    }
+    else if(!fmString.compare("rw")) {
+        return FileMode::READ_WRITE;
+    }
+    else if(!fmString.compare("a")) {
+        return FileMode::ADD;
+    }
+    // In widl it's "TypeMismatchError" so this exception used
+    // instead of InvalidValues
+    throw TypeMismatchException("Invalid FileMode");
+}
+
+FilePtr fileReferenceToFile(JSContextRef context, JSValueRef fileReference)
+{
+    auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+    FilePtr file_ptr;
+    try {
+        file_ptr = JSFile::getPrivateObject(context, fileReference);
+    } catch (const TypeMismatchException &tme) {
+        LOGD("Use virtual path.");
+        std::string virtual_path =
+            JSUtil::JSValueToString(context, fileReference);
+        if (!External::isVirtualPath(virtual_path)) {
+            LOGE("FileReference can be File object or a virtual path");
+            throw TypeMismatchException(
+                "FileReference can be File object or a virtual path");
+        }
+        std::string string_path =
+            External::fromVirtualPath(virtual_path, g_ctx);
+        LOGD("Path: %s", string_path.c_str());
+
+        PathPtr path = Path::create(string_path);
+        NodePtr node_ptr = Node::resolve(path);
+        file_ptr = FilePtr(new File(node_ptr, File::PermissionList()));
+    }
+
+    return file_ptr;
+}
+
+void getBasePathAndName(const std::string& filepath,
+        std::string& out_basepath,
+        std::string& out_name)
+{
+    const size_t filepath_len = filepath.length();
+
+    size_t name_end_index = filepath_len;
+    size_t name_start_index = 0;
+
+    for(int i = filepath_len - 1; i >= 0; --i) {
+        const char& cur = filepath[i];
+        if(cur == '/' || cur == '\\') {
+            if( (filepath_len-1) == i ) {
+                name_end_index = i;
+            } else {
+                name_start_index = i+1;
+                out_name = filepath.substr(name_start_index,
+                    name_end_index - name_start_index);
+
+                out_basepath = filepath.substr(0, name_start_index);
+                return;
+            }
+        }
+    }
+
+    // \ / is not found
+    out_basepath = "";
+    out_name = filepath.substr(0, name_end_index);
+}
+
+std::string removeDuplicatedSlashesFromPath(const std::string& path)
+{
+    const size_t path_len = path.length();
+
+    std::string out;
+    out.reserve(path_len);
+
+    bool prev_is_dir = false;
+    for(size_t i = 0; i < path_len; ++i) {
+        const char& cur = path[i];
+        if(cur == '/' || cur == '\\') {
+            if(!prev_is_dir) {
+                out += cur;
+            }
+            prev_is_dir = true;
+        } else {
+            prev_is_dir = false;
+            out += cur;
+        }
+    }
+
+    return out;
+}
+
+bool isDirectoryPath(const std::string& path)
+{
+    if(path.empty()) {
+        return false;
+    }
+
+    const char last_char = path[path.length() - 1];
+    return last_char ==  '\\' || last_char == '/';
+}
+
+std::string removeTrailingDirectorySlashFromPath(const std::string& path)
+{
+    if(!isDirectoryPath(path)) {
+        return path;
+    }
+
+    return path.substr(0, path.length() - 1);
+}
+
+std::string stripBasePathFromPath(const std::string& fullpath)
+{
+    const size_t location = fullpath.find_last_of("/\\");
+    if(std::string::npos == location) {
+        return fullpath;
+    }
+
+    return fullpath.substr(location + 1);
+}
+
+namespace{
+static std::string errErrno = "ERRNO";
+static std::string errEndOfListOfFile = "End list of file";
+static std::string errParamater = "Invalid parameter";
+static std::string errBadFile = "Incorrect file";
+static std::string errInternal = "Internal error";
+static std::string errCRC = "CRC error";
+static std::string errUnknown = "Unknown error";
+
+const std::string& getArchiveErrorMessage(int errorCode)
+{
+    /**
+     * All errors are defined in minizip library in files:
+     * zip.h and unzip.h
+     */
+    switch (errorCode) {
+        // ZIP_ERRNO & UNZ_ERRNO both value Z_ERRNO
+        case ZIP_ERRNO:
+            return errErrno;
+        // UNZ_END_OF_LIST_OF_FILE both value -100
+        case UNZ_END_OF_LIST_OF_FILE:
+            return errEndOfListOfFile;
+        // ZIP_PARAMERROR & UNZ_PARAMERROR both value -102
+        case ZIP_PARAMERROR:
+            return errParamater;
+        // ZIP_BADZIPFILE & UNZ_BADZIPFILE both value -103
+        case ZIP_BADZIPFILE:
+            return errBadFile;
+        // ZIP_INTERNALERROR & UNZ_INTERNALERROR bot value -104
+        case ZIP_INTERNALERROR:
+            return errInternal;
+        // UNZ_CRCERROR -105
+        case UNZ_CRCERROR:
+            return errCRC;
+        default:
+            return errUnknown;
+    }
+}
+}
+
+extern std::string getBasePathFromPath(const std::string& fullpath)
+{
+    const std::string tmp_path = removeTrailingDirectorySlashFromPath(fullpath);
+    const size_t location = tmp_path.find_last_of("/\\");
+    if(std::string::npos == location) {
+        return std::string();
+    }
+
+    return tmp_path.substr(0, location + 1);
+}
+
+extern std::string getArchiveLogMessage(const int errorCode, const std::string &hint)
+{
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getArchiveErrorMessage(errorCode) << ", " << errorCode;
+    return std::string(ss.str());
+}
+
+} //namespace Archive
+} //namespace DeviceAPI
diff --git a/src/Archive/ArchiveUtils.h b/src/Archive/ArchiveUtils.h
new file mode 100644 (file)
index 0000000..140f7f0
--- /dev/null
@@ -0,0 +1,124 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ARCHIVE_ARCHIVE_UTILS_H__
+#define __TIZEN_ARCHIVE_ARCHIVE_UTILS_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <File.h>
+#include <PlatformException.h>
+
+#include <string>
+#include "ArchiveFile.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+extern std::string bytesToReadableString(const size_t num_bytes);
+extern std::string fileModeToString(FileMode fm);
+extern FileMode stringToFileMode(std::string fmString);
+extern Filesystem::FilePtr fileReferenceToFile(
+    JSContextRef context, JSValueRef fileReference);
+
+/**
+ * Gets base path and name from full path string, example cases:
+ * full path             |  base path        | name
+ * ----------------------+-------------------+------------------
+ * ""                    | ""                | ""
+ * "/opt/usr/media/TEST" | "/opt/usr/media/" | "TEST"
+ * "/opt/usr/media/TEST/"| "/opt/usr/media/" | "TEST"
+ * "opt/usr/media/TEST"  | "opt/usr/media/"  | "TEST"
+ * "opt/usr/media/TEST/" | "opt/usr/media/"  | "TEST"
+ * "TEST"                | ""                | "TEST"
+ * "TEST/"               | ""                | "TEST"
+ * "/TEST/"              | "/"               | "TEST"
+ */
+extern void getBasePathAndName(const std::string& filepath,
+        std::string& out_basepath,
+        std::string& out_name);
+
+/**
+ * If path contains duplicated slashes they will be removed
+ *
+ * Note this function does not fix slash style '/', '\'
+ * (Linux/Windows)
+ *
+ * Example path:              | Result:
+ * ---------------------------+------------------------------
+ * "my/a//b/c/d/e"            | "my/a/b/c/d/e"
+ * "add\ff\\\g"               | "add\f\g"
+ * "first//second\\a\/"       | "first/second\a"  (mixed / with \)
+ */
+extern std::string removeDuplicatedSlashesFromPath(const std::string& path);
+
+/**
+ * Return true if last character of string is '/' or '\'
+ */
+extern bool isDirectoryPath(const std::string& path);
+
+/**
+ * If path contains trailing '/' or '\' it will be removed.
+ *
+ * Example path:              | Result:
+ * ---------------------------+------------------------------
+ * "documents/someName/"      | "documents/someName"
+ * "documents/yetAnotherName" | "documents/yetAnotherName"
+ */
+extern std::string removeTrailingDirectorySlashFromPath(const std::string& path);
+
+/**
+ * Returns FILE name without leading base path:
+ *
+ * Example path:              | Result:
+ * ---------------------------+------------------------------
+ * "documents/ABC/a.txt"      | "a.txt"
+ * "documents/A/X/Y/Z/my.log" | "my.log"
+ *
+ * "documents/A/B/C/"         | "" (fullpath is directory)
+ * "a.txt"                    | "a.txt"
+ * "A/"                       | "" (fullpath is directory)
+ */
+extern std::string stripBasePathFromPath(const std::string& fullpath);
+
+/**
+ * Returns path without last directory or file part
+ *
+ * Example path:              | Result:               | Extracted ending:
+ * ---------------------------+-----------------------+--------------
+ * "documents/ABC/a.txt"      | "documents/ABC/"      | "a.txt"
+ * "documents/A/X/Y/Z/my.log" | "documents/A/X/Y/Z/"  | "my.log"
+ *
+ * "documents/A/B/C/"         | "documents/A/B/"      | "C/"
+ * "a.txt"                    | ""                    | "a.txt"
+ * "A/"                       | ""                    | "A/"
+ */
+extern std::string getBasePathFromPath(const std::string& fullpath);
+
+extern std::string getArchiveLogMessage(const int errorCode, const std::string &hint);
+
+template <class T = DeviceAPI::Common::UnknownException>
+void throwArchiveException(const int errorCode, const std::string &hint)
+{
+    std::string log = getArchiveLogMessage(errorCode, hint);
+    LOGE("%s", log.c_str());
+    throw T(log.c_str());
+}
+
+} //namespace Archive
+} //namespace DeviceAPI
+
+#endif // __TIZEN_ARCHIVE_ARCHIVE_UTILS_H__
diff --git a/src/Archive/CMakeLists.txt b/src/Archive/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..6ad9c9e
--- /dev/null
@@ -0,0 +1,77 @@
+SET(TARGET_NAME ${archive_target})
+SET(DESTINATION_NAME ${archive_dest})
+SET(TARGET_IMPL_NAME ${archive_impl})
+SET(TARGET_CONFIG_NAME ${archive_config})
+
+PKG_CHECK_MODULES(platform_pkgs_archive REQUIRED minizip)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+SET(INCLUDE_DIRS
+    ${filesystem_include}
+    ${platform_pkgs_archive_INCLUDE_DIRS}
+)
+
+INCLUDE_DIRECTORIES(${INCLUDE_COMMON} ${INCLUDE_DIRS})
+MESSAGE(STATUS "${TARGET_NAME} module includes: INCLUDE_COMMON ${INCLUDE_DIRS}")
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${filesystem_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSArchiveManager.cpp
+    JSArchiveFile.cpp
+    JSArchiveFileEntry.cpp
+    ArchiveCallbackData.cpp
+    ArchiveManager.cpp
+    ArchiveFile.cpp
+    ArchiveFileEntry.cpp
+    Zip.cpp
+    UnZip.cpp
+    UnZipExtractRequest.cpp
+    ArchiveUtils.cpp
+    ZipAddRequest.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+
+SET(LINK_LIBS
+    ${filesystem_impl}
+    ${filesystem_config}
+    ${platform_pkgs_tizen_LIBRARIES}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME} ${LIBS_COMMON} ${LINK_LIBS})
+MESSAGE(STATUS "${TARGET_NAME} module links: LIBS_COMMON ${LINK_LIBS}")
+
+SET(SRCS_CONFIG
+    plugin_config.cpp
+)
+
+ADD_LIBRARY(${TARGET_CONFIG_NAME} SHARED ${SRCS_CONFIG})
+
+TARGET_LINK_LIBRARIES(${TARGET_CONFIG_NAME}
+    ${LIBS_COMMON}
+)
+
+SET(SRCS
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+    ${TARGET_CONFIG_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_CONFIG_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/archive
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Archive/JSArchiveFile.cpp b/src/Archive/JSArchiveFile.cpp
new file mode 100755 (executable)
index 0000000..6ac4e94
--- /dev/null
@@ -0,0 +1,535 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <SecurityExceptions.h>
+#include <GlobalContextManager.h>
+#include <File.h>
+#include <Path.h>
+#include <JSUtil.h>
+#include <FilesystemExternalUtils.h>
+#include <JSFile.h>
+#include <Export.h>
+
+#include "JSArchiveFile.h"
+#include "JSArchiveFileEntry.h"
+#include "JSFile.h"
+#include "ArchiveCallbackData.h"
+#include "ArchiveUtils.h"
+#include "plugin_config.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Archive {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Filesystem;
+
+namespace {
+const char* ARCHIVE_FILE = "ArchiveFile";
+const char* ARCHIVE_FILE_MODE = "mode";
+const char* ARCHIVE_FILE_DECOMPRESSED_SIZE = "decompressedSize";
+}
+
+JSClassDefinition JSArchiveFile::m_classInfo = {
+        0,                      // version
+        kJSClassAttributeNone,  // attributes
+        ARCHIVE_FILE,           // class name
+        NULL,                   // parent class
+        m_property,             // static values
+        m_function,             // static functions
+        initialize,             // initialize
+        finalize,               // finalize
+        NULL,                   // hasProperty
+        NULL,                   // getProperty
+        NULL,                   // setProperty
+        NULL,                   // deleteProperty
+        NULL,                   // getPropertyNames
+        NULL,                   // callAsFunctionvalidator
+        NULL,                   // constructor
+        NULL,
+        NULL                    // convertToType
+};
+
+const JSClassDefinition* JSArchiveFile::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSStaticFunction JSArchiveFile::m_function[] = {
+        { ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ADD, add, kJSPropertyAttributeNone },
+        { ARCHIVE_FUNCTION_API_ARCHIVE_FILE_EXTRACT_ALL, extractAll, kJSPropertyAttributeNone },
+        { ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRIES, getEntries, kJSPropertyAttributeNone },
+        { ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRY_BY_NAME, getEntryByName, kJSPropertyAttributeNone },
+        { ARCHIVE_FUNCTION_API_ARCHIVE_FILE_CLOSE, close, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+JSStaticValue JSArchiveFile::m_property[] =
+{
+    {ARCHIVE_FILE_MODE, getMode, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {ARCHIVE_FILE_DECOMPRESSED_SIZE, getDecompressedSize, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSArchiveFile::m_jsClassRef = JSClassCreate(JSArchiveFile::getClassInfo());
+
+const DLL_EXPORT JSClassRef JSArchiveFile::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSArchiveFile::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSArchiveFile::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ArchiveFileHolder* priv =
+            static_cast<ArchiveFileHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+ArchiveFilePtr JSArchiveFile::getPrivateObject(JSContextRef context,
+        JSValueRef value_ref)
+{
+    if (!JSValueIsObjectOfClass(context, value_ref, getClassRef())) {
+        LOGE("TypeMismatch");
+        throw TypeMismatchException("TypeMismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value_ref);
+    ArchiveFileHolder* priv = static_cast<ArchiveFileHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    return priv->ptr;
+}
+
+JSObjectRef JSArchiveFile::makeJSObject(JSContextRef context,
+        ArchiveFilePtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw TypeMismatchException("Native is null");
+    }
+
+    ArchiveFileHolder* priv = new ArchiveFileHolder;
+    if(!priv){
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context,
+            getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+JSValueRef JSArchiveFile::getMode(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        std::string fm_string = fileModeToString(priv->getFileMode());
+        return JSUtil::toJSValueRef(context, fm_string);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSArchiveFile::getDecompressedSize(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getDecompressedSize());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSArchiveFile::add(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = ARCHIVE_CHECK_ACCESS(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ADD);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    AddProgressCallback *callback = NULL;
+
+    try {
+        ArchiveFilePtr priv = JSArchiveFile::getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) AddProgressCallback(g_ctx);
+        if(!callback) {
+            LOGE("Couldn't allocate AddProgressCallback");
+            throw UnknownException("Memory allocation error");
+        }
+
+        // set all callbacks
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setProgressCallback(validator.toFunction(3, true));
+
+        // process sourceFile argument (File or path)
+        if (validator.isOmitted(0)) {
+            LOGE("FileReference not given");
+            throw TypeMismatchException("Missing argument");
+        }
+        FilePtr file_ptr = fileReferenceToFile(context, arguments[0]);
+
+        // prepare empty archive file and assign File pointer
+        ArchiveFileEntryPtr afep = ArchiveFileEntryPtr(
+            new ArchiveFileEntry(file_ptr));
+        callback->setFileEntry(afep);
+
+        callback->setBasePath(file_ptr->getNode()->getPath()->getPath());
+        LOGD("base path:%s base virt:%s", callback->getBasePath().c_str(),
+                callback->getBaseVirtualPath().c_str());
+
+        // check and set options
+        if(!validator.isOmitted(4)){
+            if(validator.isUndefined(4)){
+                LOGE("Type mismath error");
+                throw TypeMismatchException("ArchiveFileEntryOptions is undefined");
+            }
+            LOGD("Processing dictionary");
+            JSObjectRef dictionary = validator.toObject(4,true);
+            JSValueRef dic_destination = JSUtil::getProperty(
+                            context, dictionary, ARCHIVE_FILE_ENTRY_OPT_DEST);
+            if (!JSValueIsUndefined(context, dic_destination)) {
+                LOGD("Setting destination path");
+                afep->setDestination(
+                        JSUtil::JSValueToString(context, dic_destination));
+            }
+            JSValueRef dic_strip = JSUtil::getProperty(
+                            context, dictionary, ARCHIVE_FILE_ENTRY_OPT_STRIP);
+            if (!JSValueIsUndefined(context, dic_strip)) {
+                LOGD("Setting strip option");
+                afep->setStriped(
+                        JSUtil::JSValueToBoolean(context, dic_strip));
+            }
+            JSValueRef dic_compression_level = JSUtil::getProperty(
+                            context, dictionary, ARCHIVE_FILE_ENTRY_OPT_COMPRESSION_LEVEL);
+            if (!JSValueIsUndefined(context, dic_compression_level)) {
+                LOGD("Setting compression level");
+                afep->setCompressionLevel(
+                        JSUtil::JSValueToULong(context, dic_compression_level));
+            }
+        }
+
+        if (!priv->isAllowedOperation(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ADD)) {
+            LOGE("Not allowed operation");
+            throw InvalidAccessException("Not allowed operation");
+        }
+
+        long op_id = priv->add(callback);
+        LOGD("Run add request with op_id: %d", op_id);
+
+        return JSUtil::toJSValueRef(context, op_id);
+    }
+    catch (const NotFoundException &nfe) {
+        callback->setError(nfe.getName(), nfe.getMessage());
+    }
+    catch (const IOException &ioe) {
+        callback->setError(ioe.getName(), ioe.getMessage());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("add BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("add fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "add fails");
+    }
+
+    if (callback && callback->isError()) {
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(
+                context,
+                callback->getErrorName(),
+                callback->getErrorMessage());
+        callback->callErrorCallback(errobj);
+        delete callback;
+        callback = NULL;
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSArchiveFile::extractAll(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = ARCHIVE_CHECK_ACCESS(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_EXTRACT_ALL);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    ExtractAllProgressCallback *callback = NULL;
+
+    try {
+        ArchiveFilePtr priv = JSArchiveFile::getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new ExtractAllProgressCallback(g_ctx);
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setProgressCallback(validator.toFunction(3, true));
+
+        // process destinationDirectory (File or path)
+        if (validator.isOmitted(0)) {
+            LOGE("FileReference not given");
+            throw TypeMismatchException("Missing argument");
+        }
+        FilePtr file_ptr = fileReferenceToFile(context, arguments[0]);
+
+        // prepare empty archive file and assign File pointer
+        callback->setDirectory(file_ptr);
+
+        // overwrite is optional - if not given use default (false)
+        bool opt_overwrite = validator.toBool(4, true, false);
+        callback->setOverwrite(opt_overwrite);
+
+        if (!priv->isAllowedOperation(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_EXTRACT_ALL)) {
+            LOGE("Not allowed operation");
+            throw InvalidAccessException("Not allowed operation");
+        }
+
+        long op_id = priv->extractAll(callback);
+        LOGD("Run extract all request with op_id: %d", op_id);
+
+        return JSUtil::toJSValueRef(context, op_id);
+    }
+    catch (const NotFoundException &nfe) {
+        callback->setError(nfe.getName(), nfe.getMessage());
+    }
+    catch (const IOException &ioe) {
+        callback->setError(ioe.getName(), ioe.getMessage());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("extractAll BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("extractAll fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "extractAll fails");
+    }
+
+    if (callback && callback->isError()) {
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(
+                context,
+                callback->getErrorName(),
+                callback->getErrorMessage());
+        callback->callErrorCallback(errobj);
+        delete callback;
+        callback = NULL;
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSArchiveFile::getEntries(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status =
+                ARCHIVE_CHECK_ACCESS(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRIES);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    GetEntriesCallbackData *callback = NULL;
+
+    try {
+        ArchiveFilePtr priv = JSArchiveFile::getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new GetEntriesCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(0));
+        callback->setErrorCallback(validator.toFunction(1, true));
+
+        if (!priv->isAllowedOperation(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRIES)) {
+            LOGE("Not allowed operation");
+            throw InvalidAccessException("Not allowed operation");
+        }
+
+        long op_id = priv->getEntries(callback);
+        LOGD("Run get entries request with op_id: %d", op_id);
+
+        return JSUtil::toJSValueRef(context, op_id);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getEntries BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("getEntries fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getEntries fails");
+    }
+}
+
+JSValueRef JSArchiveFile::getEntryByName(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status =
+                ARCHIVE_CHECK_ACCESS(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRIES);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    GetEntryByNameCallbackData *callback = NULL;
+
+    try {
+        ArchiveFilePtr priv = JSArchiveFile::getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new GetEntryByNameCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setName(validator.toString(0));
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        if (!priv->isAllowedOperation(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRY_BY_NAME)) {
+            LOGE("Not allowed operation");
+            throw InvalidAccessException("Not allowed operation");
+        }
+
+        long op_id = priv->getEntryByName(callback);
+        LOGD("Run get entry by name request with op_id: %d", op_id);
+
+        return JSUtil::toJSValueRef(context, op_id);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getEntryByName BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("getEntryByName fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getEntryByName fails");
+    }
+}
+
+JSValueRef JSArchiveFile::close(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try{
+        ArchiveFilePtr priv = JSArchiveFile::getPrivateObject(context, thisObject);
+
+        priv->close();
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("close failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("close failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // Archive
+} // DeviceAPI
diff --git a/src/Archive/JSArchiveFile.h b/src/Archive/JSArchiveFile.h
new file mode 100644 (file)
index 0000000..72bf13a
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef _TIZEN_ARCHIVE_JS_ARCHIVE_FILE_H_
+#define _TIZEN_ARCHIVE_JS_ARCHIVE_FILE_H_
+#include <JavaScriptCore/JavaScript.h>
+
+#include "ArchiveFile.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+
+class JSArchiveFile {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static ArchiveFilePtr getPrivateObject(JSContextRef context,
+            JSValueRef value_ref);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            ArchiveFilePtr native);
+
+private:
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getMode(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDecompressedSize(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef add(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef extractAll(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getEntries(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getEntryByName(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef close(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+};
+
+} // Archive
+} // DeviceAPI
+
+#endif // _TIZEN_ARCHIVE_JS_ARCHIVE_FILE_H_
diff --git a/src/Archive/JSArchiveFileEntry.cpp b/src/Archive/JSArchiveFileEntry.cpp
new file mode 100755 (executable)
index 0000000..1697682
--- /dev/null
@@ -0,0 +1,331 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <GlobalContextManager.h>
+#include <JSFile.h>
+#include <File.h>
+#include <Path.h>
+#include <FilesystemExternalUtils.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+#include <SecurityExceptions.h>
+
+#include "ArchiveCallbackData.h"
+#include "ArchiveFile.h"
+#include "JSArchiveFileEntry.h"
+#include "ArchiveUtils.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Filesystem;
+
+namespace {
+const char* ARCHIVE_FILE_ENTRY = "ArchiveFileEntry";
+const char* ARCHIVE_FILE_ENTRY_NAME = "name";
+const char* ARCHIVE_FILE_ENTRY_SIZE = "size";
+const char* ARCHIVE_FILE_ENTRY_COMPRESSED_SIZE = "compressedSize";
+const char* ARCHIVE_FILE_ENTRY_MODIFIED = "modified";
+}
+
+const char* ARCHIVE_FILE_ENTRY_OPT_DEST = "destination";
+const char* ARCHIVE_FILE_ENTRY_OPT_STRIP = "stripSourceDirectory";
+const char* ARCHIVE_FILE_ENTRY_OPT_COMPRESSION_LEVEL = "compressionLevel";
+
+struct ArchiveFileEntryHolder{
+    ArchiveFileEntryPtr ptr;
+};
+
+JSClassDefinition JSArchiveFileEntry::m_classInfo = {
+        0,                      // version
+        kJSClassAttributeNone,  // attributes
+        ARCHIVE_FILE_ENTRY,     // class name
+        NULL,                   // parent class
+        m_property,             // static values
+        m_function,             // static functions
+        initialize,             // initialize
+        finalize,               // finalize
+        NULL,                   // hasProperty
+        NULL,                   // getProperty
+        NULL,                   // setProperty
+        NULL,                   // deleteProperty
+        NULL,                   // getPropertyNames
+        NULL,                   // callAsFunctionvalidator
+        NULL,                   // constructor
+        NULL,                   // hasInstance
+        NULL                    // convertToType
+};
+
+const JSClassDefinition* JSArchiveFileEntry::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSStaticFunction JSArchiveFileEntry::m_function[] = {
+        { ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ENTRY_EXTRACT, extract, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+JSStaticValue JSArchiveFileEntry::m_property[] =
+{
+    {ARCHIVE_FILE_ENTRY_NAME, getName, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {ARCHIVE_FILE_ENTRY_SIZE, getSize, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {ARCHIVE_FILE_ENTRY_COMPRESSED_SIZE, getCompressedSize, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {ARCHIVE_FILE_ENTRY_MODIFIED, getModified, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSArchiveFileEntry::m_jsClassRef = JSClassCreate(JSArchiveFileEntry::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSArchiveFileEntry::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSArchiveFileEntry::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSArchiveFileEntry::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ArchiveFileEntryHolder* priv =
+            static_cast<ArchiveFileEntryHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+ArchiveFileEntryPtr JSArchiveFileEntry::getPrivateObject(JSContextRef context,
+        JSValueRef value_ref)
+{
+    if (!JSValueIsObjectOfClass(context, value_ref, getClassRef())) {
+        LOGE("TypeMismatch");
+        throw TypeMismatchException("TypeMismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value_ref);
+    ArchiveFileEntryHolder* priv = static_cast<ArchiveFileEntryHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    return priv->ptr;
+}
+
+JSObjectRef JSArchiveFileEntry::makeJSObject(JSContextRef context,
+        ArchiveFileEntryPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw TypeMismatchException("Native is null");
+    }
+
+    ArchiveFileEntryHolder* priv = new ArchiveFileEntryHolder;
+    if(!priv){
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context,
+            getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+JSValueRef JSArchiveFileEntry::getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getName());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSArchiveFileEntry::getSize(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getSize());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSArchiveFileEntry::getCompressedSize(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getCompressedSize());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSArchiveFileEntry::getModified(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::makeDateObject(context, priv->getModified());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSArchiveFileEntry::extract(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status =
+                ARCHIVE_CHECK_ACCESS(ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ENTRY_EXTRACT);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    ExtractEntryProgressCallback *callback = NULL;
+
+    try {
+        ArchiveFileEntryPtr priv = JSArchiveFileEntry::getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new(std::nothrow) ExtractEntryProgressCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        if(!callback) {
+            LOGD("Couldn't allocate ExtractEntryProgressCallback");
+            throw UnknownException("Memory allocation error");
+        }
+
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setProgressCallback(validator.toFunction(3, true));
+        callback->setStripName(validator.toBool(4,true));
+        callback->setOverwrite(validator.toBool(5,true));
+
+        if (validator.isOmitted(0)) {
+            LOGE("FileReference not given");
+            throw TypeMismatchException("Missing argument");
+        }
+
+        FilePtr file_ptr = fileReferenceToFile(context, arguments[0]);
+        callback->setDirectory(file_ptr);
+
+        long op_id = priv->extractTo(callback);
+        LOGD("Run extract request with op_id: %d", op_id);
+
+        return JSUtil::toJSValueRef(context, op_id);
+    }
+    catch (const NotFoundException &nfe) {
+        callback->setError(nfe.getName(), nfe.getMessage());
+    }
+    catch (const IOException &ioe) {
+        callback->setError(ioe.getName(), ioe.getMessage());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("extract caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("extract fails");
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "extract fails");
+    }
+
+    if (callback && callback->isError()) {
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(
+                context,
+                callback->getErrorName(),
+                callback->getErrorMessage());
+        callback->callErrorCallback(errobj);
+        delete callback;
+        callback = NULL;
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+
+} // Archive
+} // DeviceAPI
diff --git a/src/Archive/JSArchiveFileEntry.h b/src/Archive/JSArchiveFileEntry.h
new file mode 100644 (file)
index 0000000..c893e4b
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef _TIZEN_ARCHIVE_JS_ARCHIVE_FILE_ENTRY_H_
+#define _TIZEN_ARCHIVE_JS_ARCHIVE_FILE_ENTRY_H_
+#include <JavaScriptCore/JavaScript.h>
+
+#include "ArchiveFileEntry.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+// these constants are used in JSArchiveFile.cpp and JSArchiveFileEntry.cpp
+extern const char* ARCHIVE_FILE_ENTRY_OPT_DEST;
+extern const char* ARCHIVE_FILE_ENTRY_OPT_STRIP;
+extern const char* ARCHIVE_FILE_ENTRY_OPT_COMPRESSION_LEVEL;
+
+class JSArchiveFileEntry {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static ArchiveFileEntryPtr getPrivateObject(JSContextRef context,
+            JSValueRef velue_ref);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            ArchiveFileEntryPtr native);
+
+private:
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getSize(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCompressedSize(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getModified(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef extract(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // Archive
+} // DeviceAPI
+
+#endif // _TIZEN_ARCHIVE_JS_ARCHIVE_FILE_ENTRY_H_
diff --git a/src/Archive/JSArchiveManager.cpp b/src/Archive/JSArchiveManager.cpp
new file mode 100755 (executable)
index 0000000..2ba13b8
--- /dev/null
@@ -0,0 +1,295 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Logger.h>
+
+#include <Export.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <SecurityExceptions.h>
+#include <FilesystemExternalUtils.h>
+#include <JSFile.h>
+#include <Path.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+
+#include "JSArchiveManager.h"
+#include "ArchiveManager.h"
+#include "ArchiveUtils.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Filesystem;
+
+namespace {
+const char* ARCHIVE_MANAGER = "ArchiveManager";
+const char* ARCHIVE_FILE_OPTIONS_OVERWRITE = "overwrite";
+}
+
+JSClassDefinition JSArchiveManager::m_classInfo = {
+        0,                      // version
+        kJSClassAttributeNone,  // attributes
+        ARCHIVE_MANAGER,        // class name
+        NULL,                   // parent class
+        NULL,                   // static values
+        m_function,             // static functions
+        initialize,             // initialize
+        finalize,               // finalize
+        NULL,                   // hasProperty
+        NULL,                   // getProperty
+        NULL,                   // setProperty
+        NULL,                   // deleteProperty
+        NULL,                   // getPropertyNames
+        NULL,                   // callAsFunctionvalidator
+        NULL,                   // constructor
+        NULL,                   // hasInstance
+        NULL                    // convertToType
+};
+
+const JSClassDefinition* JSArchiveManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSStaticFunction JSArchiveManager::m_function[] = {
+        { ARCHIVE_FUNCTION_API_ARCHIVE_MANAGER_ABORT, abort, kJSPropertyAttributeNone },
+        { ARCHIVE_FUNCTION_API_ARCHIVE_MANAGER_OPEN, open, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+JSClassRef JSArchiveManager::m_jsClassRef = JSClassCreate(JSArchiveManager::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSArchiveManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSArchiveManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSArchiveManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+JSValueRef JSArchiveManager::open(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = ARCHIVE_CHECK_ACCESS(ARCHIVE_FUNCTION_API_ARCHIVE_MANAGER_OPEN);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    OpenCallbackData *open_cb = NULL;
+    try{
+        long op_id = -1;
+        ArgumentValidator validator(context, argumentCount, arguments);
+        FilePtr file_ptr;
+        // process file mode argument (is checked when opening archive)
+        std::string fm_string = validator.toString(1);
+        // in case of invalid file mode exception is thrown
+        FileMode fm = stringToFileMode(fm_string);
+
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        // set callbacks
+        open_cb = new (std::nothrow) OpenCallbackData(g_ctx);
+        if(!open_cb) {
+            LOGE("Couldn't allocate OpenCallbackData");
+            throw UnknownException("Memory allocation error");
+        }
+        open_cb->setSuccessCallback(validator.toFunction(2));
+        open_cb->setErrorCallback(validator.toFunction(3, true));
+
+        bool overwrite = false;
+        // check and set options (if given)
+        if(!validator.isOmitted(4)) {
+            if(validator.isUndefined(4)) {
+                LOGE("Type mismath error");
+                throw TypeMismatchException("ArchiveFileOptions is undefined");
+            }
+
+            LOGD("Processing options dictionary.");
+            JSObjectRef options = validator.toObject(4, true);
+            JSValueRef opt_overwrite = JSUtil::getProperty(context, options,
+                    ARCHIVE_FILE_OPTIONS_OVERWRITE);
+            if (!JSValueIsUndefined(context, opt_overwrite)) {
+                overwrite = JSUtil::JSValueToBoolean(context, opt_overwrite);
+                LOGD("Overwrite: %d", overwrite);
+
+                if(FileMode::ADD == fm) {
+                    LOGW("File mode is: \"a\" -> overwrite will be ignored");
+                }
+            }
+        }
+
+        std::string location_string = validator.toString(0);
+        std::string location_full_path;
+
+        LOGD("location_string: %s", location_string.c_str());
+
+        // process file reference
+        try {
+            file_ptr = fileReferenceToFile(context, arguments[0]);
+            const std::string full_path = file_ptr->getNode()->getPath()->getFullPath();
+            LOGD("open: %s mode: 0x%x overwrite: %d", full_path.c_str(), fm, overwrite);
+
+            if(FileMode::WRITE == fm || FileMode::READ_WRITE == fm) {
+                if(overwrite) {
+                    try {
+                        //Store requested full path
+                        location_string = std::string();    // remove "[object File]"
+                        location_full_path = full_path;
+
+                        LOGD("Deleting existing file: %s", full_path.c_str());
+                        file_ptr->getNode()->remove(OPT_RECURSIVE);
+                        file_ptr.reset();   //We need to create new empty file
+                    } catch(...) {
+                        LOGE("Couldn't remove existing file: %s", full_path.c_str());
+                        throw Common::IOException("Could not remove existing file");
+                    }
+                }
+                else if(FileMode::WRITE == fm) {
+                    LOGE("open: %s with mode: \"w\" file exists and overwrite is FALSE!"
+                            " throwing InvalidModificationException", full_path.c_str());
+                    throw Common::InvalidModificationException("Zip archive already exists");
+                }
+            }
+        } catch (const NotFoundException& nfe) {
+            LOGD("location_string: %s is not file reference", location_string.c_str());
+            file_ptr.reset();
+        }
+
+        if(!file_ptr) {
+            NodePtr node_ptr;
+
+            if(FileMode::WRITE == fm ||
+                    FileMode::READ_WRITE == fm ||
+                    FileMode::ADD == fm) {
+
+                if(location_full_path.empty()) {
+                    location_full_path = External::fromVirtualPath(location_string, g_ctx);
+                }
+                LOGD("Archive file not found - trying to create new one at: "
+                        "original: %s full: %s", location_string.c_str(),
+                        location_full_path.c_str());
+
+                PathPtr path = Path::create(location_full_path);
+
+                std::string parent_path_string = path->getPath();
+                PathPtr parent_path = Path::create(parent_path_string);
+                LOGD("Parent path: %s", parent_path_string.c_str());
+
+                NodePtr parent_node = Node::resolve(parent_path);
+                parent_node->setPermissions(PERM_READ | PERM_WRITE);
+                std::string filename = path->getName();
+                LOGD("File name: %s", filename.c_str());
+                node_ptr = parent_node->createChild(Path::create(filename), NT_FILE);
+            }
+            else {
+                LOGE("Archive file not found");
+                throw Common::NotFoundException("Archive file not found");
+            }
+            file_ptr = FilePtr(new File(node_ptr, File::PermissionList()));
+        }
+
+        // prepare empty archive file and assign File pointer
+        ArchiveFilePtr afp = ArchiveFilePtr(new ArchiveFile(fm));
+        afp->setFile(file_ptr);
+        afp->setOverwrite(overwrite);
+        open_cb->setArchiveFile(afp);
+
+        op_id = ArchiveManager::getInstance().open(open_cb);
+        return JSUtil::toJSValueRef(context, op_id);
+    }
+    catch (const NotFoundException &nfe) {
+       open_cb->setError(nfe.getName(), nfe.getMessage());
+    }
+    catch (const IOException &ioe) {
+       open_cb->setError(ioe.getName(), ioe.getMessage());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Open failed: %s", error.getMessage().c_str());
+        delete open_cb;
+        open_cb = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Open failed");
+        delete open_cb;
+        open_cb = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    if (open_cb && open_cb->isError()) {
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                open_cb->getErrorName(),
+                open_cb->getErrorMessage());
+        open_cb->callErrorCallback(errobj);
+        delete open_cb;
+        open_cb = NULL;
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+JSValueRef JSArchiveManager::abort(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        long operation_id = validator.toLong(0);
+
+        ArchiveManager::getInstance().abort(operation_id);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Abort failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Abort failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // Archive
+} // DeviceAPI
diff --git a/src/Archive/JSArchiveManager.h b/src/Archive/JSArchiveManager.h
new file mode 100644 (file)
index 0000000..ce0cb70
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef _TIZEN_ARCHIVE_JS_ARCHIVE_MANAGER_H_
+#define _TIZEN_ARCHIVE_JS_ARCHIVE_MANAGER_H_
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Archive {
+
+class JSArchiveManager {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef open(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef abort(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // Archive
+} // DeviceAPI
+
+#endif // _TIZEN_ARCHIVE_JS_ARCHIVE_MANAGER_H_
diff --git a/src/Archive/UnZip.cpp b/src/Archive/UnZip.cpp
new file mode 100644 (file)
index 0000000..310466b
--- /dev/null
@@ -0,0 +1,430 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "UnZip.h"
+
+#include <cstdio>
+#include <errno.h>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <File.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <Node.h>
+#include <Path.h>
+#include <PlatformException.h>
+
+#include "ArchiveUtils.h"
+#include "UnZipExtractRequest.h"
+#include "ArchiveFile.h"
+
+namespace DeviceAPI {
+
+using namespace DeviceAPI::Common;
+
+namespace Archive {
+
+UnZip::UnZip(const std::string& filename) :
+        m_zipfile_name(filename),
+        m_unzip(NULL),
+        m_default_buffer_size(1024 * 1024)
+{
+    LOGD("Entered");
+
+    m_unzip = unzOpen(filename.c_str());
+    if(!m_unzip) {
+        LOGE("unzOpen returned NULL : It means the file is invalid.");
+        throw InvalidValuesException("Failed to open zip file");
+    }
+    m_is_open = true;
+}
+
+UnZip::~UnZip()
+{
+    close();
+}
+
+void UnZip::close()
+{
+    LOGD("Entered");
+    if(!m_is_open) {
+        LOGD("Unzip already closed - exiting");
+        return;
+    }
+
+    int errclose = unzClose(m_unzip);
+    m_unzip = NULL;
+
+    if (errclose != UNZ_OK) {
+        LOGE("ret: %d",errclose);
+        throwArchiveException(errclose, "unzClose()");
+    }
+    m_is_open = false;
+}
+
+UnZipPtr UnZip::open(const std::string& filename)
+{
+    LOGD("Entered");
+    return UnZipPtr(new UnZip(filename));
+}
+
+ArchiveFileEntryPtrMapPtr UnZip::listEntries(unsigned long *decompressedSize)
+{
+    if(!m_is_open) {
+        LOGE("Failed to get list of entries - UnZip closed");
+        throw UnknownException("Failed to get list of files in zip archive");
+    }
+    unz_global_info gi;
+    int err = unzGetGlobalInfo (m_unzip, &gi);
+    if (UNZ_OK != err) {
+        LOGE("ret: %d",err);
+        throwArchiveException(err, "unzGetGlobalInfo()");
+    }
+
+    char filename_inzip[512];
+    unz_file_info file_info;
+
+    ArchiveFileEntryPtrMapPtr map = ArchiveFileEntryPtrMapPtr(
+            new ArchiveFileEntryPtrMap());
+
+    unsigned long totalDecompressed = 0;
+
+    err = unzGoToFirstFile(m_unzip);
+    if (err != UNZ_OK) {
+        LOGW("%s",getArchiveLogMessage(err, "unzGoToFirstFile()").c_str());
+    }
+
+    for (uLong i = 0; i < gi.number_entry; i++) {
+
+        err = unzGetCurrentFileInfo(m_unzip, &file_info,
+                filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
+        if (err != UNZ_OK) {
+            LOGE("ret: %d",err);
+            throwArchiveException(err, "unzGetCurrentFileInfo()");
+        }
+
+        LOGD("file: %s | unc size: %d | comp size: %d", filename_inzip,
+                file_info.uncompressed_size, file_info.compressed_size);
+
+        ArchiveFileEntryPtr entry = ArchiveFileEntryPtr(new ArchiveFileEntry());
+        entry->setName(filename_inzip);
+        entry->setSize(file_info.uncompressed_size);
+        entry->setCompressedSize(file_info.compressed_size);
+
+        totalDecompressed += file_info.uncompressed_size;
+
+        tm date;// = file_info.tmu_date;
+        date.tm_sec = file_info.tmu_date.tm_sec;
+        date.tm_min = file_info.tmu_date.tm_min;
+        date.tm_hour = file_info.tmu_date.tm_hour;
+        date.tm_mday = file_info.tmu_date.tm_mday;
+        date.tm_mon = file_info.tmu_date.tm_mon;
+        date.tm_year = file_info.tmu_date.tm_year - 1900;
+        date.tm_wday = 0;
+        date.tm_yday = 0;
+        date.tm_isdst = 0;
+        LOGD("%d, %d, %d, %d, %d, %d", date.tm_hour, date.tm_min, date.tm_sec, date.tm_mday, date.tm_mon, date.tm_year);
+        entry->setModified(mktime(&date));
+
+        map->insert(std::make_pair(filename_inzip, entry));
+
+        if ( (i+1) < gi.number_entry) {
+
+            err = unzGoToNextFile(m_unzip);
+            if (UNZ_OK != err) {
+                LOGE("ret: %d",err);
+                throwArchiveException(err, "unzGoToNextFile()");
+            }
+        }
+    }
+
+    (*decompressedSize) = totalDecompressed;
+
+    return map;
+}
+
+void UnZip::extractAllFilesTo(const std::string& extract_path,
+        ExtractAllProgressCallback* callback)
+{
+    if(!m_is_open) {
+        LOGE("Failed to extract files - UnZip closed");
+        throw UnknownException("Failed to extract zip archive");
+    }
+
+    //
+    // Calculate number of entries to extract and total number of bytes
+    //
+    unz_global_info gi;
+    updateCallbackWithArchiveStatistics(callback, gi);
+
+    //
+    // Begin extracting entries
+    //
+    int err = unzGoToFirstFile(m_unzip);
+    if (err != UNZ_OK) {
+        LOGW("%s",getArchiveLogMessage(err, "unzGoToFirstFile()").c_str());
+    }
+
+    for (uLong i = 0; i < gi.number_entry; i++) {
+
+        if (callback->isCanceled()) {
+            LOGD("Operation cancelled");
+            throw OperationCanceledException();
+        }
+
+        extractCurrentFile(extract_path, std::string(), callback);
+
+        if ((i + 1) < gi.number_entry) {
+            err = unzGoToNextFile(m_unzip);
+            if (UNZ_OK != err) {
+                LOGE("ret: %d",err);
+                throwArchiveException(err, "unzGoToNextFile()");
+            }
+        }
+    }
+
+    callback->callSuccessCallbackOnMainThread();
+    callback = NULL;
+}
+
+struct ExtractDataHolder
+{
+    UnZip* unzip;
+    ExtractEntryProgressCallback* callback;
+    std::string root_output_path;
+};
+
+void UnZip::extractTo(ExtractEntryProgressCallback* callback)
+{
+    if(!m_is_open) {
+        LOGE("Extract archive file entry failed - UnZip closed");
+        throw UnknownException("Extract archive file entry failed");
+    }
+
+    if(!callback) {
+        LOGE("callback is NULL");
+        throw UnknownException("Extract archive file entry failed");
+    }
+
+    if(!callback->getArchiveFileEntry()) {
+        LOGE("callback->getArchiveFileEntry() is NULL");
+        throw UnknownException("Extract archive file entry failed");
+    }
+
+    Filesystem::FilePtr out_dir = callback->getDirectory();
+    if(!out_dir) {
+        LOGE("Output directory is not valid");
+        throw InvalidValuesException("Output directory is not correct");
+    }
+
+    Filesystem::NodePtr out_node = out_dir->getNode();
+    if(!out_node) {
+        LOGE("Output directory is not valid");
+        throw InvalidValuesException("Output directory is not correct");
+    }
+
+    Filesystem::PathPtr out_path = out_node->getPath();
+    if(!out_path) {
+        LOGE("Output directory is not valid");
+        throw InvalidValuesException("Output directory is not correct");
+    }
+
+    auto entry_name_in_zip = callback->getArchiveFileEntry()->getName();
+    auto root_output_path = out_path->getFullPath();
+    LOGD("Extract: [%s] to root output directory: [%s] (stripBasePath: [%s])",
+            entry_name_in_zip.c_str(),
+            root_output_path.c_str(),
+            callback->getStripBasePath().c_str());
+
+    //
+    // Calculate number of entries to extract and total number of bytes
+    //
+    unz_global_info gi;
+    updateCallbackWithArchiveStatistics(callback, gi, entry_name_in_zip);
+
+    //
+    // Begin extracting entries
+    //
+
+    ExtractDataHolder h;
+    h.unzip = this;
+    h.callback = callback;
+    h.root_output_path = root_output_path;
+
+    // this loop call internally progress callbacks
+    IterateFilesInZip(gi, entry_name_in_zip, callback, extractItFunction, &h);
+
+    // after finish extracting success callback will be called
+    callback->callSuccessCallbackOnMainThread();
+    callback = NULL;
+}
+
+void UnZip::extractItFunction(const std::string& file_name, unz_file_info& file_info,
+        void* user_data)
+{
+    ExtractDataHolder* h = static_cast<ExtractDataHolder*>(user_data);
+    if(!h) {
+        LOGE("ExtractDataHolder is NULL!");
+        throw UnknownException("Could not list content of zip archive");
+    }
+
+    h->unzip->extractCurrentFile(h->root_output_path,
+            h->callback->getStripBasePath(),
+            h->callback);
+}
+
+unsigned int UnZip::IterateFilesInZip(unz_global_info& gi,
+        const std::string& entry_name_in_zip,
+        OperationCallbackData* callback,
+        UnZip::IterateFunction itfunc,
+        void* user_data)
+{
+    int err = unzGoToFirstFile(m_unzip);
+    if (UNZ_OK != err) {
+        LOGW("%s",getArchiveLogMessage(err, "unzGoToFirstFile()").c_str());
+    }
+
+    unsigned int num_file_or_folder_matched = 0;
+    const bool is_directory = isDirectoryPath(entry_name_in_zip);
+
+    unz_file_info cur_file_info;
+    char tmp_fname[512];
+
+    for (uLong i = 0; i < gi.number_entry; i++) {
+
+        if (callback->isCanceled()) {
+            LOGD("Operation cancelled");
+            throw OperationCanceledException();
+        }
+
+        err = unzGetCurrentFileInfo(m_unzip, &cur_file_info,
+                tmp_fname, sizeof(tmp_fname), NULL, 0, NULL, 0);
+        if (UNZ_OK != err) {
+            LOGE("ret: %d",err);
+            throwArchiveException(err, "unzGetCurrentFileInfo()");
+        }
+
+        const std::string cur_filename_in_zip(tmp_fname);
+        bool match = true;
+
+        if(!entry_name_in_zip.empty()) {
+            if(is_directory) {
+                //If entry_name_in_zip is pointing at directory we need to check each entry in
+                //zip if its path starts with entry_name_in_zip
+                match = (0 == cur_filename_in_zip.find(entry_name_in_zip));
+            } else {
+                //If entry name points to file we only extract entry with matching name
+                match = (cur_filename_in_zip == entry_name_in_zip);
+            }
+        }
+
+        if(match) {
+            itfunc(cur_filename_in_zip, cur_file_info, user_data);
+            ++num_file_or_folder_matched;
+        }
+
+        if ((i + 1) < gi.number_entry) {
+            err = unzGoToNextFile(m_unzip);
+            if (UNZ_OK != err) {
+                LOGE("ret: %d",err);
+                throwArchiveException(err, "unzGoToNextFile()");
+            }
+        }
+    }
+
+    return num_file_or_folder_matched;
+}
+
+void UnZip::extractCurrentFile(const std::string& extract_path,
+        const std::string& base_strip_path,
+        BaseProgressCallback* callback)
+{
+    LOGD("Entered");
+
+    if (callback->isCanceled()) {
+        LOGD("Operation cancelled");
+        throw OperationCanceledException();
+    }
+
+    LOGD("extract_path: [%s] base_strip_path: [%s] ", extract_path.c_str(),
+            base_strip_path.c_str());
+    UnZipExtractRequest::execute(*this, extract_path, base_strip_path, callback);
+}
+
+struct ArchiveStatistics
+{
+    ArchiveStatistics() : uncompressed_size(0),
+            number_of_files(0),
+            number_of_folders(0) {}
+
+    unsigned long uncompressed_size;
+    unsigned long number_of_files;
+    unsigned long number_of_folders;
+};
+
+void generateArchiveStatistics(const std::string& file_name, unz_file_info& file_info,
+         void* user_data)
+{
+    if(user_data) {
+        ArchiveStatistics* astats = static_cast<ArchiveStatistics*>(user_data);
+        astats->uncompressed_size += file_info.uncompressed_size;
+
+        if(isDirectoryPath(file_name)) {
+            astats->number_of_folders += 1;
+        }
+        else {
+            astats->number_of_files += 1;
+        }
+    }
+}
+
+void UnZip::updateCallbackWithArchiveStatistics(ExtractAllProgressCallback* callback,
+        unz_global_info& out_global_info,
+        const std::string optional_filter)
+{
+    int err = unzGetGlobalInfo(m_unzip, &out_global_info);
+    if (UNZ_OK != err) {
+        LOGE("ret: %d",err);
+        throwArchiveException(err, "unzGetGlobalInfo()");
+    }
+
+    ArchiveStatistics astats;
+    const auto num_matched = IterateFilesInZip(out_global_info, optional_filter,
+            callback, generateArchiveStatistics, &astats);
+    if(0 == num_matched) {
+        LOGE("No matching file/directory: [%s] has been found in zip archive",
+                optional_filter.c_str());
+        LOGE("Throwing NotFoundException - Could not extract file from archive");
+        throw NotFoundException("Could not extract file from archive");
+    }
+
+    callback->setExpectedDecompressedSize(astats.uncompressed_size);
+    LOGD("Expected uncompressed size: %s",
+            bytesToReadableString(astats.uncompressed_size).c_str());
+
+    callback->setNumberOfFilesToExtract(astats.number_of_files);
+    LOGD("Number entries to extract: files: %d folders: %d", astats.number_of_files,
+            astats.number_of_folders);
+}
+
+} //namespace Archive
+} //namespace DeviceAPI
diff --git a/src/Archive/UnZip.h b/src/Archive/UnZip.h
new file mode 100644 (file)
index 0000000..508eead
--- /dev/null
@@ -0,0 +1,99 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ARCHIVE_UNZIP_H__
+#define __TIZEN_ARCHIVE_UNZIP_H__
+
+#include <memory>
+#include <string>
+#include <queue>
+
+#include <unzip.h>
+
+#include "ArchiveCallbackData.h"
+#include "ArchiveFileEntry.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+class UnZipExtractRequest;
+
+typedef std::shared_ptr<std::vector<char>> CharVectorPtr;
+
+class UnZip;
+typedef std::shared_ptr<UnZip> UnZipPtr;
+
+class UnZip
+{
+public:
+    static UnZipPtr open(const std::string& filename);
+    ~UnZip();
+
+    ArchiveFileEntryPtrMapPtr listEntries(unsigned long *decompressedSize);
+
+    /**
+     * \brief Extract all files to output directory
+     * \param callback which keep pointer to ArchiveFile.
+     */
+    void extractAllFilesTo(const std::string& extract_path,
+            ExtractAllProgressCallback* callback);
+
+    void extractTo(ExtractEntryProgressCallback* callback);
+
+    void close();
+
+private:
+    UnZip(const std::string& filename);
+
+    /**
+     * \brief Extract current file (iterated with minizip library)
+     * \param callback which keep pointer to ArchiveFile.
+     */
+    void extractCurrentFile(const std::string& extract_path,
+            const std::string& base_strip_path,
+            BaseProgressCallback* callback);
+
+    static void extractItFunction(const std::string& file_name,
+            unz_file_info& file_info,
+            void* user_data);
+
+    typedef void (*IterateFunction) (const std::string& file_name,
+            unz_file_info& file_info,
+            void* user_data);
+
+    unsigned int IterateFilesInZip(unz_global_info& gi,
+            const std::string& entry_name_in_zip,
+            OperationCallbackData* callback,
+            IterateFunction itfunc,
+            void* user_data);
+
+    void updateCallbackWithArchiveStatistics(ExtractAllProgressCallback* callback,
+            unz_global_info& out_global_info,
+            const std::string optional_filter = std::string());
+
+    std::string m_zipfile_name;
+    unzFile m_unzip;
+    size_t m_default_buffer_size;
+    bool m_is_open;
+
+    friend class UnZipExtractRequest;
+};
+
+} //namespace Archive
+} //namespace DeviceAPI
+
+#endif // __TIZEN_ARCHIVE_ZIP_H__
diff --git a/src/Archive/UnZipExtractRequest.cpp b/src/Archive/UnZipExtractRequest.cpp
new file mode 100644 (file)
index 0000000..18df81d
--- /dev/null
@@ -0,0 +1,508 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "UnZipExtractRequest.h"
+
+#include <cstdio>
+#include <errno.h>
+#include <iostream>
+#include <memory>
+#include <string>
+#include <string.h>
+#include <sys/stat.h>
+#include <utime.h>
+
+#include <Logger.h>
+#include <Node.h>
+#include <Path.h>
+#include <PlatformException.h>
+
+#include "ArchiveFile.h"
+#include "ArchiveUtils.h"
+#include "UnZip.h"
+
+namespace DeviceAPI {
+
+using namespace DeviceAPI::Common;
+
+namespace Archive {
+
+FilePathStatus getPathStatus(const std::string& path)
+{
+    if(path.empty()) {
+        return FPS_NOT_EXIST;
+    }
+
+    std::string npath = removeTrailingDirectorySlashFromPath(path);
+
+    struct stat sb;
+    if (stat(npath.c_str(), &sb) == -1) {
+        return FPS_NOT_EXIST;
+    }
+    if(sb.st_mode & S_IFDIR) {
+        return FPS_DIRECTORY;
+    } else {
+        return FPS_FILE;
+    }
+}
+
+void divideToPathAndName(const std::string& filepath, std::string& out_path,
+        std::string& out_name)
+{
+
+    size_t pos_last_dir = filepath.find_last_of("/\\");
+    if(pos_last_dir == std::string::npos) {
+        out_path = "";
+        out_name = filepath;
+    } else {
+        out_path = filepath.substr(0, pos_last_dir+1);
+        out_name = filepath.substr(pos_last_dir+1);
+    }
+}
+
+void createMissingDirectories(const std::string& path, bool check_first = true)
+{
+    if(check_first) {
+        const FilePathStatus path_status = getPathStatus(path);
+        //LOGD("[%s] status: %d", path.c_str(), path_status);
+        if(FPS_DIRECTORY == path_status) {
+            return;
+        }
+    }
+
+    const size_t extract_path_len = path.length();
+    for(size_t i = 0; i < extract_path_len; ++i) {
+        const char& cur = path[i];
+        if( (('\\' == cur || '/' == cur) && i > 0) ||   //handle left side from current /
+                (extract_path_len-1 == i) ) {           //handle last subdirectory path
+
+            const std::string left_part = path.substr(0,i+1);
+            const FilePathStatus status = getPathStatus(left_part);
+            //LOGD("left_part: [%s] status:%d", left_part.c_str(), status);
+
+            if(FPS_DIRECTORY != status) {
+                //TODO investigate 0775 (mode) - Filesystem assumed that file should have parent mode
+                if(mkdir(left_part.c_str(), 0775) == -1) {
+                    LOGE("Couldn't create new directory: %s errno:%s",
+                            left_part.c_str(), strerror(errno));
+               //TODO check why mkdir return -1 but directory is successfully created
+               //     throw UnknownException(
+               //             "Could not create new directory");
+                }
+            }
+        }
+    }
+}
+
+void changeFileAccessAndModifyDate(const std::string& filepath, tm_unz tmu_date)
+{
+  struct utimbuf ut;
+  struct tm newdate;
+  newdate.tm_sec = tmu_date.tm_sec;
+  newdate.tm_min = tmu_date.tm_min;
+  newdate.tm_hour = tmu_date.tm_hour;
+  newdate.tm_mday = tmu_date.tm_mday;
+  newdate.tm_mon = tmu_date.tm_mon;
+
+  if (tmu_date.tm_year > 1900) {
+      newdate.tm_year = tmu_date.tm_year - 1900;
+  } else {
+      newdate.tm_year = tmu_date.tm_year ;
+  }
+  newdate.tm_isdst = -1;
+
+  ut.actime = ut.modtime = mktime(&newdate);
+  if(utime(filepath.c_str(), &ut) == -1) {
+      LOGE("Couldn't set time for: [%s] errno:%s", filepath.c_str(), strerror(errno));
+  }
+}
+
+void UnZipExtractRequest::execute(UnZip& owner, const std::string& extract_path,
+        const std::string& base_strip_path,
+        BaseProgressCallback* callback)
+{
+    UnZipExtractRequest req(owner, extract_path, base_strip_path, callback);
+    req.run();
+}
+
+UnZipExtractRequest::UnZipExtractRequest(UnZip& owner,
+        const std::string& extract_path,
+        const std::string& base_strip_path,
+        BaseProgressCallback* callback) :
+
+        m_owner(owner),
+        m_extract_path(extract_path),
+        m_base_strip_path(base_strip_path),
+        m_callback(callback),
+
+        m_output_file(NULL),
+        m_buffer(NULL),
+        m_delete_output_file(false),
+        m_close_unz_current_file(false),
+        m_new_dir_status(FPS_NOT_EXIST),
+
+        m_is_directory_entry(false)
+{
+    if(!m_callback){
+        LOGE("Callback is null");
+        throw UnknownException("Problem with callback functionality");
+    }
+}
+
+void UnZipExtractRequest::run()
+{
+    LOGD("Entered");
+
+    getCurrentFileInfo();
+
+    if(m_is_directory_entry) {
+        handleDirectoryEntry();
+    } else {
+        handleFileEntry();
+    }
+}
+
+UnZipExtractRequest::~UnZipExtractRequest()
+{
+    if(m_output_file) {
+        fclose(m_output_file);
+        m_output_file = NULL;
+    }
+
+    if(m_delete_output_file && !m_is_directory_entry) {
+        if(std::remove(m_output_filepath.c_str()) != 0) {
+            LOGE("Couldn't remove partial file! "
+                    "std::remove(\"%s\") failed with errno:%s",
+                    m_output_filepath.c_str(), strerror(errno));
+        }
+    }
+
+    delete [] m_buffer;
+    m_buffer = NULL;
+
+    if(m_close_unz_current_file) {
+        int err = unzCloseCurrentFile (m_owner.m_unzip);
+        if(UNZ_OK != err) {
+            LOGW("%s",getArchiveLogMessage(err, "unzCloseCurrentFile()").c_str());
+        }
+    }
+}
+
+void UnZipExtractRequest::getCurrentFileInfo()
+{
+    LOGD("Entered");
+    int err = unzGetCurrentFileInfo(m_owner.m_unzip, &m_file_info,
+            m_filename_inzip, sizeof(m_filename_inzip), NULL, 0, NULL, 0);
+    if (err != UNZ_OK) {
+        LOGE("ret: %d", err);
+        throwArchiveException(err, "unzGetCurrentFileInfo()");
+    }
+
+    LOGD("Input from ZIP: m_filename_inzip: [%s]", m_filename_inzip);
+    LOGD("m_base_strip_path: [%s]", m_base_strip_path.c_str());
+
+    std::string file_path = m_filename_inzip;
+    if(!m_base_strip_path.empty()) {
+        if(file_path.find(m_base_strip_path) != 0) {
+            LOGW("m_base_strip_path: [%s] is not begin of m_filename_inzip: [%s]!",
+                    m_base_strip_path.c_str(),
+                    m_filename_inzip);
+        }
+        else {
+            file_path = file_path.substr(m_base_strip_path.length());
+            LOGD("Stripped file name: [%s]", file_path.c_str());
+        }
+    }
+    else {
+        LOGD("Not stripped file name: [%s]", file_path.c_str());
+    }
+
+    m_output_filepath = removeDuplicatedSlashesFromPath(m_extract_path + "/" + file_path);
+
+    LOGD("Packed: [%s], uncompressed_size: %d, will extract to: [%s]",
+            m_filename_inzip, m_file_info.uncompressed_size,
+            m_output_filepath.c_str());
+
+    std::string path, name;
+    divideToPathAndName(file_path, path, name);
+    m_new_dir_path = removeDuplicatedSlashesFromPath(m_extract_path + "/" + path);
+    m_new_dir_status = getPathStatus(m_new_dir_path);
+    m_is_directory_entry = name.empty();
+
+    LOGD("New output dir: [%s] status: %d m_is_directory_entry: %d",
+            m_new_dir_path.c_str(), m_new_dir_status, m_is_directory_entry);
+
+    if(FPS_DIRECTORY != m_new_dir_status) {
+
+        if(m_is_directory_entry) {
+
+            std::string base_directories;
+            const size_t len = m_new_dir_path.length();
+
+            for(int i = static_cast<int>(len) - 2; i >= 0; i--) {  //skip last \, /
+                const char& cur = m_new_dir_path[i];
+                if('\\' == cur || '/' == cur) {
+                    base_directories = m_new_dir_path.substr(0, static_cast<size_t>(i));
+                    break;
+                }
+            }
+
+            LOGD("Type: DIRECTORY checking base output directories: [%s]",
+                    base_directories.c_str());
+            createMissingDirectories(base_directories, false);
+        } else {
+            LOGD("Type: FILE checking output dir: [%s]", m_new_dir_path.c_str());
+            createMissingDirectories(m_new_dir_path, false);
+        }
+    }
+}
+
+void UnZipExtractRequest::handleDirectoryEntry()
+{
+    LOGD("Entered");
+    if(FPS_DIRECTORY != m_new_dir_status) {
+
+        if(FPS_FILE == m_new_dir_status) {
+            if(m_callback->getOverwrite()) {    //Is a file & overwrite is set:
+                std::string fn = removeTrailingDirectorySlashFromPath(m_new_dir_path);
+                if(std::remove(fn.c_str()) != 0) {
+                    LOGE("std::remove(\"%s\") failed with errno:%s",
+                            m_new_dir_path.c_str(), strerror(errno));
+                    throw UnknownException(
+                            "Could not overwrite file in output directory");
+                }
+            } else {                            //Is a file & overwrite is not set:
+                LOGE("Failed to extract directory, "
+                        "file with the same name exists in output directory");
+                throw UnknownException("Failed to extract directory, "
+                        "file with the same name exists in output directory");
+            }
+        }
+
+        //Try to create new directory in output directory
+        if(mkdir(m_new_dir_path.c_str(), 0775) == -1) {
+            LOGE("Couldn't create new directory: %s errno:%s",
+                    m_new_dir_path.c_str(), strerror(errno));
+            throw UnknownException(
+                    "Could not create new directory in extract output directory");
+        }
+    }
+
+    LOGD("Set dir: [%s] access and modify to: %4d-%2d-%2d %2d:%2d:%2d", m_new_dir_path.c_str(),
+            m_file_info.tmu_date.tm_year,
+            m_file_info.tmu_date.tm_mon,
+            m_file_info.tmu_date.tm_mday,
+            m_file_info.tmu_date.tm_hour,
+            m_file_info.tmu_date.tm_min,
+            m_file_info.tmu_date.tm_sec);
+
+    // Directory already exists we only need to update time
+    changeFileAccessAndModifyDate(m_new_dir_path, m_file_info.tmu_date);
+
+    LOGD("Extracted directory entry: [%s]", m_new_dir_path.c_str());
+}
+
+bool UnZipExtractRequest::prepareOutputSubdirectory()
+{
+    LOGD("Entered");
+    //This zip entry points to file - verify that parent directory in output dir exists
+    if(FPS_DIRECTORY != m_new_dir_status) {
+        if(FPS_FILE == m_new_dir_status) {
+            LOGE("Path: %s is pointing to file not directory!",
+                    m_new_dir_path.c_str());
+            throw UnknownException("Failed to extract file from zip archive, "
+                    "output path is invalid");
+        }
+
+        //Try to create new directory in output directory
+        //TODO investigate 0775 (mode) - Filesystem assumed that file should have parent mode
+        if(mkdir(m_new_dir_path.c_str(), 0775) == -1) {
+            LOGW("couldn't create new directory: %s errno:%s",
+                    m_new_dir_path.c_str(), strerror(errno));
+            //TODO check why mkdir return -1 but directory is successfully created
+            //     throw UnknownException(
+            //     "Could not create new directory in extract output directory");
+        }
+    }
+
+    if(m_callback->isCanceled()) {
+        LOGD("Operation cancelled");
+        throw OperationCanceledException();
+    }
+
+    const FilePathStatus output_fstatus = getPathStatus(m_output_filepath);
+    if(FPS_NOT_EXIST != output_fstatus) {
+        if(!m_callback->getOverwrite()) {
+            LOGW("%s exists at output path: [%s], overwrite is set to FALSE",
+                    (FPS_DIRECTORY == output_fstatus ? "Directory" : "File"),
+                    m_output_filepath.c_str());
+
+            //Just skip this file - TODO: this should be documented in WIDL
+            return false;
+        } else {
+            if(FPS_DIRECTORY == output_fstatus) {
+                try {
+                    Filesystem::PathPtr path = Filesystem::Path::create(m_output_filepath);
+                    Filesystem::NodePtr node = Filesystem::Node::resolve(path);
+                    node->remove(Filesystem::OPT_RECURSIVE);
+                    LOGD("Removed directory: [%s]", m_output_filepath.c_str());
+                } catch(BasePlatformException& ex) {
+                    LOGE("Remove dir: [%s] failed with exception: %s:%s",
+                            m_output_filepath.c_str(),
+                            ex.getName().c_str(), ex.getMessage().c_str());
+                    throw UnknownException("Could not overwrite existing directory");
+                } catch (...) {
+                    LOGE("Remove dir: [%s] failed", m_output_filepath.c_str());
+                    throw UnknownException("Could not overwrite existing directory");
+                }
+            } //else {
+                //We will overwrite it with fopen
+            //}
+        }
+    }
+
+    return true;
+}
+
+void UnZipExtractRequest::handleFileEntry()
+{
+    LOGD("Entered");
+    if(!prepareOutputSubdirectory()) {
+        LOGE("File exists but overwrite is false");
+        throw InvalidModificationException("file already exists.");
+    }
+
+    int err = unzOpenCurrentFilePassword(m_owner.m_unzip,
+        NULL); //password is not supported yet therefore passing NULL
+    if (UNZ_OK != err) {
+        LOGE("ret: %d", err);
+        throwArchiveException(err, "unzOpenCurrentFilePassword()");
+    }
+
+    //We have successfully opened curent file, therefore we should close it later
+    m_close_unz_current_file = true;
+
+    const size_t buffer_size = m_owner.m_default_buffer_size;
+    m_buffer = new(std::nothrow) char[buffer_size];
+    if(!m_buffer) {
+        LOGE("Couldn't allocate buffer with size: %s",
+                bytesToReadableString(buffer_size).c_str());
+        throw UnknownException("Memory allocation failed");
+    }
+
+    m_output_file = fopen(m_output_filepath.c_str(), "wb");
+    if(!m_output_file) {
+        LOGE("Couldn't open output file: %s", m_output_filepath.c_str());
+        throw UnknownException("Could not create extracted file");
+    }
+    m_delete_output_file = true;
+
+    int read_size = 0;
+    bool marked_as_finished = false;
+
+    LOGD("Started extracting: [%s] uncompressed size: %d - %s", m_filename_inzip,
+            m_file_info.uncompressed_size,
+            bytesToReadableString(m_file_info.uncompressed_size).c_str());
+
+    ExtractAllProgressCallback* extract_callback = NULL;
+    if(m_callback->getCallbackType() == EXTRACT_ALL_PROGRESS_CALLBACK ||
+            m_callback->getCallbackType() == EXTRACT_ENTRY_PROGRESS_CALLBACK) {
+        extract_callback = static_cast<ExtractAllProgressCallback*>(m_callback);
+        extract_callback->startedExtractingFile(m_file_info.uncompressed_size);
+    }
+
+    ArchiveFileEntryPtrMapPtr entries = m_callback->getArchiveFile()->getEntryMap();
+    auto it = entries->find(m_filename_inzip);
+    if (it == entries->end()) {
+        LOGE("Entry not found");
+        throw Common::NotFoundException("Entry not found");
+    }
+
+    while(true) {
+        if(m_callback->isCanceled()) {
+            LOGD("Operation cancelled");
+            throw OperationCanceledException();
+        }
+
+        read_size = unzReadCurrentFile(m_owner.m_unzip, m_buffer, buffer_size);
+        if (read_size < 0) {
+            LOGE("unzReadCurrentFile failed with error code:%d for file:%s", read_size,
+                    m_filename_inzip);
+            throw UnknownException("Failed to extract file from zip archive");
+        }
+        else if(0 == read_size) {
+
+            if(extract_callback) {
+                if(!marked_as_finished) {
+                    LOGD("NOT marked_as_finished -> increment extracted files counter");
+                    extract_callback->finishedExtractingFile();
+
+                    //Call progress callback only if we expected empty file
+                    if(m_file_info.uncompressed_size == 0) {
+                        LOGD("Calling progress callback(%f, %s)",
+                                extract_callback->getOverallProgress(), m_filename_inzip);
+                        extract_callback->callProgressCallbackOnMainThread(
+                                extract_callback->getOverallProgress(), it->second);
+                    }
+                }
+            }
+            //Finished writing file, we should not delete extracted file
+            m_delete_output_file = false;
+            break;
+        }
+
+        if (fwrite(m_buffer, read_size, 1, m_output_file) != 1) {
+            LOGE("Couldn't write extracted data to output file:%s",
+                    m_output_filepath.c_str());
+            throw UnknownException("Could not write extract file into output file");
+        }
+
+        if(extract_callback) {
+            extract_callback->extractedPartOfFile(read_size);
+            LOGD("File: [%s] extracted: %s - %f%%; total progress %f%%", m_filename_inzip,
+                    bytesToReadableString(read_size).c_str(),
+                    100.0f * extract_callback->getCurrentFileProgress(),
+                    100.0f * extract_callback->getOverallProgress());
+
+            // It is better to update number of extracted entries so we will have
+            // overal progres: 1.0 if all files are extracted
+            //
+            if(extract_callback->getCurrentFileProgress() >= 1.0) {
+                LOGD("Current file: [%s] progress: %f >= 1.0 -> "
+                        "marked_as_finished = true and increment extracted files counter",
+                        m_filename_inzip, extract_callback->getCurrentFileProgress());
+                marked_as_finished = true;
+                extract_callback->finishedExtractingFile();
+            }
+
+            LOGD("Calling progress callback(%f, %s)",
+                    extract_callback->getOverallProgress(), m_filename_inzip);
+            extract_callback->callProgressCallbackOnMainThread(
+                    extract_callback->getOverallProgress(), it->second);
+        }
+    }
+
+    if(m_output_file) {
+        fclose(m_output_file);
+        m_output_file = NULL;
+    }
+
+    changeFileAccessAndModifyDate(m_output_filepath, m_file_info.tmu_date);
+}
+
+} //namespace Archive
+} //namespace DeviceAPI
diff --git a/src/Archive/UnZipExtractRequest.h b/src/Archive/UnZipExtractRequest.h
new file mode 100644 (file)
index 0000000..49d6561
--- /dev/null
@@ -0,0 +1,85 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ARCHIVE_UNZIP_EXTRACT_REQUEST_H__
+#define __TIZEN_ARCHIVE_UNZIP_EXTRACT_REQUEST_H__
+
+#include <stdio.h>
+#include <string>
+#include "UnZip.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+enum FilePathStatus {
+    FPS_NOT_EXIST = 0,
+    FPS_FILE = 1,
+    FPS_DIRECTORY = 2
+};
+
+class UnZipExtractRequest
+{
+public:
+    static void execute(UnZip& owner,
+            const std::string& extract_path,
+            const std::string& base_strip_path,
+            BaseProgressCallback* callback);
+
+    ~UnZipExtractRequest();
+
+private:
+    UnZipExtractRequest(UnZip& owner,
+            const std::string& extract_path,
+            const std::string& base_strip_path,
+            BaseProgressCallback* callback);
+    void run();
+
+    void getCurrentFileInfo();
+
+    void handleDirectoryEntry();
+
+    void handleFileEntry();
+    bool prepareOutputSubdirectory();
+
+    //-----------------------------------------------------------------------------
+    //Input request variables
+    UnZip& m_owner;
+    const std::string m_extract_path;
+    const std::string m_base_strip_path;
+    BaseProgressCallback* m_callback;
+
+    //-----------------------------------------------------------------------------
+    //Working variables
+    FILE* m_output_file; //Used to write extracted file into output directory
+    char* m_buffer; //Memory buffer passed between Minizip lib and fwrite function
+
+    bool m_delete_output_file;
+    bool m_close_unz_current_file;
+
+    unz_file_info m_file_info; //Informations about current archive entry (from minizip)
+    char m_filename_inzip[512]; //Name of archive file entry (from minizip)
+    std::string m_output_filepath; //Extracted output file name with full path
+
+    FilePathStatus m_new_dir_status;
+    bool m_is_directory_entry; //Is this request for directory
+    std::string m_new_dir_path;
+};
+
+} //namespace Archive
+} //namespace DeviceAPI
+
+#endif // __TIZEN_ARCHIVE_UNZIP_EXTRACT_REQUEST_H__
diff --git a/src/Archive/Zip.cpp b/src/Archive/Zip.cpp
new file mode 100644 (file)
index 0000000..fd9a683
--- /dev/null
@@ -0,0 +1,146 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "Zip.h"
+
+#include <iostream>
+#include <memory>
+#include <string>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <File.h>
+#include <Logger.h>
+#include <Path.h>
+#include <PlatformException.h>
+
+#include "ArchiveFile.h"
+#include "ArchiveUtils.h"
+#include "crypt.h"
+
+#include "ZipAddRequest.h"
+
+namespace DeviceAPI {
+
+using namespace DeviceAPI::Common;
+
+namespace Archive {
+
+void Zip::generateZipFileInfo(const std::string& filename, zip_fileinfo& out_zi)
+{
+    memset(&out_zi, 0, sizeof(zip_fileinfo));
+
+    time_t tm_t = 0;
+    if (filename != "-") {
+        std::string name = filename;
+        if (name[name.length() - 1] == '/') {
+            name[name.length() - 1] = '\0';
+        }
+
+        struct stat s;
+        // not all systems allow stat'ing a file with / appended
+        if (stat(name.c_str(), &s) == 0) {
+            tm_t = s.st_mtime;
+        }
+    }
+
+    struct tm* filedate = localtime(&tm_t);
+    if(filedate) {
+        out_zi.tmz_date.tm_sec  = filedate->tm_sec;
+        out_zi.tmz_date.tm_min  = filedate->tm_min;
+        out_zi.tmz_date.tm_hour = filedate->tm_hour;
+        out_zi.tmz_date.tm_mday = filedate->tm_mday;
+        out_zi.tmz_date.tm_mon  = filedate->tm_mon ;
+        out_zi.tmz_date.tm_year = filedate->tm_year;
+    }
+}
+
+Zip::Zip(const std::string& filename, ZipOpenMode open_mode) :
+        m_zipfile_name(filename),
+        m_zip(NULL),
+        m_default_buffer_size(1024 * 1024)
+{
+    LOGD("Entered");
+
+    int append_mode = APPEND_STATUS_CREATE;
+    if(ZOM_CREATEAFTER == open_mode) {
+        append_mode = APPEND_STATUS_CREATEAFTER;
+    } else if(ZOM_ADDINZIP == open_mode) {
+        append_mode = APPEND_STATUS_ADDINZIP;
+    }
+    LOGD("append_mode: %d", append_mode);
+
+    m_zip = zipOpen(filename.c_str(), append_mode);
+    if(!m_zip) {
+        LOGE("zipOpen returned NULL!");
+        throw UnknownException("Opening/creating zip file failed");
+    }
+    m_is_open = true;
+}
+
+Zip::~Zip()
+{
+    close();
+}
+
+void Zip::close()
+{
+    LOGD("Entered");
+    if(!m_is_open) {
+        LOGD("Already closed - exiting.");
+        return;
+    }
+
+    int errclose = zipClose(m_zip, NULL);
+    m_zip = NULL;
+
+    if (errclose != ZIP_OK) {
+        LOGE("ret: %d", errclose);
+        throwArchiveException(errclose, "zipClose()");
+    }
+    m_is_open = false;
+}
+
+ZipPtr Zip::createNew(const std::string& filename)
+{
+    LOGD("Entered");
+    return ZipPtr(new Zip(filename, ZOM_CREATE));
+}
+
+ZipPtr Zip::open(const std::string& filename)
+{
+    LOGD("Entered");
+    return ZipPtr(new Zip(filename, ZOM_ADDINZIP));
+}
+
+void Zip::addFile(AddProgressCallback*& callback)
+{
+    LOGD("Entered");
+    if(!callback) {
+        LOGE("callback is NULL!");
+        throw UnknownException("Could not add file(-s) to archive");
+    }
+    if(!m_is_open) {
+        LOGE("Zip file not opened - exiting");
+        throw UnknownException("Could not add file(-s) to archive - zip file closed");
+    }
+
+    ZipAddRequest::execute(*this, callback);
+}
+
+} //namespace Archive
+} //namespace DeviceAPI
diff --git a/src/Archive/Zip.h b/src/Archive/Zip.h
new file mode 100644 (file)
index 0000000..657a989
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ARCHIVE_ZIP_H__
+#define __TIZEN_ARCHIVE_ZIP_H__
+
+#include <memory>
+#include <string>
+
+#include <zip.h>
+
+#include "ArchiveCallbackData.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+
+class ZipAddRequest;
+
+class Zip;
+typedef std::shared_ptr<Zip> ZipPtr;
+
+class Zip
+{
+public:
+    static ZipPtr createNew(const std::string& filename);
+    static ZipPtr open(const std::string& filename);
+    ~Zip();
+
+    /**
+     * When request has finished callback is set to NULL and is
+     * deleted on main thread after calling all progress callbacks.
+     * If exception is thrown please delete callback.
+     */
+    void addFile(AddProgressCallback*& callback);
+
+    void close();
+
+private:
+    enum ZipOpenMode {
+        ZOM_CREATE,
+        ZOM_CREATEAFTER,
+        ZOM_ADDINZIP
+    };
+
+    Zip(const std::string& filename, ZipOpenMode open_mode);
+
+    static void generateZipFileInfo(const std::string& filename, zip_fileinfo& out_zi);
+
+    std::string m_zipfile_name;
+    zipFile m_zip;
+    size_t m_default_buffer_size;
+    bool m_is_open;
+
+
+    friend class ZipAddRequest;
+};
+
+} //namespace Archive
+} //namespace DeviceAPI
+
+#endif // __TIZEN_ARCHIVE_ZIP_H__
diff --git a/src/Archive/ZipAddRequest.cpp b/src/Archive/ZipAddRequest.cpp
new file mode 100644 (file)
index 0000000..a43352c
--- /dev/null
@@ -0,0 +1,529 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Logger.h>
+
+#include "ZipAddRequest.h"
+
+#include <PlatformException.h>
+
+#include "ArchiveFile.h"
+#include "ArchiveFileEntry.h"
+#include "ArchiveUtils.h"
+
+namespace DeviceAPI {
+
+using namespace DeviceAPI::Common;
+
+namespace Archive {
+
+ZipAddRequest::ZipAddRequest(Zip& owner, AddProgressCallback*& callback) :
+        m_owner(owner),
+        m_callback(callback),
+        m_input_file(NULL),
+        m_buffer(NULL),
+        m_buffer_size(m_owner.m_default_buffer_size),
+        m_files_to_compress(0),
+        m_bytes_to_compress(0),
+        m_files_compressed(0),
+        m_bytes_compressed(0),
+        m_compression_level(0),
+        m_new_file_in_zip_opened(false)
+{
+}
+
+ZipAddRequest::~ZipAddRequest()
+{
+    if(m_input_file) {
+        fclose(m_input_file);
+        m_input_file = NULL;
+    }
+
+    delete [] m_buffer;
+    m_buffer = NULL;
+
+
+    if(m_new_file_in_zip_opened) {
+        int err = zipCloseFileInZip(m_owner.m_zip);
+        if (ZIP_OK != err) {
+            LOGE("%s",getArchiveLogMessage(err, "zipCloseFileInZip()").c_str());
+        }
+    }
+}
+
+void ZipAddRequest::execute(Zip& owner, AddProgressCallback*& callback)
+{
+    ZipAddRequest req(owner, callback);
+    req.run();
+}
+
+void ZipAddRequest::run()
+{
+    if(!m_callback) {
+        LOGE("m_callback is NULL");
+        throw UnknownException("Could not add file(-s) to archive");
+    }
+
+    if(!m_callback->getFileEntry()) {
+        LOGE("m_callback->getFileEntry() is NULL");
+        throw InvalidValuesException("Provided ArchiveFileEntry is not correct");
+    }
+
+    if(m_callback->isCanceled()) {
+        LOGD("Operation cancelled");
+        throw OperationCanceledException();
+    }
+
+    m_compression_level = m_callback->getFileEntry()->getCompressionLevel();
+    m_root_src_file = m_callback->getFileEntry()->getFile();
+    m_root_src_file_node = m_root_src_file->getNode();
+
+    //We just need read permission to list files in subdirectories
+    m_root_src_file_node->setPermissions(Filesystem::PERM_READ);
+
+    std::string src_basepath, src_name;
+    getBasePathAndName(m_root_src_file_node->getPath()->getFullPath(), src_basepath,
+            src_name);
+
+    m_absoulte_path_to_extract = src_basepath;
+    LOGD("m_absoulte_path_to_extract: [%s]", m_absoulte_path_to_extract.c_str());
+
+    m_destination_path_in_zip = removeDuplicatedSlashesFromPath(
+            m_callback->getFileEntry()->getDestination());
+
+    // If we have destination set then we need to create all folders and sub folders
+    // inside this zip archive.
+    //
+    if(m_destination_path_in_zip.length() > 0) {
+        LOGD("destination is: [%s]", m_destination_path_in_zip.c_str());
+
+        for(size_t i = 0; i < m_destination_path_in_zip.length(); ++i) {
+            const char cur_char = m_destination_path_in_zip[i];
+
+            if( ((cur_char == '/' || cur_char == '\\') && i > 0 ) ||
+                (i == m_destination_path_in_zip.length() - 1)) {
+
+                //Extract left side with '/':
+                const std::string new_dir = m_destination_path_in_zip.substr(0, i + 1);
+
+                LOGD("Adding empty directory: [%s] to archive", new_dir.c_str());
+                addEmptyDirectoryToZipArchive(new_dir);
+            }
+        }
+    }
+
+    // Generate list of files and all subdirectories
+    //
+    Filesystem::NodeList all_sub_nodes;
+    addNodeAndSubdirsToList(m_root_src_file_node, all_sub_nodes);
+
+    if(m_callback->isCanceled()) {
+        LOGD("Operation cancelled");
+        throw OperationCanceledException();
+    }
+
+    // Calculate total size to be compressed
+    //
+    m_bytes_to_compress = 0;
+    m_files_to_compress = 0;
+
+    int i = 0;
+    for(auto it = all_sub_nodes.begin(); it != all_sub_nodes.end(); ++it, ++i) {
+
+        unsigned long long size = 0;
+        if((*it)->getType() == Filesystem::NT_FILE) {
+            size = (*it)->getSize();
+            m_bytes_to_compress += size;
+            ++m_files_to_compress;
+        }
+
+        LOGD("[%d] : [%s] --zip--> [%s] | size: %s", i, (*it)->getPath()->getFullPath().c_str(),
+                getNameInZipArchiveFor(*it, m_callback->getFileEntry()->getStriped()).c_str(),
+                bytesToReadableString(size).c_str());
+    }
+
+    LOGD("m_files_to_compress: %d", m_files_to_compress);
+    LOGD("m_bytes_to_compress: %llu (%s)", m_bytes_to_compress,
+            bytesToReadableString(m_bytes_to_compress).c_str());
+
+    if(m_callback->isCanceled()) {
+        LOGD("Operation cancelled");
+        throw OperationCanceledException();
+    }
+
+    // Begin files compression
+    //
+    for(auto it = all_sub_nodes.begin(); it != all_sub_nodes.end(); ++it, ++i) {
+            addToZipArchive(*it);
+    }
+
+    m_callback->callSuccessCallbackOnMainThread();
+    m_callback = NULL;
+}
+
+void ZipAddRequest::addNodeAndSubdirsToList(Filesystem::NodePtr src_node,
+        Filesystem::NodeList& out_list_of_child_nodes)
+{
+    out_list_of_child_nodes.push_back(src_node);
+
+    if(Filesystem::NT_DIRECTORY == src_node->getType()) {
+        auto child_nodes = src_node->getChildNodes();
+        for(auto it = child_nodes.begin(); it != child_nodes.end(); ++it) {
+            addNodeAndSubdirsToList(*it, out_list_of_child_nodes);
+        }
+    }
+}
+
+void ZipAddRequest::addEmptyDirectoryToZipArchive(std::string name_in_zip)
+{
+    LOGD("Entered name_in_zip:%s", name_in_zip.c_str());
+
+    if(name_in_zip.length() == 0) {
+        LOGW("Trying to create directory with empty name - \"\"");
+        return;
+    }
+
+    const char last_char = name_in_zip[name_in_zip.length()-1];
+    if(last_char != '/' && last_char != '\\') {
+            name_in_zip += "/";
+            LOGD("Corrected name_in_zip: [%s]", name_in_zip.c_str());
+    }
+
+    if(m_new_file_in_zip_opened) {
+        LOGE("WARNING: Previous new file in zip archive is opened!");
+        int err = zipCloseFileInZip(m_owner.m_zip);
+        if (ZIP_OK != err) {
+            LOGE("%s",getArchiveLogMessage(err, "zipCloseFileInZip()").c_str());
+        }
+    }
+
+    bool is_directory = false;
+    std::string conflicting_name;
+
+    if(m_callback->getArchiveFile()->isEntryWithNameInArchive(name_in_zip,
+            &is_directory, &conflicting_name)) {
+
+        if(!is_directory) {
+            LOGE("Entry: [%s] exists and is NOT directory!", conflicting_name.c_str());
+
+            LOGE("Throwing InvalidValuesException - File with the same name exists");
+            throw InvalidValuesException("File with the same name exists");
+        }
+
+        LOGD("Directory: [%s] already exists -> nothing to do", name_in_zip.c_str());
+            return;
+    }
+
+    if(m_callback->isCanceled()) {
+        LOGD("Operation cancelled");
+        throw OperationCanceledException();
+    }
+
+    zip_fileinfo new_dir_info;
+    memset(&new_dir_info, 0, sizeof(zip_fileinfo));
+
+    //
+    // Since this directory does not exist we will set current time
+    //
+    time_t current_time = time(NULL);
+    struct tm* current_time_tm = localtime(&current_time);
+    if(current_time_tm) {
+        new_dir_info.tmz_date.tm_sec  = current_time_tm->tm_sec;
+        new_dir_info.tmz_date.tm_min  = current_time_tm->tm_min;
+        new_dir_info.tmz_date.tm_hour = current_time_tm->tm_hour;
+        new_dir_info.tmz_date.tm_mday = current_time_tm->tm_mday;
+        new_dir_info.tmz_date.tm_mon  = current_time_tm->tm_mon ;
+        new_dir_info.tmz_date.tm_year = current_time_tm->tm_year;
+    }
+
+    int err = zipOpenNewFileInZip3(m_owner.m_zip, name_in_zip.c_str(), &new_dir_info,
+            NULL, 0, NULL, 0, NULL,
+            (m_compression_level != 0) ? Z_DEFLATED : 0,
+            m_compression_level, 0,
+            -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+            NULL, 0);
+
+    if (err != ZIP_OK) {
+        LOGE("ret: %d", err);
+        throwArchiveException(err, "zipOpenNewFileInZip3()");
+    }
+
+    m_new_file_in_zip_opened = true;
+
+    err = zipCloseFileInZip(m_owner.m_zip);
+    if (ZIP_OK != err) {
+        LOGE("%s",getArchiveLogMessage(err, "zipCloseFileInZip()").c_str());
+    }
+
+    LOGD("Added new empty directory to archive: [%s]", name_in_zip.c_str());
+    m_new_file_in_zip_opened = false;
+}
+
+void ZipAddRequest::addToZipArchive(Filesystem::NodePtr src_file_node)
+{
+    const std::string name_in_zip = getNameInZipArchiveFor(src_file_node,
+            m_callback->getFileEntry()->getStriped());
+    const std::string src_file_path = src_file_node->getPath()->getFullPath();
+
+    LOGD("Compress: [%s] to zip archive as: [%s]", src_file_path.c_str(),
+            name_in_zip.c_str());
+
+    zip_fileinfo new_file_info;
+    Zip::generateZipFileInfo(src_file_path, new_file_info);
+
+    if(m_new_file_in_zip_opened) {
+        LOGE("WARNING: Previous new file in zip archive is opened!");
+        int err = zipCloseFileInZip(m_owner.m_zip);
+        if (ZIP_OK != err) {
+            LOGE("%s",getArchiveLogMessage(err, "zipCloseFileInZip()").c_str());
+        }
+    }
+
+    if(m_callback->isCanceled()) {
+        LOGD("Operation cancelled");
+        throw OperationCanceledException();
+    }
+
+    std::string conflicting_name;
+    if(m_callback->getArchiveFile()->isEntryWithNameInArchive(name_in_zip,
+            NULL, &conflicting_name)) {
+
+        LOGE("Cannot add new entry with name name: [%s] "
+                "it would conflict with existing entry: [%s]",
+                name_in_zip.c_str(), conflicting_name.c_str());
+
+        LOGE("Throwing InvalidModificationException - Archive entry name conflicts");
+        throw InvalidModificationException("Archive entry name conflicts");
+    }
+
+    int err = zipOpenNewFileInZip3(m_owner.m_zip, name_in_zip.c_str(), &new_file_info,
+            NULL, 0, NULL, 0, NULL,
+            (m_compression_level != 0) ? Z_DEFLATED : 0,
+            m_compression_level, 0,
+            -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
+            NULL, 0);
+
+    if (err != ZIP_OK) {
+        LOGE("ret: %d", err);
+        throwArchiveException(err, "zipOpenNewFileInZip3()");
+    }
+
+    m_new_file_in_zip_opened = true;
+
+    if(m_input_file) {
+        LOGW("WARNING: Previous m_input_file has not been closed");
+        fclose(m_input_file);
+        m_input_file = NULL;
+    }
+
+    Filesystem::File::PermissionList perm_list;
+    Filesystem::FilePtr cur_file(new Filesystem::File(src_file_node, perm_list));
+    ArchiveFileEntryPtr cur_afentry(new ArchiveFileEntry(cur_file));
+    cur_afentry->setCompressionLevel(m_compression_level);
+    cur_afentry->setName(name_in_zip);
+    cur_afentry->setModified(src_file_node->getModified());
+
+    auto entry = m_callback->getFileEntry();
+    cur_afentry->setDestination(entry->getDestination());
+    cur_afentry->setStriped(entry->getStriped());
+    cur_afentry->setSize(0);
+
+    LOGD("m_bytes_compressed:%llu / m_bytes_to_compress: %llu",
+            m_bytes_compressed, m_bytes_to_compress);
+
+    LOGD("m_files_compressed:%d / m_files_to_compress: %d",
+            m_files_compressed, m_files_to_compress);
+
+    if(src_file_node->getType() == Filesystem::NT_FILE) {
+        m_input_file = fopen(src_file_path.c_str(), "rb");
+        if (!m_input_file) {
+            LOGE("Error opening source file:%s", src_file_path.c_str());
+            throw UnknownException("Could not open file to be added");
+        }
+
+        //Get file length
+        fseek(m_input_file, 0, SEEK_END);
+        const size_t in_file_size = ftell(m_input_file);
+        fseek(m_input_file, 0, SEEK_SET);
+        LOGD("Source file: [%s] size: %d - %s", src_file_path.c_str(),
+                in_file_size,
+                bytesToReadableString(in_file_size).c_str());
+
+        cur_afentry->setSize(in_file_size);
+
+        if(!m_buffer) {
+            m_buffer = new(std::nothrow) char[m_buffer_size];
+            if(!m_buffer) {
+                LOGE("Couldn't allocate m_buffer");
+                throw UnknownException("Memory allocation error");
+            }
+        }
+
+        size_t total_bytes_read = 0;
+        size_t size_read = 0;
+
+        do {
+            size_read = fread(m_buffer, 1, m_buffer_size, m_input_file);
+            if (size_read < m_buffer_size &&
+                        feof(m_input_file) == 0) {
+                LOGE("Error reading source file: %s\n", src_file_path.c_str());
+                throw UnknownException("New file addition failed");
+            }
+
+            LOGD("Read: %d bytes from input file:[%s]", size_read,
+                    src_file_path.c_str());
+            total_bytes_read += size_read;
+            m_bytes_compressed += size_read;
+
+            if (size_read > 0) {
+                err = zipWriteInFileInZip (m_owner.m_zip, m_buffer, size_read);
+                if (err < 0) {
+                    LOGE("Error during adding file: %s into zip archive",
+                            src_file_path.c_str());
+                    throw UnknownException("New file addition failed");
+                }
+            }
+
+            if(total_bytes_read == in_file_size) {
+                LOGD("Finished reading and compressing source file: [%s]",
+                        src_file_path.c_str());
+                ++m_files_compressed;
+            }
+
+            LOGD("Callculatting overall progress: %llu/%llu bytes; "
+                    "%d/%d files; current file: [%s] progress: %d/%d bytes; ",
+                    m_bytes_compressed, m_bytes_to_compress,
+                    m_files_compressed, m_files_to_compress,
+                    src_file_path.c_str(),
+                    total_bytes_read, in_file_size);
+
+            double progress = 1.0;
+            if(m_bytes_to_compress > 0 || m_files_to_compress > 0) {
+                progress = static_cast<double>(m_bytes_compressed + m_files_compressed) /
+                        static_cast<double>(m_bytes_to_compress + m_files_to_compress);
+            }
+
+            LOGD("Wrote: %s total progress: %.2f%% %d/%d files",
+                    bytesToReadableString(size_read).c_str(), progress * 100.0,
+                    m_files_compressed, m_files_to_compress);
+
+            LOGD("Calling add onprogress callback(%f, %s)", progress,
+                    name_in_zip.c_str());
+            m_callback->callProgressCallbackOnMainThread(progress, cur_afentry);
+
+        } while (size_read > 0 && total_bytes_read < in_file_size);
+
+        if(in_file_size != total_bytes_read) {
+            LOGE("in_file_size(%d) != total_bytes_read(%d)", in_file_size,
+                    total_bytes_read);
+            throw UnknownException("Could not add file to archive");
+        }
+
+        fclose(m_input_file);
+        m_input_file = NULL;
+    }
+
+    err = zipCloseFileInZip(m_owner.m_zip);
+    if (ZIP_OK != err) {
+        LOGE("%s",getArchiveLogMessage(err, "zipCloseFileInZip()").c_str());
+    }
+
+    m_new_file_in_zip_opened = false;
+}
+
+std::string removeDirCharsFromFront(const std::string& path)
+{
+    for(size_t i = 0; i < path.length(); ++i) {
+        const char& cur = path[i];
+        if(cur != '/' && cur != '\\') {
+            return path.substr(i);
+        }
+    }
+
+    return std::string();   //in case path contained only slashes
+}
+
+std::string generateFullPathForZip(const std::string& path)
+{
+    //Step 1: Remove / from begining
+    const size_t path_len = path.length();
+
+    size_t start_i = 0;
+    for(size_t i = 0; i < path_len; ++i) {
+        const char& cur = path[i];
+        if(cur != '/' && cur != '\\') {
+            start_i = i;
+            break;
+        }
+    }
+
+    std::string out;
+    out.reserve(path_len);
+
+    //Step 1: Remove duplicated / characters
+    bool prev_is_dir = false;
+    for(size_t i = start_i; i < path_len; ++i) {
+        const char& cur = path[i];
+        if(cur == '/' || cur == '\\') {
+            if(!prev_is_dir) {
+                out += cur;
+            }
+            prev_is_dir = true;
+        } else {
+            prev_is_dir = false;
+            out += cur;
+        }
+    }
+
+    return out;
+}
+
+std::string ZipAddRequest::getNameInZipArchiveFor(Filesystem::NodePtr node, bool strip)
+{
+    const std::string node_full_path = node->getPath()->getFullPath();
+    std::string cut_path;
+
+    const size_t pos = node_full_path.find(m_absoulte_path_to_extract);
+    if(std::string::npos == pos) {
+        LOGW("node: [%s] is not containing m_absoulte_path_to_extract: [%s]!",
+                node_full_path.c_str(),
+                m_absoulte_path_to_extract.c_str());
+    }
+
+    cut_path = node_full_path.substr(pos+m_absoulte_path_to_extract.length());
+    LOGD("node_full_path:%s cut_path: %s", node_full_path.c_str(), cut_path.c_str());
+
+    if(!strip) {
+        cut_path = m_callback->getBaseVirtualPath() + "/" + cut_path;
+        LOGD("nonstripped cut_path: %s", cut_path.c_str());
+    }
+
+    std::string name = generateFullPathForZip(m_destination_path_in_zip + "/" + cut_path);
+    if(node->getType() == Filesystem::NT_DIRECTORY) {
+        if(name.length() > 0
+                && name[name.length()-1] != '/'
+                && name[name.length()-1] != '\\') {
+            name += "/";
+            LOGD("Directory: [%s] added \\", name.c_str());
+        }
+    }
+
+    return name;
+}
+
+} //namespace Archive
+} //namespace DeviceAPI
diff --git a/src/Archive/ZipAddRequest.h b/src/Archive/ZipAddRequest.h
new file mode 100644 (file)
index 0000000..a40db2d
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ARCHIVE_ZIP_ADD_REQUEST_H__
+#define __TIZEN_ARCHIVE_ZIP_ADD_REQUEST_H__
+
+#include <stdio.h>
+#include <string>
+
+#include <File.h>
+#include <Node.h>
+#include <Path.h>
+
+#include "ArchiveCallbackData.h"
+#include "Zip.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+class ZipAddRequest
+{
+public:
+
+    /**
+     * When request has finished callback is set to NULL and is
+     * deleted on main thread after calling all progress callbacks.
+     * If exception is thrown please delete callback.
+     */
+    static void execute(Zip& owner, AddProgressCallback*& callback);
+    ~ZipAddRequest();
+
+private:
+    ZipAddRequest(Zip& owner, AddProgressCallback*& callback);
+    void run();
+
+    void addNodeAndSubdirsToList(Filesystem::NodePtr src_node,
+            Filesystem::NodeList& out_list_of_child_nodes);
+
+    void addEmptyDirectoryToZipArchive(std::string name_in_zip);
+    void addToZipArchive(Filesystem::NodePtr src_file_node);
+
+    std::string getNameInZipArchiveFor(Filesystem::NodePtr node, bool strip);
+
+    //-----------------------------------------------------------------------------
+    //Input request variables
+    Zip& m_owner;
+    AddProgressCallback* m_callback;
+
+
+    FILE* m_input_file;
+    char* m_buffer;
+    size_t m_buffer_size;
+
+
+    unsigned long m_files_to_compress;
+    unsigned long long m_bytes_to_compress;
+
+    unsigned long m_files_compressed;
+    unsigned long long m_bytes_compressed;
+
+    Filesystem::FilePtr m_root_src_file;
+    Filesystem::NodePtr m_root_src_file_node;
+    std::string m_absoulte_path_to_extract;
+    std::string m_destination_path_in_zip;
+
+    unsigned int m_compression_level;
+
+    bool m_new_file_in_zip_opened;
+};
+
+} //namespace Archive
+} //namespace DeviceAPI
+
+#endif // __TIZEN_ARCHIVE_ZIP_ADD_REQUEST_H__
diff --git a/src/Archive/config.xml b/src/Archive/config.xml
new file mode 100755 (executable)
index 0000000..d7c7073
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-archive.so</library-name>
+    <feature-install-uri>archive.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/filesystem.read</name>
+        <device-capability>filesystem.read</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/filesystem.write</name>
+        <device-capability>filesystem.write</device-capability>
+    </api-feature>
+</plugin-properties>
diff --git a/src/Archive/plugin_config.cpp b/src/Archive/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..18647b0
--- /dev/null
@@ -0,0 +1,144 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <map>
+#include <Commons/FunctionDefinition.h>
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Archive {
+
+namespace{
+const char* ARCHIVE_FEATURE_API_WRITE = "http://tizen.org/privilege/filesystem.write";
+const char* ARCHIVE_FEATURE_API_READ = "http://tizen.org/privilege/filesystem.read";
+
+const char* ARCHIVE_DEVICE_CAP_WRITE = "filesystem.write";
+const char* ARCHIVE_DEVICE_CAP_READ = "filesystem.read";
+}
+
+static FunctionMapping createArchiveFunctions();
+
+static FunctionMapping ArchiveFunctions = createArchiveFunctions();
+
+#pragma GCC visibility push(default)
+DEFINE_FUNCTION_GETTER(Archive, ArchiveFunctions);
+#pragma GCC visibility pop
+
+static FunctionMapping createArchiveFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_ARCHIVE_WRITE, ARCHIVE_DEVICE_CAP_WRITE);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_ARCHIVE_READ, ARCHIVE_DEVICE_CAP_READ);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_ARCHIVE_WRITE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_ARCHIVE_WRITE, DEVICE_CAP_ARCHIVE_WRITE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_ARCHIVE_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_ARCHIVE_READ, DEVICE_CAP_ARCHIVE_READ);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_ARCHIVE_READ, ARCHIVE_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_ARCHIVE_WRITE, ARCHIVE_FEATURE_API_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(ARCHIVE_FEATURES_READ);
+    ACE_ADD_API_FEATURE(ARCHIVE_FEATURES_READ, FEATURE_ARCHIVE_READ);
+
+    ACE_CREATE_FEATURE_LIST(ARCHIVE_FEATURES_WRITE);
+    ACE_ADD_API_FEATURE(ARCHIVE_FEATURES_WRITE, FEATURE_ARCHIVE_WRITE);
+
+    /**
+     * Functions
+     */
+    FunctionMapping archiveMapping;
+
+    // open
+    AceFunction archiveFileOpenFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ARCHIVE_FILE_OPEN,
+            ARCHIVE_FUNCTION_API_ARCHIVE_MANAGER_OPEN,
+            ARCHIVE_FEATURES_WRITE,
+            DEVICE_LIST_ARCHIVE_WRITE);
+
+    archiveMapping.insert(std::make_pair(
+                                ARCHIVE_FUNCTION_API_ARCHIVE_MANAGER_OPEN,
+                                archiveFileOpenFunc));
+
+    // add
+    AceFunction archiveFileAddFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ARCHIVE_FILE_ADD,
+            ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ADD,
+            ARCHIVE_FEATURES_WRITE,
+            DEVICE_LIST_ARCHIVE_WRITE);
+
+    archiveMapping.insert(std::make_pair(
+                                ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ADD,
+                                archiveFileAddFunc));
+
+    // extractAll
+    AceFunction archiveFileExtractAllFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ARCHIVE_FILE_EXTRACT_ALL,
+            ARCHIVE_FUNCTION_API_ARCHIVE_FILE_EXTRACT_ALL,
+            ARCHIVE_FEATURES_WRITE,
+            DEVICE_LIST_ARCHIVE_WRITE);
+
+    archiveMapping.insert(std::make_pair(
+                                ARCHIVE_FUNCTION_API_ARCHIVE_FILE_EXTRACT_ALL,
+                                archiveFileExtractAllFunc));
+
+    // getEntries
+    AceFunction archiveFileGetEntriesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ARCHIVE_FILE_GET_ENTRIES,
+            ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRIES,
+            ARCHIVE_FEATURES_READ,
+            DEVICE_LIST_ARCHIVE_READ);
+
+    archiveMapping.insert(std::make_pair(
+                                ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRIES,
+                                archiveFileGetEntriesFunc));
+
+    // getEntryByName
+    AceFunction archiveFileGetEntryByNameFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ARCHIVE_FILE_GET_ENTRY_BY_NAME,
+            ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRY_BY_NAME,
+            ARCHIVE_FEATURES_READ,
+            DEVICE_LIST_ARCHIVE_READ);
+
+    archiveMapping.insert(std::make_pair(
+                                ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRY_BY_NAME,
+                                archiveFileGetEntryByNameFunc));
+
+    // extract
+    AceFunction archiveFileEntryExtractFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ARCHIVE_FILE_ENTRY_EXTRACT,
+            ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ENTRY_EXTRACT,
+            ARCHIVE_FEATURES_WRITE,
+            DEVICE_LIST_ARCHIVE_WRITE);
+
+    archiveMapping.insert(std::make_pair(
+                                ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ENTRY_EXTRACT,
+                                archiveFileEntryExtractFunc));
+
+    return archiveMapping;
+}
+
+}
+}
diff --git a/src/Archive/plugin_config.h b/src/Archive/plugin_config.h
new file mode 100755 (executable)
index 0000000..b1dc7d8
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ARCHIVE_PLUGIN_CONFIG_H_
+#define _ARCHIVE_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+DECLARE_FUNCTION_GETTER(Archive);
+
+#define ARCHIVE_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getArchiveFunctionData, \
+    functionName)
+
+} // Archive
+} // DeviceAPI
+
+#endif // _ARCHIVE_PLUGIN_CONFIG_H_
diff --git a/src/Archive/plugin_config_impl.h b/src/Archive/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..8ac0abe
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _ARCHIVE_PLUGIN_CONFIG_IMPL_H_
+#define _ARCHIVE_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_ARCHIVE_ARCHIVE_CLASS                             "archive"
+
+#define ARCHIVE_FUNCTION_API_ARCHIVE_MANAGER_ABORT              "abort"
+#define ARCHIVE_FUNCTION_API_ARCHIVE_MANAGER_OPEN               "open"
+
+#define ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ADD                   "add"
+#define ARCHIVE_FUNCTION_API_ARCHIVE_FILE_EXTRACT_ALL           "extractAll"
+#define ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRIES           "getEntries"
+#define ARCHIVE_FUNCTION_API_ARCHIVE_FILE_GET_ENTRY_BY_NAME     "getEntryByName"
+#define ARCHIVE_FUNCTION_API_ARCHIVE_FILE_CLOSE                 "close"
+
+#define ARCHIVE_FUNCTION_API_ARCHIVE_FILE_ENTRY_EXTRACT         "extract"
+
+
+
+#endif // _ARCHIVE_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/Archive/plugin_initializer.cpp b/src/Archive/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..c289411
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <GlobalContextManager.h>
+#include <Logger.h>
+
+#include "JSArchiveManager.h"
+#include "JSArchiveFile.h"
+#include "JSArchiveFileEntry.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Archive {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+namespace Options{
+class_definition_options_t ArchiveOptions = {
+    JS_CLASS,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED,
+    NULL,
+    NULL,
+    NULL
+};
+}
+
+void on_widget_start_callback(int widget_id)
+{
+    LOGD("[TIZEN\\Archive] on_widget_start_callback (%d)", widget_id);
+    try {
+        WrtAccessSingleton::Instance().initialize(widget_id);
+    }
+    catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widget_id)
+{
+    LOGD("[TIZEN\\Archive ] on_widget_stop_callback (%d)", widget_id);
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widget_id);
+    }
+    catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void* context)
+{
+    LOGD("[Tizen\\Archive] on_frame_unload_callback ( %p )", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void* context)
+{
+    LOGD("[Tizen\\Archive] on_frame_unload_callback ( %p )", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_ARCHIVE_ARCHIVE_CLASS,
+        (js_class_template_getter)JSArchiveManager::getClassRef,
+        &Options::ArchiveOptions)
+PLUGIN_CLASS_MAP_END
+
+}
+}
+
diff --git a/src/Badge/BadgeManager.cpp b/src/Badge/BadgeManager.cpp
new file mode 100755 (executable)
index 0000000..da37219
--- /dev/null
@@ -0,0 +1,405 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "BadgeManager.h"
+
+#include <glib.h>
+#include <badge.h>
+#include <badge_internal.h>
+#include <JSUtil.h>
+#include <fcntl.h>
+#include <aul.h>
+#include <package_manager.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <Logger.h>
+#include <pkgmgr-info.h>
+#include <errno.h>
+
+using namespace DeviceAPI::Common;
+using namespace std;
+
+namespace DeviceAPI {
+namespace Badge {
+
+typedef struct {
+    unsigned int action;
+    const char* pkgname;
+    unsigned int count;
+    void* user_data;
+} BADGE_EVENT_DATA_T;
+
+static gboolean badgeEventCB(void *data) {
+    LOGD("enter");
+    BADGE_EVENT_DATA_T *fnData = static_cast<BADGE_EVENT_DATA_T*>(data);
+
+    try {
+        unsigned int action = (unsigned int)(fnData->action);
+        if (action == BADGE_ACTION_UPDATE) {
+            char* pkgname = (char*)(fnData->pkgname);
+            if (!pkgname) {
+                LOGE("pkgname is NULL.");
+                throw UnknownException("pkgname is NULL.");
+            }
+            std::string appId(pkgname);
+
+            long count = (long)(fnData->count);
+
+            BadgeManager *thisObj = (BadgeManager*)(fnData->user_data);
+            if (!thisObj) {
+                LOGE("UserData is NULL.");
+                throw UnknownException("UserData is NULL.");
+            }
+
+            LOGD("%d, %s, %s, %d",action ,pkgname,appId.c_str() ,count);
+            CallbackUserData *callback = thisObj->getCallbackFromMap(appId);
+            if (callback) {
+                LOGD("Invoke badge callback application id : %s, %d", appId.c_str(), count);
+                JSValueRef argAppId = JSUtil::toJSValueRef(callback->getContext(), appId);
+                JSValueRef argCount = JSUtil::toJSValueRef(callback->getContext(), count);
+                JSValueRef args[2] = { argAppId, argCount };
+                callback->callSuccessCallback(2, args);
+                LOGD("success callback called");
+            } else {
+                LOGE("No matched application id : %s", appId.c_str());
+            }
+
+        } else {
+            LOGE("Invaild callback action : %d", action);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("badge_state_changed_cb: %s", err.getMessage().c_str());
+    }
+
+    delete fnData;
+    return false;
+}
+
+static void badge_changed_cb(unsigned int action, const char *pkgname, unsigned int count, void *user_data)
+{
+    LOGD("enter");
+
+    BADGE_EVENT_DATA_T *data = new BADGE_EVENT_DATA_T;
+    data->action = action;
+    data->pkgname = pkgname;
+    data->count = count;
+    data->user_data = user_data;
+
+    LOGD("action : %d , pkgname : %s , count : %d", action, pkgname, count);
+    g_idle_add(badgeEventCB, static_cast<void*>(data));
+}
+
+void BadgeManager::setCallbackToMap(std::string appId, CallbackUserData *callback)
+{
+    LOGD("enter");
+
+    CallbackUserData *value = mBadgeCallbacks[appId];
+    if (value) {
+        delete value;
+        LOGD("prev callback delete");
+    }
+    mBadgeCallbacks[appId] = callback;
+    LOGD("insert callback %s", appId.c_str());
+    LOGD("callback size : %d", mBadgeCallbacks.size());
+}
+
+CallbackUserData* BadgeManager::getCallbackFromMap(std::string appId)
+{
+    LOGD("get callback %s", appId.c_str());
+    return mBadgeCallbacks[appId];
+}
+
+void BadgeManager::removeCallbackFromMap(std::string appId) {
+    LOGD("enter");
+
+    CallbackUserData *value = mBadgeCallbacks[appId];
+    mBadgeCallbacks.erase(appId);
+    if (value) {
+        delete value;
+    }
+
+    LOGD("callback size : %d", mBadgeCallbacks.size());
+}
+
+
+long BadgeManager::getBadgeCount(const char* appId)
+{
+    char *pkgname = NULL;
+    pkgname = _badge_get_pkgname_by_appid(appId);
+    if (!pkgname) {
+        LOGE("InvalidValues error : appId");
+        throw InvalidValuesException("InvalidValues error : appId");
+    } else {
+        if (pkgname) {free(pkgname);}
+    }
+
+    int ret = BADGE_ERROR_SERVICE_NOT_READY;
+    bool badgeExist = FALSE;
+    ret = badge_is_existing(appId, &badgeExist);
+    if (ret != BADGE_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, BadgeUtil::getBadgeErrorMessage(ret).c_str());
+        BadgeUtil::throwBadgeException(ret,"");
+    }
+    LOGD("badge exist : %d ", badgeExist);
+    unsigned int count = 0;
+
+    if (!badgeExist) {
+        LOGE("badge not exist. appId : %d", appId);
+        return static_cast<long>(count);
+    }
+
+    ret = badge_get_count(appId, &count);
+    if (ret == BADGE_ERROR_NONE) {
+        LOGD("ret : %d , count : %d", ret, count);
+        return static_cast<long>(count);
+    } else{
+        LOGE("ret : %d , %s", ret, BadgeUtil::getBadgeErrorMessage(ret).c_str());
+        BadgeUtil::throwBadgeException(ret,"");
+    }
+}
+
+void BadgeManager::addChangeListener(BadgeCallbackMapT& badgeCallback)
+{
+    LOGD("enter");
+
+    bool badgeExist = FALSE;
+    int ret = BADGE_ERROR_SERVICE_NOT_READY;
+
+    try {
+        BadgeCallbackMapT::iterator itr = badgeCallback.begin();
+
+        if (mBadgeCallbacks.empty()) {
+            ret = badge_register_changed_cb(badge_changed_cb, this);
+            if (ret != BADGE_ERROR_NONE) {
+                LOGE("ret : %d , %s", ret, BadgeUtil::getBadgeErrorMessage(ret).c_str());
+                BadgeUtil::throwBadgeException(ret,"");
+            }
+        }
+
+        itr = badgeCallback.begin();
+        while (itr != badgeCallback.end()) {
+            setCallbackToMap(itr->first, itr->second);
+            ++itr;
+            LOGD("set callback to map");
+        }
+
+    } catch (const BasePlatformException &err) {
+        LOGE("addChangeListener: %s", err.getMessage().c_str());
+    }
+}
+
+void BadgeManager::removeChangeListener(std::vector<std::string>& appIdList)
+{
+    LOGD("enter");
+
+    std::vector<std::string>::iterator itr = appIdList.begin();
+
+    while (itr != appIdList.end()) {
+        removeCallbackFromMap(*itr);
+        ++itr;
+    }
+
+    if (mBadgeCallbacks.empty()) {
+        int ret = badge_unregister_changed_cb(badge_changed_cb);
+        if (ret != BADGE_ERROR_NONE) {
+            LOGE("unknown error : %d , %s", ret, BadgeUtil::getBadgeErrorMessage(ret).c_str());
+        }
+    }
+}
+
+BadgeManager* BadgeManager::getInstance(){
+    static BadgeManager instance;
+    return &instance;
+}
+
+BadgeManager::BadgeManager()
+{
+}
+
+BadgeManager::~BadgeManager()
+{
+    LOGD("enter");
+
+    BadgeCallbackMapT::iterator itr = mBadgeCallbacks.begin();
+    while (itr != mBadgeCallbacks.end()) {
+        CallbackUserData *value = itr->second;
+        if (value) {
+            delete value;
+        }
+        ++itr;
+    }
+
+    int ret = badge_unregister_changed_cb(badge_changed_cb);
+    if (ret != BADGE_ERROR_NONE) {
+        LOGE("unknown error : %d , %s", ret, BadgeUtil::getBadgeErrorMessage(ret).c_str());
+    }
+}
+
+bool BadgeManager::checkPermisionForCreatingBadge(const char* appId)
+{
+    if (!appId) {
+        LOGE("InvalidValues error : appId");
+        throw InvalidValuesException("InvalidValues error : appId");
+    }
+
+    char *caller_appid = NULL;
+    caller_appid = _badge_get_pkgname_by_pid();
+    if (!caller_appid) {
+        LOGE("fail to get caller pkgId");
+        throw UnknownException("Platform error while getting caller pkgId.");
+    }
+
+    char *caller_pkgname = NULL;
+    caller_pkgname = _badge_get_pkgname_by_appid(caller_appid);
+    if (!caller_pkgname) {
+        if (caller_appid) {free(caller_appid);}
+        LOGE("fail to get caller pkgId");
+        throw UnknownException("Platform error while getting caller pkgId.");
+    }
+
+    char *pkgname = NULL;
+    pkgname = _badge_get_pkgname_by_appid(appId);
+    if (!pkgname) {
+        if (caller_appid) {free(caller_appid);}
+        if (caller_pkgname) {free(caller_pkgname);}
+        LOGE("fail to get pkgId");
+        throw InvalidValuesException("InvalidValues error : appId");
+    }
+
+    bool flag = false;
+    if (_badge_is_same_certinfo(caller_pkgname, pkgname) == 1) {
+        flag = true;
+    } else {
+        LOGE("The author signature is not match");
+        flag = false;
+    }
+
+    if (caller_appid) {free(caller_appid);}
+    if (caller_pkgname) {free(caller_pkgname);}
+    if (pkgname) {free(pkgname);}
+
+    return flag;
+}
+
+char* BadgeManager::_badge_get_pkgname_by_appid(const char* appId)
+{
+    LOGD("enter");
+    char *pkgId = NULL;
+    pkgmgrinfo_appinfo_h pkgmgrinfo_appinfo;
+    int ret = PACKAGE_MANAGER_ERROR_NONE;
+
+    if (!appId) {
+        LOGE("appId is null");
+        return NULL;
+    }
+
+    ret = pkgmgrinfo_appinfo_get_appinfo(appId, &pkgmgrinfo_appinfo);
+    if (ret != PMINFO_R_OK)
+    {
+        LOGE("fail to get caller pkgId : %d", ret);
+        return NULL;
+    }
+
+    ret = pkgmgrinfo_appinfo_get_pkgname(pkgmgrinfo_appinfo, &pkgId);
+    if (ret != PMINFO_R_OK)
+    {
+        LOGE("fail to get caller pkgId : %d", ret);
+        return NULL;
+    }
+
+    if (!pkgId)
+    {
+        LOGE("fail to get caller pkgId");
+        return NULL;
+    }
+
+    return pkgId;
+}
+
+int BadgeManager::_badge_is_same_certinfo(const char *caller, const char *pkgname)
+{
+    int ret = PACKAGE_MANAGER_ERROR_NONE;
+    package_manager_compare_result_type_e compare_result = PACKAGE_MANAGER_COMPARE_MISMATCH;
+
+    if (!caller) {
+        return 0;
+    }
+    if (!pkgname) {
+        return 0;
+    }
+
+    LOGD("pkgname : %s , caller : %s", pkgname, caller);
+    ret = package_manager_compare_package_cert_info(pkgname, caller, &compare_result);
+    LOGD("return : %d , compare result : %d", ret, compare_result);
+    if (ret == PACKAGE_MANAGER_ERROR_NONE && compare_result == PACKAGE_MANAGER_COMPARE_MATCH) {
+        LOGD("compare match");
+        return 1;
+    }
+
+    LOGD("compare no match");
+    return 0;
+}
+
+char* BadgeManager::_badge_get_pkgname_by_pid()
+{
+    char *pkgname = NULL;
+    int pid = 0;
+    int ret = AUL_R_OK;
+    int fd = 0;
+    long max = 4096;
+
+    pid = getpid();
+    pkgname = static_cast<char*>(malloc(max));
+    if (!pkgname) {
+        LOGE("fail to alloc memory");
+        return NULL;
+    }
+    memset(pkgname, 0x00, max);
+
+    ret = aul_app_get_pkgname_bypid(pid, pkgname, max);
+    if (ret != AUL_R_OK) {
+        LOGE("ret %d", ret);
+        fd = open("/proc/self/cmdline", O_RDONLY);
+        if (fd < 0) {
+            LOGE("open failed : %d", fd);
+            LOGE("errno : %d , %s", errno, strerror(errno));
+            free(pkgname);
+            return NULL;
+        }
+
+        ret = read(fd, pkgname, max - 1);
+        if (ret <= 0) {
+            LOGE("read failed : %d", ret);
+            LOGE("errno : %d , %s", errno, strerror(errno));
+            close(fd);
+            free(pkgname);
+            return NULL;
+        }
+
+        close(fd);
+    }
+
+    if (pkgname[0] == '\0') {
+        free(pkgname);
+        return NULL;
+    } else
+        return pkgname;
+}
+
+}
+}
+
diff --git a/src/Badge/BadgeManager.h b/src/Badge/BadgeManager.h
new file mode 100755 (executable)
index 0000000..651d44d
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _BADGE_MANAGER_H_
+#define _BADGE_MANAGER_H_
+
+#include <string>
+#include <vector>
+#include <map>
+#include <CallbackUserData.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <badge.h>
+#include "BadgeUtil.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Badge {
+
+typedef std::map<std::string, CallbackUserData*> BadgeCallbackMapT;
+
+class BadgeManager
+{
+    public:
+        long getBadgeCount(const char* appId);
+        void addChangeListener(BadgeCallbackMapT& badgeCallback);
+        void removeChangeListener(std::vector<std::string>& appIdList);
+        bool checkPermisionForCreatingBadge(const char* appId);
+
+        static BadgeManager* getInstance();
+
+        // internal function
+        void setCallbackToMap(std::string appId, CallbackUserData *callback);
+        CallbackUserData* getCallbackFromMap(std::string appId);
+        void removeCallbackFromMap(std::string appId);
+
+    private:
+        BadgeManager();
+        virtual ~BadgeManager();
+
+        char* _badge_get_pkgname_by_appid(const char* appId);
+        int _badge_is_same_certinfo(const char *caller, const char *pkgname);
+        char* _badge_get_pkgname_by_pid();
+
+        BadgeCallbackMapT mBadgeCallbacks;
+
+};
+
+}
+}
+
+#endif
+
+
diff --git a/src/Badge/BadgeUtil.cpp b/src/Badge/BadgeUtil.cpp
new file mode 100755 (executable)
index 0000000..ddeb894
--- /dev/null
@@ -0,0 +1,74 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "BadgeUtil.h"
+
+#include <sstream>
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Badge {
+
+using namespace DeviceAPI::Common;
+
+void BadgeUtil::throwBadgeException(const int errorCode, const std::string &hint)
+{
+    std::stringstream ss;
+    ss << hint << " : " << getBadgeErrorMessage(errorCode);
+    LOGE("%s", ss.str().c_str());
+
+    switch(errorCode) {
+        case BADGE_ERROR_INVALID_PARAMETER:
+            throw InvalidValuesException(ss.str().c_str());
+        case BADGE_ERROR_PERMISSION_DENIED:
+            throw SecurityException(ss.str().c_str());
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+std::string BadgeUtil::getBadgeErrorMessage(const int errorCode)
+{
+    LOGE("%d", errorCode);
+
+    switch(errorCode) {
+        case BADGE_ERROR_INVALID_PARAMETER:
+            return "Invalid Parameter";
+        case BADGE_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case BADGE_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case BADGE_ERROR_IO_ERROR:
+            return "IO error";
+        case BADGE_ERROR_FROM_DB:
+            return "Database error";
+        case BADGE_ERROR_ALREADY_EXIST:
+            return "Already exist";
+        case BADGE_ERROR_FROM_DBUS:
+            return "Dbus error";
+        case BADGE_ERROR_NOT_EXIST:
+            return "Not exist";
+        case BADGE_ERROR_SERVICE_NOT_READY:
+            return "Service not ready";
+        default:
+            return "Unknown Error";
+    }
+}
+
+} // Account
+} // DeviceAPI
diff --git a/src/Badge/BadgeUtil.h b/src/Badge/BadgeUtil.h
new file mode 100755 (executable)
index 0000000..91ea7ed
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BADGE_UTIL_H_
+#define __TIZEN_BADGE_UTIL_H_
+
+#include <string>
+#include <badge.h>
+
+
+namespace DeviceAPI {
+namespace Badge {
+
+class BadgeUtil {
+public:
+    static void throwBadgeException(const int errorCode, const std::string &hint);
+    static std::string getBadgeErrorMessage(const int errorCode);
+};
+
+} // Badge
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_ACCOUNT_UTIL_H_
diff --git a/src/Badge/CMakeLists.txt b/src/Badge/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..2f58f88
--- /dev/null
@@ -0,0 +1,47 @@
+SET(TARGET_NAME ${badge_target})
+SET(DESTINATION_NAME ${badge_dest})
+SET(TARGET_IMPL_NAME ${badge_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_badge REQUIRED badge capi-appfw-package-manager pkgmgr-info)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_badge_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSBadgeManager.cpp
+    BadgeManager.cpp
+    BadgeUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${platform_pkgs_badge_LIBRARIES}
+)
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/badge
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Badge/JSBadgeManager.cpp b/src/Badge/JSBadgeManager.cpp
new file mode 100755 (executable)
index 0000000..a4f29ce
--- /dev/null
@@ -0,0 +1,334 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <Commons/Exception.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <badge.h>
+#include <badge_internal.h>
+#include <Logger.h>
+
+#include "JSBadgeManager.h"
+#include "BadgeManager.h"
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+
+namespace DeviceAPI {
+namespace Badge {
+
+#define BADGE_ATTR_MAXBADGECOUNT "maxBadgeCount"
+#define BADGE_MAXBADGECOUNT 999
+
+#define BADGE_SETCOUNT "setBadgeCount"
+#define BADGE_GETCOUNT "getBadgeCount"
+#define BADGE_ADDCHANGELISTENER "addChangeListener"
+#define BADGE_REMOVECHANGELISTENER "removeChangeListener"
+
+JSClassRef JSBadgeManager::m_jsClassRef = NULL;
+
+JSClassDefinition JSBadgeManager::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    "BadgeManager",
+    NULL,
+    m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    hasInstance,
+    NULL
+};
+
+JSStaticValue JSBadgeManager::m_property[] = {
+    { BADGE_ATTR_MAXBADGECOUNT, getMaxBadgeCount, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+
+JSStaticFunction JSBadgeManager::m_function[] =
+{
+    { BADGE_SETCOUNT, setBadgeCount, kJSPropertyAttributeNone },
+    { BADGE_GETCOUNT, getBadgeCount, kJSPropertyAttributeNone },
+    { BADGE_ADDCHANGELISTENER, addChangeListener, kJSPropertyAttributeNone },
+    { BADGE_REMOVECHANGELISTENER, removeChangeListener, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSBadgeManager::getClassRef()
+{
+    if (!m_jsClassRef)
+    {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+
+const JSClassDefinition* JSBadgeManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+void JSBadgeManager::initialize(JSContextRef context, JSObjectRef object)
+{
+}
+
+void JSBadgeManager::finalize(JSObjectRef object)
+{
+    LOGD("JSBadgeManager::finalize");
+}
+
+bool JSBadgeManager::hasInstance(JSContextRef context, JSObjectRef constructor,
+        JSValueRef possibleInstance, JSValueRef* exception)
+{
+    return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
+}
+
+JSValueRef JSBadgeManager::getMaxBadgeCount(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try
+    {
+        return JSUtil::toJSValueRef(context, static_cast<long>(BADGE_MAXBADGECOUNT));
+    }
+    catch(const WrtDeviceApis::Commons::Exception& err)
+    {
+        LOGE("trying to get incorrect value");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSBadgeManager::setBadgeCount (
+    JSContextRef context, JSObjectRef object,
+    JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+    JSValueRef* exception)
+
+{
+    LOGD("Enter");
+
+    AceSecurityStatus status = BADGE_CHECK_ACCESS(BADGE_FUNCTION_API);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try
+    {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string appId = validator.toString(0, false);
+        long count = validator.toLong(1, false);
+
+        if (appId.empty()) {
+            return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid application ID");
+        }
+
+        if (count < 0) {
+            return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid badge count");
+        }
+
+        int ret = BADGE_ERROR_SERVICE_NOT_READY;
+        bool badgeExist = FALSE;
+        ret = badge_is_existing(appId.c_str(), &badgeExist);
+        if (ret != BADGE_ERROR_NONE) {
+            LOGE("ret : %d , %s", ret, BadgeUtil::getBadgeErrorMessage(ret).c_str());
+            BadgeUtil::throwBadgeException(ret,"");
+        }
+
+        LOGD("badge exist : %d", badgeExist);
+        if (!badgeExist) {
+            if (!(BadgeManager::getInstance()->checkPermisionForCreatingBadge(appId.c_str()))) {
+                return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::SECURITY_ERROR, "The author signature is not match");
+            }
+
+            LOGD("badge create %s", appId.c_str());
+            ret = badge_create(appId.c_str(), appId.c_str());
+            if (ret != BADGE_ERROR_NONE) {
+                LOGE("ret : %d , %s", ret, BadgeUtil::getBadgeErrorMessage(ret).c_str());
+                BadgeUtil::throwBadgeException(ret,"");
+            }
+        }
+
+        ret = badge_set_count(appId.c_str(), count);
+        LOGD("count : %d", count);
+        if (ret != BADGE_ERROR_NONE) {
+                LOGE("ret : %d , %s", ret, BadgeUtil::getBadgeErrorMessage(ret).c_str());
+                BadgeUtil::throwBadgeException(ret,"");
+        }
+
+    } catch (const BasePlatformException &err) {
+        LOGE("error : %s", err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("");
+        LOGE("error : %s", err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+
+}
+
+JSValueRef JSBadgeManager::getBadgeCount (
+    JSContextRef context, JSObjectRef object,
+    JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+    JSValueRef* exception)
+
+{
+    LOGD("Enter");
+
+    AceSecurityStatus status = BADGE_CHECK_ACCESS(BADGE_FUNCTION_API);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try
+    {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string appId = validator.toString(0, false);
+
+        if (appId.empty()) {
+            return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid application ID");
+        }
+
+        long count = BadgeManager::getInstance()->getBadgeCount(appId.c_str());
+        LOGD("[getBadgeCount] appId : %s , count : %d", appId.c_str(), count);
+
+        return JSUtil::toJSValueRef(context, count);
+    } catch (const BasePlatformException &err) {
+        LOGE("error : %s", err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("");
+        LOGE("error : %s", err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSBadgeManager::addChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    AceSecurityStatus status = BADGE_CHECK_ACCESS(BADGE_FUNCTION_API);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef dataArrayObj = validator.toArrayObject(0);
+        JSObjectRef func = validator.toFunction(1);
+
+        size_t size = JSGetArrayLength(context, dataArrayObj);
+        std::vector<std::string> applicationIds;
+        for(size_t i = 0; i < size; ++i) {
+            JSValueRef element = JSGetArrayElement(context, dataArrayObj, i);
+            std::string tmpAppId(JSUtil::JSValueToString(context, element));
+            if (tmpAppId.empty() || !(tmpAppId.compare("null")) || !(tmpAppId.compare("undefined"))) {
+                return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid application ID");
+            }
+            applicationIds.push_back(tmpAppId);
+        }
+
+        BadgeCallbackMapT badgeCallback;
+        for (std::vector<std::string>::iterator it = applicationIds.begin(); it != applicationIds.end(); ++it) {
+            CallbackUserData *callback = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            callback->setSuccessCallback(func);
+            badgeCallback[*it] = callback;
+        }
+
+        BadgeManager::getInstance()->addChangeListener(badgeCallback);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("error : %s", err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("");
+        LOGE("error : %s", err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSBadgeManager::removeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    AceSecurityStatus status = BADGE_CHECK_ACCESS(BADGE_FUNCTION_API);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef dataArrayObj = validator.toArrayObject(0);
+
+        std::vector<std::string> appIdList;
+        size_t size = JSGetArrayLength(context, dataArrayObj);
+
+        for(size_t i = 0; i < size; ++i) {
+            JSValueRef element = JSGetArrayElement(context, dataArrayObj, i);
+            appIdList.push_back(JSUtil::JSValueToString(context, element));
+        }
+
+        BadgeManager::getInstance()->removeChangeListener(appIdList);
+    } catch (const BasePlatformException &err) {
+        LOGE("error : %s", err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("");
+        LOGE("error : %s", err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    return JSValueMakeUndefined(context);
+}
+
+
+}
+}
diff --git a/src/Badge/JSBadgeManager.h b/src/Badge/JSBadgeManager.h
new file mode 100755 (executable)
index 0000000..771c95e
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _BADGE_JS_BADGE_MANAGER_H_
+#define _BADGE_JS_BADGE_MANAGER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <Commons/IEvent.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <string>
+
+namespace DeviceAPI {
+namespace Badge {
+
+class JSBadgeManager {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static bool hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception);
+
+    static JSValueRef getMaxBadgeCount(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef setBadgeCount (
+        JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    static JSValueRef getBadgeCount (
+        JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    static JSValueRef addChangeListener (
+        JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    static JSValueRef removeChangeListener (
+        JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    static JSClassDefinition m_classInfo;
+    static JSStaticValue m_property[];
+    static JSStaticFunction m_function[];
+    static JSClassRef m_jsClassRef;
+};
+
+}
+}
+
+#endif
+
diff --git a/src/Badge/config.xml b/src/Badge/config.xml
new file mode 100755 (executable)
index 0000000..20bea6d
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-badge.so</library-name>
+    <feature-install-uri>badge.install.uri</feature-install-uri>
+    <api-feature>
+        <name>http://tizen.org/privilege/notification</name>
+    <device-capability>notification</device-capability>
+    </api-feature>
+</plugin-properties>
+
diff --git a/src/Badge/plugin_config.cpp b/src/Badge/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..f91e63e
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <iostream>
+#include <Commons/Exception.h>
+#include <dpl/exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define BADGE_FEATURE_API_BADGE  "http://tizen.org/privilege/notification"
+
+#define BADGE_DEVICE_CAP_BADGE "notification"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Badge {
+
+static FunctionMapping createBadgeFunctions();
+
+static FunctionMapping BadgeFunctions =
+    createBadgeFunctions();
+
+DEFINE_FUNCTION_GETTER(BADGE, BadgeFunctions);
+
+static FunctionMapping createBadgeFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BADGE, BADGE_DEVICE_CAP_BADGE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BADGE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BADGE, DEVICE_CAP_BADGE);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_BADGE, BADGE_FEATURE_API_BADGE);
+
+    ACE_CREATE_FEATURE_LIST(BADGE_FEATURES_BADGE);
+    ACE_ADD_API_FEATURE(BADGE_FEATURES_BADGE, FEATURE_BADGE);
+
+    /**
+     * Functions
+     */
+
+    FunctionMapping BadgeMapping;
+
+    AceFunction BadgeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_API_BADGE,
+            BADGE_FUNCTION_API,
+            BADGE_FEATURES_BADGE,
+            DEVICE_LIST_BADGE);
+
+    BadgeMapping.insert(std::make_pair(
+                               BADGE_FUNCTION_API,
+                               BadgeFunc));
+
+
+
+    return BadgeMapping;
+}
+
+}
+}
+
diff --git a/src/Badge/plugin_config.h b/src/Badge/plugin_config.h
new file mode 100755 (executable)
index 0000000..f9f16d8
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _BADGE_PLUGIN_CONFIG_H_
+#define _BADGE_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+
+namespace DeviceAPI {
+namespace Badge {
+
+#define BADGE_FUNCTION_API       "badge"
+
+DECLARE_FUNCTION_GETTER(BADGE);
+
+#define BADGE_CHECK_ACCESS(functionName)                     \
+        aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(                  \
+            getBADGEFunctionData,           \
+            functionName)
+
+}
+}
+
+#endif
diff --git a/src/Badge/plugin_initializer.cpp b/src/Badge/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..aa5c4e7
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        plugin_initializer.cpp
+ * @brief
+ */
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include "JSBadgeManager.h"
+
+namespace DeviceAPI {
+namespace Badge {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+#define WRT_JS_EXTENSION_OBJECT_TIZEN "tizen"
+
+void on_widget_start_callback(int widgetId)
+{
+    LoggerD("[TIZEN\\Badge ] on_widget_start_callback ("<<widgetId<<")");
+
+    Try
+    {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LoggerE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LoggerD("[TIZEN\\Badge] on_widget_stop_callback ("<<widgetId<<")");
+    Try
+    {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LoggerE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LoggerD("[TIZEN\\Badge] on_frame_load_callback (" << context << ")");
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LoggerD("[TIZEN\\Badge] on_frame_unload_callback (" << context << ")");
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+                    "badge",
+                    (js_class_template_getter)DeviceAPI::Badge::JSBadgeManager::getClassRef,
+                    NULL)
+PLUGIN_CLASS_MAP_END
+
+} // Badge
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothAdapter.cpp b/src/Bluetooth/BluetoothAdapter.cpp
new file mode 100755 (executable)
index 0000000..7f6748c
--- /dev/null
@@ -0,0 +1,1927 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <pcrecpp.h>
+
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include <TimeTracer.h>
+
+#include "plugin_config_impl.h"
+#include "BluetoothAdapter.h"
+#include "BluetoothCallbackUtil.h"
+#include "BluetoothUtil.h"
+#include "JSBluetoothDevice.h"
+#include "JSBluetoothServiceHandler.h"
+#include "JSBluetoothSocket.h"
+#include "GlobalContextManager.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+struct MultiSuccessCallbackHolder {
+    MultiCallbackUserDataPtr ptr;
+    JSValueRef mJSBluetoothSocket;
+};
+
+
+gboolean BluetoothAdapter::callMultiSuccessCallback(void* data)
+{
+    LOGD("Enter");
+    MultiSuccessCallbackHolder* holder =
+        static_cast<MultiSuccessCallbackHolder*>(data);
+
+    if(!holder){
+        LOGE("holder creation failed");
+        return false;
+    }
+    holder->ptr->invokeCallback("onconnect", holder->mJSBluetoothSocket);
+    JSValueUnprotect(holder->ptr->getContext(), holder->mJSBluetoothSocket);
+    delete holder;
+    return false;
+}
+
+gboolean BluetoothAdapter::callCloseCallback(void* data)
+{
+    LOGD("Enter");
+    MultiSuccessCallbackHolder* holder =
+        static_cast<MultiSuccessCallbackHolder*>(data);
+
+    if(!holder){
+        LOGE("holder creation failed");
+        return false;
+    }
+    holder->ptr->invokeCallback("onclose");
+    delete holder;
+    return false;
+
+}
+
+
+void BluetoothAdapter::onStateChangedCB(int result,
+        bt_adapter_state_e adapterState, void *userData)
+{
+    LOGD("Enter %d", result);
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    bool previousState = object->mEnabled;
+    object->mEnabled = (adapterState == BT_ADAPTER_ENABLED) ? true : false;
+    if(object->mEnabled == true) {
+        object->mVisible = object->getVisible();
+    }
+
+    // call onstatechanged in ChangeListener
+    if(previousState != object->mEnabled && result == BT_ERROR_NONE
+            && object->mChangeListener != NULL) {
+        LOGD("call onstatechanged in ChangeListener");
+        object->mChangeListener->invokeCallback("onstatechanged",
+                JSUtil::toJSValueRef(object->mChangeListener->getContext(),
+                    object->mEnabled));
+    }
+
+#ifndef APP_CONTROL_SETTING_SUPPORT
+    // call a result callback of setPowered()
+    if(object->mUserDataList[SET_POWERED] != NULL) {  // requested event
+        LOGD("call a result callback of setPowered()");
+        if(object->mRequestedState != object->mEnabled) {
+            LOGW("Requested state is not equal to current state");
+            return;
+        }
+
+        MultiCallbackUserDataPtr callback =
+            static_cast<MultiCallbackUserDataPtr>(
+                    object->mUserDataList[SET_POWERED]);
+        object->mUserDataList[SET_POWERED].reset();
+        if (!callback) {
+            LOGD("callback is null");
+            return;
+        }
+
+        JSContextRef context = callback->getContext();
+        try {
+            if (result != BT_ERROR_NONE) {
+                LOGE("%d", result);
+                BluetoothUtil::throwBluetoothException(result,
+                    "onStateChangedCB error");
+            }
+
+            callback->invokeCallback("success");
+        } catch (BasePlatformException &e) {
+            LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+             callback->invokeCallback("error",
+                    JSWebAPIErrorFactory::makeErrorObject(context, e));
+        }
+    } else {  // unexpected event
+        LOGW("Bluetooth state is changed unexpectedly");
+    }
+#endif
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothAdapter::onNameChangedCB(char *name, void *userData)
+{
+    LOGD("Enter %d", name);
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    LOGD("changed name: %s", name);
+    // call onnamechanged in ChangeListener
+    if(object->mChangeListener != NULL) {
+        LOGD("call onnamechanged in ChangeListener");
+        object->mChangeListener->invokeCallback("onnamechanged",
+                JSUtil::toJSValueRef(object->mChangeListener->getContext(),
+                    std::string(name)));
+    }
+
+    // call a result callback of setName()
+    if(object->mUserDataList[SET_NAME] != NULL
+            && !strcmp(object->mRequestedName.c_str(), name))
+    {
+        // requested event
+        MultiCallbackUserDataPtr callback =
+            static_cast<MultiCallbackUserDataPtr>(object->mUserDataList[SET_NAME]);
+        object->mUserDataList[SET_NAME].reset();
+        if(callback)
+            callback->invokeCallback("success");
+    } else {
+        // unexpected event
+        LOGW("Bluetooth name is changed unexpectedly");
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothAdapter::onVisibilityChangedCB(int result,
+        bt_adapter_visibility_mode_e visibilityMode, void *userData)
+{
+    LOGE("Enter %d", result);
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    bool previousVisible = object->mVisible;
+    object->mVisible =
+        (visibilityMode != BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE) ? true : false;
+
+    // call onvisibilitychanged in ChangeListener
+    if(object->mChangeListener != NULL) {
+        if(previousVisible != object->mVisible) {
+            LOGD("call onvisibilitychanged in ChangeListener");
+            object->mChangeListener->invokeCallback("onvisibilitychanged",
+                    JSUtil::toJSValueRef(object->mChangeListener->getContext(),
+                        object->mVisible));
+        }
+    }
+#ifndef APP_CONTROL_SETTING_SUPPORT
+    // call a result callback of setVisible()
+    if(object->mUserDataList[SET_VISIBLE] != NULL) {  // requested event
+        if(object->mRequestedVisibility != visibilityMode) {
+            LOGW("Requested visibility is not same to current visibility");
+            return;
+        }
+
+        MultiCallbackUserDataPtr callback =
+            static_cast<MultiCallbackUserDataPtr>(
+                    object->mUserDataList[SET_VISIBLE]);
+        if (!callback) {
+            LOGE("callback is null");
+            return;
+        }
+        object->mUserDataList[SET_VISIBLE].reset();
+        JSContextRef context = callback->getContext();
+
+        try {
+            if (result != BT_ERROR_NONE) {
+                LOGE("%d", result);
+                BluetoothUtil::throwBluetoothException(result,
+                    "onVisibilityChangedCB error");
+            }
+
+            callback->invokeCallback("success");
+        } catch (BasePlatformException &e) {
+            LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+            callback->invokeCallback("error",
+                JSWebAPIErrorFactory::makeErrorObject(context, e));
+        }
+    } else {  // unexpected event
+        LOGW("Bluetooth visibility is changed unexpectedly");
+    }
+#endif
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothAdapter::onDiscoveryStateChangedCB(int result,
+        bt_adapter_device_discovery_state_e discoveryState,
+        bt_adapter_device_discovery_info_s *discoveryInfo, void *userData)
+{
+    LOGE("Enter %d", result);
+
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    switch(discoveryState) {
+        case BT_ADAPTER_DEVICE_DISCOVERY_STARTED:
+        {
+            LOGD("Discovery started");
+
+            if (!object->mUserDataList[DISCOVER_DEVICES]) {
+                LOGW("Unexpected discovery");
+                break;
+            }
+
+            MultiCallbackUserDataPtr callback =
+                static_cast<MultiCallbackUserDataPtr>(
+                    object->mUserDataList[DISCOVER_DEVICES]);
+            if (!callback) {
+                LOGE("callback is null");
+                break;
+            }
+
+            try {
+                if (result != BT_ERROR_NONE) {
+                    LOGE("%d", result);
+                    BluetoothUtil::throwBluetoothException(result,
+                        "onDiscoveryStateChangedCB error");
+                }
+
+                // store MAC address of previously found device into mDisappearedDevices
+                object->mDisappearedDevices.clear();
+                for(auto iter = object->mFoundDevices.begin();
+                        iter != object->mFoundDevices.end(); iter++) {
+                    BluetoothDeviceSharedPtr foundDevice = *iter;
+                    object->mDisappearedDevices.push_back(
+                        foundDevice->getAddress());
+                }
+
+                object->mFoundDevices.clear();
+                callback->invokeCallback("onstarted");
+            } catch (BasePlatformException &e) {
+                LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+                object->mUserDataList[DISCOVER_DEVICES].reset();
+
+                JSContextRef context = callback->getContext();
+                callback->invokeCallback("error",
+                    JSWebAPIErrorFactory::makeErrorObject(context, e));
+            }
+            break;
+        }
+        case BT_ADAPTER_DEVICE_DISCOVERY_FINISHED:
+        {
+            LOGD("Discovery finished");
+            if (result != BT_ERROR_NONE && result != BT_ERROR_CANCELLED) {
+                LOGW("Unexpected result of discovery finish");
+                break;
+            }
+
+            // in case of stopDiscovery()
+            if (object->mUserDataList[STOP_DISCOVERY]) {
+                MultiCallbackUserDataPtr callback =
+                    static_cast<MultiCallbackUserDataPtr>(
+                        object->mUserDataList[STOP_DISCOVERY]);
+
+                if (!callback) {
+                    LOGE("callback is null");
+                    break;
+                }
+
+                LOGD("Call successCallback of stopDiscovery()");
+                object->mUserDataList[STOP_DISCOVERY].reset();
+                callback->invokeCallback("success");
+            }
+
+            if (!object->mUserDataList[DISCOVER_DEVICES]) {
+                LOGW("Unexpected discovery");
+                break;
+            }
+
+            // in case of discoverDevices()
+            MultiCallbackUserDataPtr callback =
+                static_cast<MultiCallbackUserDataPtr>(
+                   object->mUserDataList[DISCOVER_DEVICES]);
+
+            if (!callback) {
+                LOGE("callback is null");
+                break;
+            }
+
+            if(object->mDisappearedDevices.size() > 0) {
+                LOGD("There are disappeared devices");
+                for(auto iter = object->mDisappearedDevices.begin();
+                        iter != object->mDisappearedDevices.end(); iter++) {
+
+                    callback->invokeCallback("ondevicedisappeared",
+                        JSUtil::toJSValueRef(callback->getContext(), *iter));
+                }
+            }
+
+
+            object->mUserDataList[DISCOVER_DEVICES].reset();
+            if (object->mFoundDevices.size() > 0) {
+                // There are found devices
+                LOGD("There are found devices");
+                int num = object->mFoundDevices.size();
+                JSObjectRef devices[num];
+                for(int i = 0; i < num; i++) {
+                    JSObjectRef deviceObj =
+                        JSBluetoothDevice::createJSObject(
+                            callback->getContext(), object->mFoundDevices[i]);
+                    devices[i] = deviceObj;
+                }
+                callback->invokeCallback("onfinished", JSObjectMakeArray(
+                    callback->getContext(), num, devices, NULL));
+            } else {
+                // There is no found device
+                LOGD("There is no found device");
+                callback->invokeCallback("onfinished", JSObjectMakeArray(
+                    callback->getContext(), 0, NULL, NULL));
+            }
+
+            break;
+        }
+        case BT_ADAPTER_DEVICE_DISCOVERY_FOUND:
+        {
+            LOGD("A device is found");
+            if (!discoveryInfo) {
+                LOGW("No information about found device");
+                break;
+            }
+
+            if (!object->mUserDataList[DISCOVER_DEVICES]) {
+                // unexpected event
+                LOGW("Unexpected discovery");
+                break;
+            }
+
+            if (result != BT_ERROR_NONE) {
+                LOGW("Unexpected result of discovery %d: %s",
+                    result,
+                    BluetoothUtil::getBluetoothErrorMessage(result).c_str());
+                break;
+            }
+
+            MultiCallbackUserDataPtr callback =
+                static_cast<MultiCallbackUserDataPtr>(
+                    object->mUserDataList[DISCOVER_DEVICES]);
+
+            // create BluetoothDevice
+            BluetoothDeviceSharedPtr device(
+               new BluetoothDevice(discoveryInfo));
+            device->copyAceCheckAccessFunction(getInstance());
+            JSContextRef context = callback->getContext();
+            JSObjectRef deviceObj =
+                JSBluetoothDevice::createJSObject(context, device);
+            object->mFoundDevices.push_back(device);
+
+            // remove MAC address of found device from mDisappearedDevices
+            for(auto iter = object->mDisappearedDevices.begin();
+                    iter != object->mDisappearedDevices.end(); iter++) {
+                if(!strcmp(discoveryInfo->remote_address, (*iter).c_str())) {
+                    object->mDisappearedDevices.erase(iter);
+                    break;
+                }
+            }
+
+            if (callback)
+                callback->invokeCallback("ondevicefound", deviceObj);
+
+            break;
+        }
+        default:
+        {
+            LOGW("Unknown state");
+        }
+    }
+}
+
+bool BluetoothAdapter::foreachBondedDevicesCB(bt_device_info_s *deviceInfo,
+        void *userData)
+{
+    LOGD("Enter");
+
+    BluetoothAdapterPtr adapter = static_cast<BluetoothAdapterPtr>(userData);
+    if(!adapter) {
+        LOGW("userData is NULL");
+        return true;
+    }
+
+    if(deviceInfo == NULL) {
+        LOGW("deviceInfo is NULL");
+        return true;
+    }
+
+    std::vector<BluetoothDeviceSharedPtr>::iterator iter;
+    for(iter = adapter->knownDevices.begin();
+        iter != adapter->knownDevices.end(); ++iter) {
+
+        BluetoothDeviceSharedPtr foundDevice = *iter;
+        if(!strcmp(foundDevice->getAddress().c_str(), deviceInfo->remote_address)) {
+            foundDevice->updateInfo(deviceInfo);
+            break;
+        }
+    }
+
+    if(iter == adapter->knownDevices.end()) {
+        BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
+        device->copyAceCheckAccessFunction(getInstance());
+        adapter->knownDevices.push_back(device);
+    }
+
+    return true;
+}
+
+void BluetoothAdapter::onBondCreatedCB(int result, bt_device_info_s *deviceInfo,
+        void *userData)
+{
+    LOGD("Enter %d", result);
+
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    if(!deviceInfo) {
+        LOGW("deviceInfo is NULL");
+        return;
+    }
+
+    if (!object->mUserDataList[CREATE_BONDING]) {
+        LOGW("A bonding is created unexpectedly");
+        return;
+    }
+
+    if (strcmp(object->mCreateBondingAddress.c_str(),
+            deviceInfo->remote_address) != 0) {
+        LOGE("A bonding is created unexpectedly %s - %s",
+            object->mCreateBondingAddress.c_str(), deviceInfo->remote_address);
+        return;
+    }
+
+    LOGD("address %s", object->mCreateBondingAddress.c_str());
+
+    MultiCallbackUserDataPtr callback =
+        static_cast<MultiCallbackUserDataPtr>(
+            object->mUserDataList[CREATE_BONDING]);
+    object->mUserDataList[CREATE_BONDING].reset();
+    if (!callback) {
+        LOGE("callback is null");
+        return;
+    }
+
+    JSContextRef context = callback->getContext();
+    try {
+        if (result != BT_ERROR_NONE) {
+            LOGE("%d", result);
+            BluetoothUtil::throwBluetoothException(result,
+                "onBondCreatedCB error");
+        }
+        BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
+        device->copyAceCheckAccessFunction(getInstance());
+        JSContextRef context = callback->getContext();
+        JSObjectRef deviceObj =
+            JSBluetoothDevice::createJSObject(context, device);
+        callback->invokeCallback("success", deviceObj);
+
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        callback->invokeCallback("error",
+            JSWebAPIErrorFactory::makeErrorObject(context, e));
+    }
+
+    int ret = bt_device_unset_bond_created_cb();
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d: %s", ret,
+            BluetoothUtil::getBluetoothErrorMessage(ret).c_str());
+    }
+    object->mCreateBondingAddress.clear();
+}
+
+void BluetoothAdapter::onBondDestroyedCB(int result, char *remoteAddress,
+    void *userData)
+{
+    LOGD("Enter %d", result);
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    if (object->mUserDataList[DESTROY_BONDING] != NULL &&
+            !strcmp(object->mDestroyBondingAddress.c_str(), remoteAddress)) {
+
+        // requested event
+        MultiCallbackUserDataPtr callback =
+            static_cast<MultiCallbackUserDataPtr>(
+                    object->mUserDataList[DESTROY_BONDING]);
+        object->mUserDataList[DESTROY_BONDING].reset();
+        if (!callback) {
+            LOGE("callback is null");
+            return;
+        }
+
+        JSContextRef context = callback->getContext();
+        try {
+            if (result != BT_ERROR_NONE) {
+                LOGE("%d", result);
+                BluetoothUtil::throwBluetoothException(result,
+                    "onBondDestroyedCB error");
+            }
+            callback->invokeCallback("success");
+        } catch (BasePlatformException &e) {
+            LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+            callback->invokeCallback("error",
+                JSWebAPIErrorFactory::makeErrorObject(context, e));
+        }
+
+        bt_device_unset_bond_destroyed_cb();
+        object->mDestroyBondingAddress.clear();
+    }
+    else {  // unexpected event
+        LOGW("A bonding is destroyed unexpectedly");
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothAdapter::onSocketConnected(int result,
+        bt_socket_connection_state_e state,
+        bt_socket_connection_s *connection, void *userData)
+{
+    LOGD("Enter %d", result);
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    if(!connection) {
+        LOGW("connection is NULL");
+        return;
+    }
+
+    if(connection->local_role == BT_SOCKET_SERVER) {
+        auto iter =
+            object->mRegisteredUUID.find(connection->service_uuid);
+        if(iter == object->mRegisteredUUID.end()) {
+            LOGW("Connection state is changed unexpectedly");
+            return;
+        }
+
+        if(state == BT_SOCKET_CONNECTED) {  // connected when Server
+            if(result == BT_ERROR_NONE) {
+                // Update BluetoothServiceHandler
+                BluetoothServiceHandlerPtr service = iter->second;
+                service->setConnectionState(true);
+
+                // Call BluetoothServiceHandler.onconnect
+                BluetoothSocketPtr socket =
+                    new BluetoothSocket(connection, getInstance());
+                MultiCallbackUserDataPtr callback = service->getOnConnect();
+                JSContextRef context = callback->getContext();
+                JSObjectRef socketObj =
+                    JSBluetoothSocket::createJSObject(context, socket);
+                if(callback){
+                    LOGD("Enter %d", result);
+
+                    MultiSuccessCallbackHolder* holder =
+                        new MultiSuccessCallbackHolder();
+                    if(NULL == holder){
+                        LOGE("holder creation failed");
+                        return;
+                    }
+                    holder->ptr = callback;
+                    holder->mJSBluetoothSocket = socketObj;
+                    JSValueProtect(holder->ptr->getContext(), holder->mJSBluetoothSocket);
+
+                    guint bGIdleRet = g_idle_add(callMultiSuccessCallback, holder);
+                    if (!bGIdleRet) {
+                        LOGD("g_idle_add fails");
+                    }
+                }
+
+                // Update mConnectedSocket
+                object->mConnectedSocket.insert(
+                        std::pair<int, BluetoothSocketPtr>(
+                            connection->socket_fd, socket));
+                bt_socket_set_data_received_cb(onSocketReceivedCB, userData);
+            }
+            else {
+                LOGW("Establishing a connection failed");
+            }
+            return;
+        }
+        else {  // disconnected when Server
+            if(result == BT_ERROR_NONE) {
+                // Update BluetoothServiceHandler
+                BluetoothServiceHandlerPtr service = iter->second;
+                service->setConnectionState(false);
+
+                // call BluetoothSocket.onclose;
+                auto i = object->mConnectedSocket.find(connection->socket_fd);
+                if(i == object->mConnectedSocket.end()) {
+                    LOGW("Unknown connected socket");
+                    return;
+                }
+                //BluetoothSocketSharedPtr socket = i->second;
+                BluetoothSocketPtr socket = i->second;
+                socket->setConnectionState(false);
+                MultiCallbackUserDataPtr callback = socket->getOnClose();
+                if(callback){
+                    MultiSuccessCallbackHolder* holder =
+                        new MultiSuccessCallbackHolder();
+                    if(NULL == holder){
+                        LOGE("holder creation failed");
+                        return;
+                    }
+                    holder->ptr = callback;
+                    holder->mJSBluetoothSocket = NULL;
+
+                    guint bGIdleRet = g_idle_add(callCloseCallback, holder);
+                    if (!bGIdleRet) {
+                        LOGD("g_idle_add fails");
+                        return;
+                    }
+                }
+                object->mConnectedSocket.erase(i);
+            }
+            else {
+                LOGW("Disconnecting a connection failed");
+            }
+        }
+    }
+    else if(connection->local_role == BT_SOCKET_CLIENT) {
+        if(state == BT_SOCKET_CONNECTED) {  // connected when Client
+            std::string remoteAddress(connection->remote_address);
+            ConnReqMultiMapT::iterator iter;
+            do {
+                iter = object->mConnReqMap.find(remoteAddress);
+                if(iter != object->mConnReqMap.end()
+                        && !strcmp(iter->second->mUUID.c_str(),
+                            connection->service_uuid)) {
+                    break;
+                }
+            } while(iter != object->mConnReqMap.end());
+
+            if(iter == object->mConnReqMap.end()) {
+                LOGW("Connection state is changed unexpectedly");
+                return;
+            }
+
+            MultiCallbackUserDataPtr callback =
+                static_cast<MultiCallbackUserDataPtr>(iter->second->mUserData);
+
+            if(result == BT_ERROR_NONE) {
+                // Update mConnectedSocket
+                BluetoothSocketPtr socket =
+                    new BluetoothSocket(connection, getInstance());
+
+                object->mConnectedSocket.insert(
+                        std::pair<int, BluetoothSocketPtr>(
+                            connection->socket_fd, socket));
+                bt_socket_set_data_received_cb(onSocketReceivedCB, userData);
+
+                // Call successcallback of connectToServiceByUUID
+                JSContextRef context = callback->getContext();
+                JSObjectRef socketObj =
+                    JSBluetoothSocket::createJSObject(context, socket);
+                if(callback)
+                    callback->invokeCallback("success", socketObj);
+
+                // Update mConnReqMap
+                object->mConnReqMap.erase(iter);
+            } else {
+                // Call errorcallback of connectToServiceByUUID
+                JSContextRef context = callback->getContext();
+                NotFoundException error("Not found");
+                if(callback)
+                    callback->invokeCallback("error",
+                        JSWebAPIErrorFactory::makeErrorObject(context, error));
+
+                // Update mConnReqMap
+                object->mConnReqMap.erase(iter);
+            }
+            return;
+        }
+        else {  // disconnected when Client
+            if(result == BT_ERROR_NONE) {
+                // call BluetoothSocket.onclose;
+                auto i = object->mConnectedSocket.find(connection->socket_fd);
+                if(i == object->mConnectedSocket.end()) {
+                    LOGW("Unknown connected socket");
+                    return;
+                }
+
+                BluetoothSocketPtr socket = i->second;
+                socket->setConnectionState(false);
+                MultiCallbackUserDataPtr callback = socket->getOnClose();
+                if(callback){
+                    MultiSuccessCallbackHolder* holder =
+                        new MultiSuccessCallbackHolder();
+                    if(NULL == holder){
+                        LOGE("holder creation failed");
+                        return;
+                    }
+                    holder->ptr = callback;
+                    holder->mJSBluetoothSocket = NULL;
+
+                    guint bGIdleRet = g_idle_add(callCloseCallback, holder);
+                    if (!bGIdleRet) {
+                        LOGD("g_idle_add fails");
+                        return;
+                    }
+                }
+                object->mConnectedSocket.erase(i);
+            } else {
+                LOGW("Disconnecting a connection failed");
+            }
+        }
+    } else {
+        LOGW("Unknown role");
+        return;
+    }
+
+    if(object->mConnectedSocket.size() == 0) {
+        bt_socket_unset_data_received_cb();
+    }
+
+    if(object->mRegisteredUUID.size() == 0 && object->mConnReqMap.size() == 0
+            && object->mConnectedSocket.size() == 0) {
+        bt_socket_unset_connection_state_changed_cb();
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothAdapter::onSocketReceivedCB(bt_socket_received_data_s *data,
+        void *userData)
+{
+    BluetoothAdapterPtr object = static_cast<BluetoothAdapterPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    if(!data) {
+        LOGW("data is NULL");
+        return;
+    }
+    LOGD("Enter %d", data->socket_fd);
+
+    ConnectedSocketMapT::iterator i =
+        object->mConnectedSocket.find(data->socket_fd);
+    if(i == object->mConnectedSocket.end()) {
+        LOGW("Unknown connected socket");
+        return;
+    }
+
+    // Store received data
+    BluetoothSocketPtr socket = i->second;
+    socket->storeRecivedData(data->data, static_cast<unsigned long>(data->data_size));
+
+    // Call BluetoothSocket.onmessage
+    MultiCallbackUserDataPtr callback = socket->getOnMessage();
+    if(callback)
+        callback->invokeCallback("onmessage");
+}
+
+BluetoothAdapter::BluetoothAdapter():
+    mEnabled(false), mVisible(false)
+{
+    Common::SecurityAccessor();
+
+    int ret = BT_ERROR_NONE;
+
+    ret = bt_initialize();
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret, "bt_initialize failed");
+    }
+
+    bt_adapter_state_e state;
+    ret = bt_adapter_get_state(&state);
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_adapter_get_state failed");
+    }
+
+    if (state == BT_ADAPTER_ENABLED) {
+        mEnabled = true;
+    }
+
+    bt_adapter_visibility_mode_e mode;
+    ret = bt_adapter_get_visibility(&mode, NULL);
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_adapter_get_visibility failed");
+    }
+
+    if (mode != BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE) {
+        mVisible = true;
+    }
+
+    ret = bt_adapter_set_state_changed_cb(onStateChangedCB, this);
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_adapter_set_state_changed_cb failed");
+    }
+
+    ret = bt_adapter_set_device_discovery_state_changed_cb(
+        onDiscoveryStateChangedCB, this);
+
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_adapter_set_device_discovery_state_changed_cb failed");
+    }
+
+    ret = bt_adapter_set_name_changed_cb(onNameChangedCB, this);
+    if(ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_adapter_set_name_changed_cb failed");
+    }
+
+    ret = bt_adapter_set_visibility_mode_changed_cb(onVisibilityChangedCB,
+        this);
+    if(ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_adapter_set_visibility_mode_changed_cb failed");
+    }
+}
+
+BluetoothAdapter::~BluetoothAdapter()
+{
+    // unset platform callback
+    bt_adapter_unset_state_changed_cb();
+    bt_adapter_unset_name_changed_cb();
+    bt_adapter_unset_visibility_mode_changed_cb();
+    bt_adapter_unset_device_discovery_state_changed_cb();
+    bt_device_unset_bond_created_cb();
+    bt_device_unset_bond_destroyed_cb();
+    bt_socket_unset_connection_state_changed_cb();
+    bt_socket_unset_data_received_cb();
+    bt_deinitialize();
+
+    for(int i = 0; i <= DESTROY_BONDING; i++) {
+        mUserDataList[i].reset();
+    }
+    mRegisteredUUID.clear();
+    mConnReqMap.clear();
+    mFoundDevices.clear();
+    mConnectedSocket.clear();
+}
+
+void BluetoothAdapter::unloadFrame(JSContextRef context)
+{
+    LOGD("Clean mUserDataList");
+    for(int i = 0; i <= DESTROY_BONDING; i++) {
+        if(mUserDataList[i]) {
+            MultiCallbackUserDataPtr callback = mUserDataList[i];
+            if(!GlobalContextManager::getInstance()->
+                    isAliveGlobalContext(callback->getContext())) {
+                mUserDataList[i].reset();
+            }
+        }
+    }
+
+    LOGD("Clean mConnReqMap");
+    for(auto iter = mConnReqMap.begin(); iter != mConnReqMap.end(); ) {
+        ConnReqMultiMapT::iterator temp = iter++;
+        MultiCallbackUserDataPtr callback = temp->second->mUserData;
+        if(!callback && !GlobalContextManager::getInstance()->
+                isAliveGlobalContext(callback->getContext())) {
+            mConnReqMap.erase(temp);
+        }
+    }
+}
+
+void BluetoothAdapter::unregisterUUID(std::string &uuid)
+{
+    int ret;
+    mRegisteredUUID.erase(mRegisteredUUID.find(uuid));
+    if(mRegisteredUUID.size() == 0 && mConnReqMap.size() == 0
+            && mConnectedSocket.size() == 0) {
+        ret = bt_socket_unset_connection_state_changed_cb();
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_socket_unset_connection_state_changed_cb failed");
+        }
+    }
+}
+
+bool BluetoothAdapter::closeConnectedSocket(int socket)
+{
+    if (!mEnabled) {
+        LOGE("Bluetooth is not powered");
+        return false;
+    }
+
+    auto iter = mConnectedSocket.find(socket);
+    if(iter == mConnectedSocket.end()) {
+        LOGW("Already disconnected");
+        return true;
+    }
+
+    mConnectedSocket.erase(iter);
+    if(mConnectedSocket.size() == 0) {
+        bt_socket_unset_data_received_cb();
+    }
+
+    int ret;
+    if(mRegisteredUUID.size() == 0 && mConnReqMap.size() == 0
+            && mConnectedSocket.size() == 0) {
+        ret = bt_socket_unset_connection_state_changed_cb();
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_socket_unset_connection_state_changed_cb failed");
+        }
+    }
+
+    return true;
+}
+
+void BluetoothAdapter::removeConnReq(std::string &remoteAddress)
+{
+    mConnReqMap.erase(remoteAddress);
+
+    if(mRegisteredUUID.size() == 0 && mConnReqMap.size() == 0
+            && mConnectedSocket.size() == 0) {
+        int ret = bt_socket_unset_connection_state_changed_cb();
+
+        if(ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_socket_unset_connection_state_changed_cb failed");
+        }
+    }
+}
+
+BluetoothAdapter* BluetoothAdapter::getInstance()
+{
+    static BluetoothAdapter instance;
+    return &instance;
+}
+
+bool BluetoothAdapter::isValidAddress(std::string &address)
+{
+    pcrecpp::RE re("(([0-9a-zA-Z]+):)+([0-9a-zA-Z]+)");
+    std::string compareAddress = "00:12:47:08:9A:A6";
+
+    if (!re.FullMatch(address)) {
+        LOGE("Invalid address");
+        return false;
+    }
+
+    if (address.size() != compareAddress.size())
+    {
+        LOGE("Invalid size");
+        return false;
+    }
+
+    return true;
+}
+
+bool BluetoothAdapter::isValidUUID(std::string &uuid)
+{
+    pcrecpp::RE re("(([0-9a-zA-Z]+)-)+([0-9a-zA-Z]+)");
+    std::string compareUUID = "00001101-0000-1000-8000-00805F9B34FB";
+
+    if (!re.FullMatch(uuid))
+    {
+        LOGE("Invalid UUID");
+        return false;
+    }
+
+    if (uuid.size() != compareUUID.size())
+    {
+        LOGE("Invalid size");
+        return false;
+    }
+
+    return true;
+}
+
+std::string BluetoothAdapter::getName() const
+{
+    char* name = NULL;
+    std::string str = "";
+    int ret;
+
+    TIME_TRACER_ITEM_BEGIN("getName::bt_adapter_get_name", 1);
+    ret = bt_adapter_get_name(&name);
+    TIME_TRACER_ITEM_END("getName::bt_adapter_get_name", 1);
+
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d, %s", ret, BluetoothUtil::getBluetoothErrorMessage(ret).c_str());
+    }
+
+    if (name) {
+        str = name;
+        free(name);
+    }
+    return str;
+}
+
+void BluetoothAdapter::setName(std::string &name,
+    MultiCallbackUserDataPtr userData)
+{
+    if (!mEnabled) {
+        LOGE("Bluetooth device is turned off");
+        ServiceNotAvailableException e("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    if (mUserDataList[SET_NAME]) {
+        LOGE("Already requested");
+        UnknownException e("Already requested");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    try {
+        std::string adapterName = getName();
+        if(adapterName == name) {   // in case of same name
+            LOGD("same name");
+            BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+            return;
+        }
+
+        mUserDataList[SET_NAME] = userData;
+
+        TIME_TRACER_ITEM_BEGIN("setName::bt_adapter_set_name", 1);
+        int ret = bt_adapter_set_name(name.c_str());
+        TIME_TRACER_ITEM_END("setName::bt_adapter_set_name", 1);
+
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_set_name failed");
+        }
+
+        mRequestedName = name;
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+
+        mUserDataList[SET_NAME].reset();
+    }
+}
+
+std::string BluetoothAdapter::getAddress() const
+{
+    char* address = NULL;
+    std::string str = "";
+
+    int ret = bt_adapter_get_address(&address);
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d, %s", ret, BluetoothUtil::getBluetoothErrorMessage(ret).c_str());
+    }
+
+    if (address != NULL) {
+        str = address;
+        free(address);
+    } else {
+        LOGW("address is NULL");
+    }
+
+    return str;
+}
+
+bool BluetoothAdapter::getPowered() const
+{
+    return mEnabled;
+}
+
+void BluetoothAdapter::setPowered(bool powered, MultiCallbackUserDataPtr userData)
+{
+    if(powered == mEnabled) {
+        LOGD("same state");
+        BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+        return;
+    }
+
+    if (mUserDataList[SET_POWERED]) {
+       LOGE("Already requested");
+       ServiceNotAvailableException e("Already requested");
+       BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+       return;
+    }
+
+    try {
+        mUserDataList[SET_POWERED] = userData;
+        mRequestedState = powered;
+        int ret = 0;
+#ifdef APP_CONTROL_SETTING_SUPPORT
+        app_control_h service;
+        ret = app_control_create(&service);
+
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_create failed");
+            throw UnknownException("app_control_create failed");
+        }
+
+        ret = app_control_set_operation(service,
+                "http://tizen.org/appcontrol/operation/edit");
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_set_operation failed");
+            throw UnknownException("app_control_set_operation failed");
+        }
+
+        ret = app_control_set_mime(service,
+                "application/x-bluetooth-on-off");
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_set_mime failed");
+            throw UnknownException("app_control_set_mime failed");
+        }
+
+        ret = app_control_send_launch_request(service, [](
+                    app_control_h request, app_control_h reply,
+                    app_control_result_e r, void *user_data) {
+            BluetoothAdapter *self = static_cast<BluetoothAdapter *>(user_data);
+            if (!self) {
+                LOGE("this is null");
+                return;
+            }
+
+            MultiCallbackUserDataPtr callback =
+                self->mUserDataList[SET_POWERED];
+
+            char *result = NULL;
+            app_control_get_extra_data(reply, "result", &result);
+            LOGD("bt_onoff : %s", result);
+
+            if (strcmp(result, "success") == 0) {
+                self->mEnabled = (self->mRequestedState == BT_ADAPTER_ENABLED) ?
+                    true : false;
+                callback->invokeCallback("success");
+            } else {
+                JSContextRef context = callback->getContext();
+                UnknownException error("Bluetooth setPowered failed");
+                callback->invokeCallback("error",
+                    JSWebAPIErrorFactory::makeErrorObject(context, error));
+            }
+            self->mUserDataList[SET_POWERED].reset();
+        }, this);
+
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_send_launch_request failed");
+            throw UnknownException("app_control_send_launch_request failed");
+        }
+
+        ret = app_control_destroy(service);
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_destroy failed");
+            throw UnknownException("app_control_destroy failed");
+        }
+#else
+        ret = powered ? bt_adapter_enable() : bt_adapter_disable();
+        if (ret != BT_ERROR_NONE) {
+
+            if (ret != BT_ERROR_ALREADY_DONE) {
+                LOGE("%d", ret);
+                BluetoothUtil::throwBluetoothException(ret,
+                    "bt_adapter_enable or disable failed");
+            } else {
+                LOGD("already done");
+                BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+                mUserDataList[SET_POWERED].reset();
+            }
+        }
+#endif
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+
+        mUserDataList[SET_POWERED].reset();
+    }
+}
+
+bool BluetoothAdapter::getVisible() const
+{
+    bt_adapter_visibility_mode_e mode;
+
+    int ret = bt_adapter_get_visibility(&mode, NULL);
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d, %s", ret, BluetoothUtil::getBluetoothErrorMessage(ret).c_str());
+    }
+
+    if (mode != BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE) {
+        return true;
+    }
+
+    return false;
+}
+
+void BluetoothAdapter::setVisible(bool visible,
+        unsigned int timeout, MultiCallbackUserDataPtr userData)
+{
+    if (!mEnabled) {
+        LOGE("Bluetooth device is turned off");
+        ServiceNotAvailableException e("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    if (mUserDataList[SET_VISIBLE]) {
+        LOGE("Already requested");
+        UnknownException e("Already requested");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    try {
+        bt_adapter_visibility_mode_e discoverable_mode =
+            BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+        if (visible) {
+            if(timeout == 0)
+                discoverable_mode = BT_ADAPTER_VISIBILITY_MODE_GENERAL_DISCOVERABLE;
+            else
+                discoverable_mode = BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE;
+        }
+
+        bt_adapter_visibility_mode_e current = BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE;
+        int time = 0;
+
+        TIME_TRACER_ITEM_BEGIN("setVisible::bt_adapter_get_visibility", 1);
+        if(bt_adapter_get_visibility(&current , &time) != BT_ERROR_NONE) {
+            LOGE("bt_adapter_get_visibility() failed");
+            throw UnknownException("Can't get current visibility");
+        }
+        TIME_TRACER_ITEM_END("setVisible::bt_adapter_get_visibility", 1);
+
+        if(discoverable_mode == current) {
+            if(discoverable_mode != BT_ADAPTER_VISIBILITY_MODE_LIMITED_DISCOVERABLE) {
+                LOGD("same visibility");
+                BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+                return;
+            }
+            else if((unsigned int)time == timeout) {
+                LOGD("same visibility");
+                BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+                return;
+            }
+        }
+
+        mUserDataList[SET_VISIBLE] = userData;
+        mRequestedVisibility = discoverable_mode;
+
+        int ret = 0;
+#ifdef APP_CONTROL_SETTING_SUPPORT
+        app_control_h service;
+        ret = app_control_create(&service);
+
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_create failed");
+            throw UnknownException("app_control_create failed");
+        }
+
+        ret = app_control_set_operation(service,
+                "http://tizen.org/appcontrol/operation/edit");
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_set_operation failed");
+            throw UnknownException("app_control_set_operation failed");
+
+        }
+
+        ret = app_control_set_mime(service,
+                "application/x-bluetooth-visibility");
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_set_mime failed");
+            throw UnknownException("app_control_set_mime failed");
+        }
+
+        ret = app_control_send_launch_request(service, [](
+                    app_control_h request, app_control_h reply,
+                    app_control_result_e r, void *user_data) {
+            BluetoothAdapter *self = static_cast<BluetoothAdapter *>(user_data);
+            if (!self) {
+                LOGE("this is null");
+                return;
+            }
+            MultiCallbackUserDataPtr callback =
+                self->mUserDataList[SET_VISIBLE];
+
+            char *result = NULL;
+            app_control_get_extra_data(reply, "result", &result);
+            LOGD("bt_visibility : %s", result);
+
+            if (strcmp(result, "success") == 0) {
+                self->mVisible = (self->mRequestedVisibility !=
+                    BT_ADAPTER_VISIBILITY_MODE_NON_DISCOVERABLE) ? true : false;
+                callback->invokeCallback("success");
+            } else {
+                JSContextRef context = callback->getContext();
+                UnknownException error("Bluetooth setVisible failed");
+                callback->invokeCallback("error",
+                    JSWebAPIErrorFactory::makeErrorObject(context, error));
+            }
+            self->mUserDataList[SET_VISIBLE].reset();
+        }, this);
+
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_send_launch_request failed");
+            throw UnknownException("app_control_send_launch_request failed");
+        }
+
+        ret = app_control_destroy(service);
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_destroy failed");
+            throw UnknownException("app_control_destroy failed");
+        }
+#else
+        ret = bt_adapter_set_visibility(discoverable_mode, timeout);
+        if (ret != BT_ERROR_NONE) {
+            if (ret != BT_ERROR_ALREADY_DONE) {
+                LOGE("%d", ret);
+                BluetoothUtil::throwBluetoothException(ret,
+                    "bt_adapter_set_visibility failed");
+            } else {
+                LOGD("already done");
+                BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+                mUserDataList[SET_VISIBLE].reset();
+            }
+        }
+#endif
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+
+        mUserDataList[SET_VISIBLE].reset();
+    }
+}
+
+void BluetoothAdapter::discoverDevices(MultiCallbackUserDataPtr userData)
+{
+    if (mUserDataList[DISCOVER_DEVICES]) {
+        LOGE("Already requested");
+        UnknownException e("Already requested");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    if (!mEnabled) {
+        LOGE("Bluetooth device is turned off");
+        ServiceNotAvailableException e("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    try {
+        mUserDataList[DISCOVER_DEVICES] = userData;
+
+        TIME_TRACER_ITEM_BEGIN(
+            "discoverDevices::bt_adapter_start_device_discovery", 1);
+        int ret = bt_adapter_start_device_discovery();
+        TIME_TRACER_ITEM_END(
+            "discoverDevices::bt_adapter_start_device_discovery", 1);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_start_device_discovery failed");
+        }
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+
+        mUserDataList[DISCOVER_DEVICES].reset();
+    }
+}
+
+void BluetoothAdapter::stopDiscovery(MultiCallbackUserDataPtr userData)
+{
+    if (!mEnabled) {
+        LOGE("Bluetooth device is turned off");
+        ServiceNotAvailableException e("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    try {
+        bool isDiscovering = false;
+        int ret = bt_adapter_is_discovering(&isDiscovering);
+
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_is_discovering failed");
+        }
+
+        if (!isDiscovering) {
+            BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+            return;
+        }
+
+        if (mUserDataList[STOP_DISCOVERY]) {
+            LOGD("Already requested");
+            UnknownException e("Already requested");
+            BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+            return;
+        }
+
+        mUserDataList[STOP_DISCOVERY] = userData;
+
+        TIME_TRACER_ITEM_BEGIN(
+            "stopDiscovery::bt_adapter_stop_device_discovery", 1);
+        ret = bt_adapter_stop_device_discovery();
+        TIME_TRACER_ITEM_END(
+            "stopDiscovery::bt_adapter_stop_device_discovery", 1);
+
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_stop_device_discovery failed");
+        }
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+
+        mUserDataList[STOP_DISCOVERY].reset();
+    }
+}
+
+void BluetoothAdapter::getKnownDevices(MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUtil::syncToAsyncDeviceArrayCallback(userData);
+}
+
+void BluetoothAdapter::getDevice(std::string &address,
+        MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUtil::syncToAsyncDeviceCallback(userData, address);
+}
+
+void BluetoothAdapter::createBonding(std::string &address,
+        MultiCallbackUserDataPtr userData)
+{
+    LOGD("Enter %s", address.c_str());
+
+    if(!isValidAddress(address)) {
+        LOGE("Wrong address");
+        NotFoundException e("Wrong address");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    if (mUserDataList[CREATE_BONDING]) {
+        LOGE("Already requested");
+        UnknownException e("Already requested");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    if (!mEnabled) {
+        LOGE("Bluetooth device is turned off");
+        ServiceNotAvailableException e("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    try {
+        mCreateBondingAddress = address;
+        mUserDataList[CREATE_BONDING] = userData;
+
+        TIME_TRACER_ITEM_BEGIN(
+            "createBonding::bt_device_set_bond_created_cb", 1);
+        int ret = bt_device_set_bond_created_cb(onBondCreatedCB, this);
+        TIME_TRACER_ITEM_END("createBonding::bt_device_set_bond_created_cb", 1);
+
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_device_set_bond_created_cb failed");
+        }
+
+        TIME_TRACER_ITEM_BEGIN("createBonding::bt_device_create_bond", 1);
+        ret = bt_device_create_bond(address.c_str());
+        TIME_TRACER_ITEM_END("createBonding::bt_device_create_bond", 1);
+
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_device_create_bond failed");
+        }
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+
+        mUserDataList[CREATE_BONDING].reset();
+        int ret = bt_device_unset_bond_created_cb();
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+        }
+        mCreateBondingAddress.clear();
+    }
+}
+
+void BluetoothAdapter::destroyBonding(std::string &address,
+        MultiCallbackUserDataPtr userData)
+{
+    LOGD("Enter");
+
+    if (!isValidAddress(address)) {
+        LOGE("Wrong address");
+        NotFoundException e("Wrong address");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    if (!mEnabled) {
+        LOGE("Bluetooth device is turned off");
+        ServiceNotAvailableException e("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    if (mUserDataList[DESTROY_BONDING]) {
+        LOGE("Already requested");
+        UnknownException e("Already requested");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    try {
+        int ret = 0;
+
+        TIME_TRACER_ITEM_BEGIN(
+            "destroyBonding::bt_device_set_bond_destroyed_cb", 1);
+        ret = bt_device_set_bond_destroyed_cb(onBondDestroyedCB, this);
+        TIME_TRACER_ITEM_END(
+            "destroyBonding::bt_device_set_bond_destroyed_cb", 1);
+
+        if(ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_device_set_bond_destroyed_cb failed");
+        }
+        mDestroyBondingAddress = address;
+        mUserDataList[DESTROY_BONDING] = userData;
+
+        bt_device_info_s *deviceInfo = NULL;
+
+        TIME_TRACER_ITEM_BEGIN(
+            "destroyBonding::bt_adapter_get_bonded_device_info", 1);
+        ret = bt_adapter_get_bonded_device_info(address.c_str(), &deviceInfo);
+        TIME_TRACER_ITEM_END(
+            "destroyBonding::bt_adapter_get_bonded_device_info", 1);
+
+        if (ret != BT_ERROR_NONE || deviceInfo == NULL) {
+            LOGD("There is no bonding");
+            throw NotFoundException("Not found");
+        }
+
+        ret = bt_adapter_free_device_info(deviceInfo);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_free_device_info failed");
+        }
+
+        TIME_TRACER_ITEM_BEGIN("destroyBonding::bt_device_destroy_bond", 1);
+        ret = bt_device_destroy_bond(address.c_str());
+        TIME_TRACER_ITEM_END("destroyBonding::bt_device_destroy_bond", 1);
+
+        if (ret == BT_ERROR_INVALID_PARAMETER) {
+            LOGE("Not found");
+            throw NotFoundException("Not found");
+        } else if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_device_destroy_bond failed");
+        }
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+
+        int ret = bt_device_unset_bond_destroyed_cb();
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+        }
+        mDestroyBondingAddress.clear();
+        mUserDataList[DESTROY_BONDING].reset();
+    }
+}
+
+void BluetoothAdapter::registerRFCOMMServiceByUUID(std::string &uuid,
+        std::string &name, MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUtil::syncToAsyncServiceCallback(userData, uuid, name);
+}
+
+void BluetoothAdapter::connectToServiceByUUID(std::string &remoteAddress,
+        std::string &uuid, Common::MultiCallbackUserDataPtr userData)
+{
+    try {
+        if(!isValidUUID(uuid)) {
+            LOGE("Wrong UUID");
+            throw InvalidValuesException("Wrong UUID");
+        }
+
+        if (!mEnabled) {
+            LOGE("Bluetooth device is turned off");
+            throw ServiceNotAvailableException("Bluetooth device is turned off");
+        }
+
+        int ret = 0;
+        TIME_TRACER_ITEM_BEGIN(
+                "connectToServiceByUUID::bt_socket_connect_rfcomm", 1);
+        ret = bt_socket_connect_rfcomm(remoteAddress.c_str(), uuid.c_str());
+        TIME_TRACER_ITEM_END(
+                "connectToServiceByUUID::bt_socket_connect_rfcomm", 1);
+
+        if (ret == BT_ERROR_REMOTE_DEVICE_NOT_BONDED) {
+            LOGE("Invalid value");
+            throw InvalidValuesException("Invalid value");
+        } else if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_socket_connect_rfcomm failed");
+        }
+
+        LOGD("bt_socket_connect_rfcomm() succeeded");
+        TIME_TRACER_ITEM_BEGIN(
+            "connectToServiceByUUID::bt_socket_set_connection_state_changed_cb",
+            1);
+        ret = bt_socket_set_connection_state_changed_cb(
+            onSocketConnected, this);
+        TIME_TRACER_ITEM_END(
+            "connectToServiceByUUID::bt_socket_set_connection_state_changed_cb",
+            1);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_socket_set_connection_state_changed_cb failed");
+        }
+
+        BluetoothConnReqPtr connReq = new BluetoothConnReq(uuid, userData);
+        mConnReqMap.insert(std::pair<std::string, BluetoothConnReqPtr>(
+            remoteAddress, connReq));
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+    }
+}
+
+void BluetoothAdapter::returnKnownDevices(
+    Common::MultiCallbackUserDataPtr userData)
+{
+    LOGD("Enter");
+
+    try {
+        if (!mEnabled) {
+            LOGE("Bluetooth device is turned off");
+            throw ServiceNotAvailableException("Bluetooth device is turned off");
+        }
+
+        knownDevices = mFoundDevices;
+        int ret = 0;
+
+        ret = bt_adapter_foreach_bonded_device(foreachBondedDevicesCB, this);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_foreach_bonded_device failed");
+        }
+
+        // There are found devices
+        if(knownDevices.size() > 0) {
+            int num = knownDevices.size();
+            LOGD("There are found devices %d", num);
+            JSObjectRef devices[num];
+            for(int i = 0; i < num; i++) {
+                JSObjectRef deviceObj =
+                    JSBluetoothDevice::createJSObject(
+                        userData->getContext(), knownDevices[i]);
+                devices[i] = deviceObj;
+            }
+
+            userData->invokeCallback("success",
+                JSObjectMakeArray(userData->getContext(),
+                    num, devices, NULL));
+        } else {
+            // There is no found device
+            userData->invokeCallback("success",
+                JSObjectMakeArray(userData->getContext(), 0, NULL, NULL) );
+        }
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        userData->invokeCallback("error",
+            JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), e));
+    }
+}
+
+void BluetoothAdapter::returnDevice(std::string &address,
+        Common::MultiCallbackUserDataPtr userData)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        if(!isValidAddress(address)) {
+            LOGE("Wrong address");
+            throw NotFoundException("Wrong address");
+        }
+
+        if (!mEnabled) {
+            LOGE("Bluetooth device is turned off");
+            throw ServiceNotAvailableException("Bluetooth device is turned off");
+        }
+
+        bt_device_info_s *deviceInfo = NULL;
+        int ret = 0;
+        TIME_TRACER_ITEM_BEGIN(
+            "returnDevice::bt_adapter_get_bonded_device_info", 1);
+        ret = bt_adapter_get_bonded_device_info(address.c_str(), &deviceInfo);
+        TIME_TRACER_ITEM_END(
+            "returnDevice::bt_adapter_get_bonded_device_info", 1);
+
+        if(ret == BT_ERROR_NONE && deviceInfo != NULL) {
+            BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
+            device->copyAceCheckAccessFunction(getInstance());
+            bt_adapter_free_device_info(deviceInfo);
+
+            LOGD("invoke successCallback");
+            userData->invokeCallback("success",
+                JSBluetoothDevice::createJSObject(userData->getContext(),
+                    device));
+            return;
+        }
+
+        std::vector<BluetoothDeviceSharedPtr>::iterator iter;
+        for(iter = mFoundDevices.begin(); iter != mFoundDevices.end(); ++iter) {
+            BluetoothDeviceSharedPtr foundDevice = *iter;
+            if(!strcmp(foundDevice->getAddress().c_str(), address.c_str())) {
+                LOGD("Found in mFoundDevices");
+                userData->invokeCallback("success",
+                    JSBluetoothDevice::createJSObject(userData->getContext(),
+                        foundDevice));
+                break;
+            }
+        }
+
+        if(iter == mFoundDevices.end()) {
+            LOGE("Can't find this device");
+            throw NotFoundException(
+                "There is no device with the given address");
+        }
+
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        userData->invokeCallback("error",
+            JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), e));
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothAdapter::returnRegisteredService(std::string &uuid,
+        std::string &name, Common::MultiCallbackUserDataPtr userData)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        if (!isValidUUID(uuid)) {
+            LOGE("Wrong UUID");
+            throw InvalidValuesException("Wrong UUID");
+        }
+
+        if (!mEnabled) {
+            LOGE("Bluetooth device is turned off");
+            throw ServiceNotAvailableException("Bluetooth device is turned off");
+        }
+
+        int ret = 0;
+        bool isRegistered;
+        TIME_TRACER_ITEM_BEGIN(
+            "returnRegisteredService::bt_adapter_is_service_used", 1);
+        ret = bt_adapter_is_service_used(uuid.c_str(), &isRegistered);
+        TIME_TRACER_ITEM_END(
+            "returnRegisteredService::bt_adapter_is_service_used", 1);
+
+        if (ret == BT_ERROR_NONE && isRegistered) {
+            LOGD("Already registered");
+            throw InvalidValuesException("Already registered");
+        }
+
+        int socket = -1;
+        TIME_TRACER_ITEM_BEGIN(
+            "returnRegisteredService::bt_socket_create_rfcomm", 1);
+        ret = bt_socket_create_rfcomm(uuid.c_str(), &socket);
+        LOGD("Enter name = %s, ret = %d", uuid.c_str(), ret);
+        TIME_TRACER_ITEM_END(
+            "returnRegisteredService::bt_socket_create_rfcomm", 1);
+
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_socket_create_rfcomm failed");
+        }
+
+        LOGD("bt_socket_create_rfcomm() succeeded");
+        TIME_TRACER_ITEM_BEGIN(
+           "returnRegisteredService::bt_socket_listen_and_accept_rfcomm", 1);
+        ret = bt_socket_listen_and_accept_rfcomm(socket, 0);
+        TIME_TRACER_ITEM_END(
+            "returnRegisteredService::bt_socket_listen_and_accept_rfcomm", 1);
+
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_socket_listen_and_accept_rfcomm failed");
+        }
+
+        LOGD("bt_socket_listen() succeeded");
+        bt_socket_set_connection_state_changed_cb(onSocketConnected, this);
+
+        BluetoothServiceHandlerPtr serviceHandler =
+            new BluetoothServiceHandler(uuid, name, socket);
+        serviceHandler->copyAceCheckAccessFunction(getInstance());
+        mRegisteredUUID.insert(
+           std::pair<std::string, BluetoothServiceHandlerPtr>(
+               uuid, serviceHandler));
+
+        JSObjectRef serviceObj =
+            JSBluetoothServiceHandler::createJSObject(
+                userData->getContext(), serviceHandler);
+        userData->invokeCallback("success", serviceObj);
+
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        userData->invokeCallback("error",
+            JSWebAPIErrorFactory::makeErrorObject(userData->getContext(), e));
+    }
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+}
+
+void BluetoothAdapter::setChangeListener(MultiCallbackUserDataPtr userData)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    LOGD("Enter");
+    mChangeListener = userData;
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+}
+
+void BluetoothAdapter::unsetChangeListener()
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    LOGD("Enter");
+    mChangeListener.reset();
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothAdapter.h b/src/Bluetooth/BluetoothAdapter.h
new file mode 100755 (executable)
index 0000000..40faf3b
--- /dev/null
@@ -0,0 +1,164 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_ADAPTER_H__
+#define __TIZEN_BLUETOOTH_ADAPTER_H__
+
+#include <string>
+#include <vector>
+#include <map>
+#include <glib.h>
+
+#include <app_control.h>
+#include <bluetooth.h>
+#include <Security.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include "BluetoothDevice.h"
+#include "BluetoothServiceHandler.h"
+#include "BluetoothSocket.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothConnReq
+{
+public:
+    BluetoothConnReq(std::string uuid,
+        Common::MultiCallbackUserDataPtr userData)
+    {
+        mUUID = uuid;
+        mUserData = userData;
+    };
+
+    std::string mUUID;
+    Common::MultiCallbackUserDataPtr mUserData;
+};
+typedef BluetoothConnReq* BluetoothConnReqPtr;
+
+class BluetoothAdapter : public Common::SecurityAccessor
+{
+public:
+    enum adapterAsyncE
+    {
+        SET_POWERED = 0,
+        SET_NAME,
+        SET_VISIBLE,
+        DISCOVER_DEVICES,
+        STOP_DISCOVERY,
+        CREATE_BONDING,
+        DESTROY_BONDING,
+    };
+
+    bool getPowered() const;
+    void setPowered(bool powered, Common::MultiCallbackUserDataPtr userData);
+    std::string getName() const;
+    void setName(std::string &name, Common::MultiCallbackUserDataPtr userData);
+    std::string getAddress() const;
+    bool getVisible() const;
+    void setVisible(bool visible, unsigned int timeout,
+        Common::MultiCallbackUserDataPtr userData);
+    void discoverDevices(Common::MultiCallbackUserDataPtr userData);
+    void stopDiscovery(Common::MultiCallbackUserDataPtr userData);
+    void getKnownDevices(Common::MultiCallbackUserDataPtr userData);
+    void getDevice(std::string &address,
+        Common::MultiCallbackUserDataPtr userData);
+    void createBonding(std::string &address,
+        Common::MultiCallbackUserDataPtr userData);
+    void destroyBonding(std::string &address,
+        Common::MultiCallbackUserDataPtr userData);
+    void registerRFCOMMServiceByUUID(std::string &uuid, std::string &name,
+        Common::MultiCallbackUserDataPtr userData);
+    void connectToServiceByUUID(std::string &remoteAddress, std::string &uuid,
+        Common::MultiCallbackUserDataPtr userData);
+
+    void returnKnownDevices(Common::MultiCallbackUserDataPtr userData);
+    void returnDevice(std::string &address,
+        Common::MultiCallbackUserDataPtr userData);
+    void returnRegisteredService(std::string &uuid, std::string &name,
+        Common::MultiCallbackUserDataPtr userData);
+
+    void unregisterUUID(std::string &uuid);
+    bool closeConnectedSocket(int socket);
+    void removeConnReq(std::string &remoteAddress);
+
+    void setChangeListener(Common::MultiCallbackUserDataPtr userData);
+    void unsetChangeListener();
+
+    static BluetoothAdapter* getInstance();
+    static bool isValidAddress(std::string &address);
+    static bool isValidUUID(std::string &uuid);
+    void unloadFrame(JSContextRef context);
+
+    static gboolean callMultiSuccessCallback(void* data);
+    static gboolean callCloseCallback(void* data);
+
+private:
+    BluetoothAdapter();
+    virtual ~BluetoothAdapter();
+
+    static void onStateChangedCB(int result, bt_adapter_state_e adapterState,
+        void *userData);
+    static void onNameChangedCB(char *name, void *userData);
+    static void onVisibilityChangedCB(int result,
+        bt_adapter_visibility_mode_e visibilityMode, void *userData);
+    static void onDiscoveryStateChangedCB(int result,
+        bt_adapter_device_discovery_state_e discoveryState,
+        bt_adapter_device_discovery_info_s *discoveryInfo, void *userData);
+    static bool foreachBondedDevicesCB(bt_device_info_s *deviceInfo,
+        void *userData);
+    static void onBondCreatedCB(int result, bt_device_info_s *deviceInfo,
+        void *userData);
+    static void onBondDestroyedCB(int result, char *remoteAddress,
+        void *userData);
+    static void onSocketConnected(int result,
+        bt_socket_connection_state_e state,
+        bt_socket_connection_s *connection,
+        void *userData);
+    static void onSocketReceivedCB(bt_socket_received_data_s *data,
+        void *userData);
+
+    // <remoteAddress, BluetoothConnReqPtr>
+    typedef std::multimap<std::string, BluetoothConnReqPtr> ConnReqMultiMapT;
+    // <UUID, BluetoothServiceHandlerPtr>
+    typedef std::map<std::string, BluetoothServiceHandlerPtr> RegisteredUUIDMapT;
+    // <socketFD, BluetoothSocketPtr>
+    typedef std::map<int, BluetoothSocketPtr> ConnectedSocketMapT;
+
+    bool mEnabled;
+    bool mVisible;
+    ConnReqMultiMapT mConnReqMap;
+    RegisteredUUIDMapT mRegisteredUUID;
+    ConnectedSocketMapT mConnectedSocket;
+    bool mRequestedState;
+    std::string mRequestedName;
+    bt_adapter_visibility_mode_e mRequestedVisibility;
+    std::string mCreateBondingAddress;
+    std::string mDestroyBondingAddress;
+    Common::MultiCallbackUserDataPtr mUserDataList[DESTROY_BONDING + 1];
+    std::vector<std::string> mDisappearedDevices;
+    std::vector<BluetoothDeviceSharedPtr> mFoundDevices;
+    std::vector<BluetoothDeviceSharedPtr> knownDevices;
+    Common::MultiCallbackUserDataPtr mChangeListener;
+};
+
+typedef BluetoothAdapter* BluetoothAdapterPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_ADAPTER_H__
diff --git a/src/Bluetooth/BluetoothCallback.cpp b/src/Bluetooth/BluetoothCallback.cpp
new file mode 100644 (file)
index 0000000..ee78257
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Ecore.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+
+#include "BluetoothCallback.h"
+
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+
+class BluetoothCallbackData
+{
+public:
+    BluetoothCallbackData(MultiCallbackUserDataPtr callback):
+        mCallback(callback),
+        mIsError(false)
+    {};
+
+    BluetoothCallbackData(MultiCallbackUserDataPtr callback,
+        Common::BasePlatformException error):
+        mCallback(callback),
+        mIsError(true)
+    {
+        mErrorName = error.getName();
+        mErrorMessage = error.getMessage();
+    };
+
+    virtual ~BluetoothCallbackData()
+    {};
+
+    MultiCallbackUserDataPtr mCallback;
+    bool mIsError;
+    std::string mErrorName;
+    std::string mErrorMessage;
+};
+
+typedef BluetoothCallbackData* BluetoothCallbackDataPtr;
+
+
+static Eina_Bool jobCompleteCB(void *userData){
+    BluetoothCallbackDataPtr data =
+        static_cast<BluetoothCallbackDataPtr>(userData);
+
+    if (!data) {
+        LOGW("BluetoothCallbackDataPtr is NULL");
+        return false;
+    }
+
+    if (!(data->mCallback)) {
+        LOGW("MulticallbackUserData is NULL");
+        delete data;
+        return false;
+    }
+
+    if (!data->mIsError) {  // Success Callback
+        LOGD("Success Callback");
+        data->mCallback->invokeCallback("success");
+    } else {  // Error Callback
+        LOGD("Error Callback");
+        data->mCallback->invokeCallback("error",
+            JSWebAPIErrorFactory::makeErrorObject(data->mCallback->getContext(),
+                data->mErrorName, data->mErrorMessage));
+    }
+
+    delete data;
+    return false;
+}
+
+void BluetoothCallback::syncToAsyncSuccessCB(MultiCallbackUserDataPtr callback)
+{
+    BluetoothCallbackDataPtr data = new BluetoothCallbackData(callback);
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+void BluetoothCallback::syncToAsyncErrorCB(MultiCallbackUserDataPtr callback,
+    Common::BasePlatformException error)
+{
+    BluetoothCallbackDataPtr data = new BluetoothCallbackData(callback, error);
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothCallback.h b/src/Bluetooth/BluetoothCallback.h
new file mode 100644 (file)
index 0000000..7e4d0e0
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CALLBACK_H__
+#define __TIZEN_BLUETOOTH_CALLBACK_H__
+
+#include <string>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+
+class BluetoothCallback
+{
+public:
+    static void syncToAsyncSuccessCB(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData);
+    static void syncToAsyncErrorCB(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData,
+        Common::BasePlatformException error);
+};
+
+} // Bluetooth
+} // DeviceAPI
+
+
+#endif // __TIZEN_BLUETOOTH_CALLBACK_H__
+
diff --git a/src/Bluetooth/BluetoothCallbackUtil.cpp b/src/Bluetooth/BluetoothCallbackUtil.cpp
new file mode 100644 (file)
index 0000000..3876c22
--- /dev/null
@@ -0,0 +1,141 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Ecore.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+
+#include "BluetoothCallbackUtil.h"
+#include "BluetoothAdapter.h"
+
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+static Eina_Bool jobCompleteCB(void *userData){
+    BluetoothCallbackUserDataPtr data =
+        static_cast<BluetoothCallbackUserDataPtr>(userData);
+
+    if(!data) {
+        LOGW("BluetoothCallbackUserDataPtr is NULL");
+        return false;
+    }
+
+    if(!(data->mUserData)) {
+        LOGW("MulticallbackUserData is NULL");
+        delete data;
+        return false;
+    }
+
+    switch(data->mCBType) {
+        case BluetoothCallbackUserData::BT_CB_SUCCESS:
+        {
+            LOGD("BT_CB_SUCCESS");
+            data->mUserData->invokeCallback("success");
+            break;
+        }
+        case BluetoothCallbackUserData::BT_CB_ERROR:
+        {
+            LOGD("BT_CB_ERROR");
+            data->mUserData->invokeCallback("error",
+                JSWebAPIErrorFactory::makeErrorObject(
+                    data->mUserData->getContext(),
+                    data->mErrorName,
+                    data->mErrorMessage));
+            break;
+        }
+        case BluetoothCallbackUserData::BT_CB_DEVICE:
+        {
+            LOGD("BT_CB_DEVICE");
+            BluetoothAdapter::getInstance()->returnDevice(
+                data->mAddress, data->mUserData);
+            break;
+        }
+        case BluetoothCallbackUserData::BT_CB_DEVICES:
+        {
+            LOGD("BT_CB_DEVICES");
+            BluetoothAdapter::getInstance()->returnKnownDevices(data->mUserData);
+            break;
+        }
+        case BluetoothCallbackUserData::BT_CB_SERVICE:
+        {
+            LOGD("BT_CB_SERVICE");
+            BluetoothAdapter::getInstance()->returnRegisteredService(
+                data->mUUID, data->mName, data->mUserData);
+            break;
+        }
+        default:
+        {
+            LOGW("Unknown callback type");
+        }
+    }
+
+    delete data;
+    return false;
+}
+
+void BluetoothCallbackUtil::syncToAsyncSuccessCallback(
+    MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUserDataPtr data =
+        new BluetoothCallbackUserData(userData,
+            BluetoothCallbackUserData::BT_CB_SUCCESS);
+
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+void BluetoothCallbackUtil::syncToAsyncErrorCallback(
+    MultiCallbackUserDataPtr userData, Common::BasePlatformException error)
+{
+    BluetoothCallbackUserDataPtr data =
+        new BluetoothCallbackUserData(userData, error);
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+void BluetoothCallbackUtil::syncToAsyncDeviceCallback(
+    MultiCallbackUserDataPtr userData, std::string &address)
+{
+    BluetoothCallbackUserDataPtr data =
+        new BluetoothCallbackUserData(userData, address);
+
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+void BluetoothCallbackUtil::syncToAsyncDeviceArrayCallback(
+    MultiCallbackUserDataPtr userData)
+{
+    BluetoothCallbackUserDataPtr data =
+        new BluetoothCallbackUserData(userData,
+            BluetoothCallbackUserData::BT_CB_DEVICES);
+
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+void BluetoothCallbackUtil::syncToAsyncServiceCallback(
+    MultiCallbackUserDataPtr userData, std::string &uuid, std::string &name)
+{
+    BluetoothCallbackUserDataPtr data = new BluetoothCallbackUserData(userData, uuid, name);
+    ecore_idler_add(jobCompleteCB, data);
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothCallbackUtil.h b/src/Bluetooth/BluetoothCallbackUtil.h
new file mode 100644 (file)
index 0000000..8f21764
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CALLBACK_UTIL_H__
+#define __TIZEN_BLUETOOTH_CALLBACK_UTIL_H__
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+
+class BluetoothCallbackUserData
+{
+public:
+    typedef enum {
+        BT_CB_SUCCESS,
+        BT_CB_ERROR,
+        BT_CB_DEVICE,
+        BT_CB_DEVICES,
+        BT_CB_SERVICE
+    } callbackTypeE;
+
+
+    BluetoothCallbackUserData(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData,
+        callbackTypeE type)
+    {
+        mUserData = userData;
+        mCBType = type;
+    };
+
+    BluetoothCallbackUserData(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData,
+        Common::BasePlatformException error)
+    {
+        mUserData = userData;
+        mErrorName = error.getName();
+        mErrorMessage = error.getMessage();
+        mCBType = BT_CB_ERROR;
+    };
+
+    BluetoothCallbackUserData(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData,
+        std::string &uuid,
+        std::string &name)
+    {
+        mUserData = userData;
+        mCBType = BT_CB_SERVICE;
+        mUUID = uuid;
+        mName = name;
+    };
+
+    BluetoothCallbackUserData(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData,
+        std::string &address)
+    {
+        mUserData = userData;
+        mCBType = BT_CB_DEVICE;
+        mAddress = address;
+    };
+
+    virtual ~BluetoothCallbackUserData()
+    {};
+
+    callbackTypeE mCBType;
+    DeviceAPI::Common::MultiCallbackUserDataPtr mUserData;
+    std::string mUUID;
+    std::string mName;
+    std::string mAddress;
+    std::string mErrorName;
+    std::string mErrorMessage;
+};
+
+typedef BluetoothCallbackUserData* BluetoothCallbackUserDataPtr;
+
+class BluetoothCallbackUtil
+{
+public:
+    static void syncToAsyncSuccessCallback(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData);
+    static void syncToAsyncErrorCallback(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData,
+        Common::BasePlatformException error);
+    static void syncToAsyncDeviceCallback(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData,
+        std::string &address);
+    static void syncToAsyncDeviceArrayCallback(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData);
+    static void syncToAsyncServiceCallback(
+        DeviceAPI::Common::MultiCallbackUserDataPtr userData,
+        std::string &uuid,
+        std::string &name);
+};
+
+
+} // Bluetooth
+} // DeviceAPI
+
+
+#endif // __TIZEN_BLUETOOTH_CALLBACK_UTIL_H__
diff --git a/src/Bluetooth/BluetoothClass.cpp b/src/Bluetooth/BluetoothClass.cpp
new file mode 100644 (file)
index 0000000..02700d6
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+
+#include "plugin_config.h"
+#include "BluetoothClass.h"
+#include "BluetoothClassDeviceMajor.h"
+#include "BluetoothClassDeviceMinor.h"
+#include "BluetoothClassDeviceService.h"
+#include "JSBluetoothClassDeviceService.h"
+
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothClass::BluetoothClass(bt_class_s bluetoothClass)
+{
+    Common::SecurityAccessor();
+    mMajor = BluetoothClassDeviceMajor::getInstance()->
+        getMajorValue(bluetoothClass.major_device_class);
+    mMinor = BluetoothClassDeviceMinor::getInstance()->
+        getMinorValue(bluetoothClass.minor_device_class);
+    mServices= BluetoothClassDeviceService::getInstance()->
+        getServiceValues(bluetoothClass.major_service_class_mask);
+}
+
+BluetoothClass::~BluetoothClass()
+{
+}
+
+unsigned long BluetoothClass::getMajor() const
+{
+    return mMajor;
+}
+
+unsigned long BluetoothClass::getMinor() const
+{
+    return mMinor;
+}
+
+JSValueRef BluetoothClass::getServices(JSContextRef context)
+{
+    return JSUtil::toJSValueRef_(context, mServices);
+}
+
+bool BluetoothClass::hasService(unsigned long service)
+{
+    for(auto iter = mServices.begin(); iter != mServices.end(); ++iter) {
+        if((*iter) == service) {
+            return true;
+        }
+    }
+    return false;
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothClass.h b/src/Bluetooth/BluetoothClass.h
new file mode 100644 (file)
index 0000000..96ebc89
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CLASS_H__
+#define __TIZEN_BLUETOOTH_CLASS_H__
+
+#include <string>
+#include <vector>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <bluetooth.h>
+#include <Security.h>
+#include <memory>
+#include <PropertyBag.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClass : public Common::SecurityAccessor
+{
+public:
+    BluetoothClass(bt_class_s bluetoothClass);
+    virtual ~BluetoothClass();
+
+    unsigned long getMajor() const;
+    unsigned long getMinor() const;
+    JSValueRef getServices(JSContextRef context);
+
+    bool hasService(unsigned long service);
+
+private:
+    unsigned long mMajor;
+    unsigned long mMinor;
+    std::vector<unsigned long> mServices;
+    //Common::PropertyBag mLocalProperty;
+};
+
+typedef std::shared_ptr<BluetoothClass> BluetoothClassSharedPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_CLASS_H__
diff --git a/src/Bluetooth/BluetoothClassDeviceMajor.cpp b/src/Bluetooth/BluetoothClassDeviceMajor.cpp
new file mode 100644 (file)
index 0000000..9a6d46c
--- /dev/null
@@ -0,0 +1,99 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+
+#include "BluetoothClassDeviceMajor.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothClassDeviceMajor::BluetoothClassDeviceMajor()
+{
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("MISC", 0x00));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("COMPUTER", 0x01));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("PHONE", 0x02));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("NETWORK", 0x03));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("AUDIO_VIDEO", 0x04));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("PERIPHERAL", 0x05));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("IMAGING", 0x06));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("WEARABLE", 0x07));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("TOY", 0x08));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("HEALTH", 0x09));
+    mMajorStringMap.insert(
+        std::pair<std::string, unsigned long>("UNCATEGORIZED", 0x1F));
+
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_MISC, 0x00));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_COMPUTER, 0x01));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_PHONE, 0x02));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_LAN_NETWORK_ACCESS_POINT, 0x03));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_AUDIO_VIDEO, 0x04));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_PERIPHERAL, 0x05));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_IMAGING, 0x06));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_WEARABLE, 0x07));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_TOY, 0x08));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_HEALTH, 0x09));
+    mMajorEnumMap.insert(std::pair<bt_major_device_class_e, unsigned long>(
+        BT_MAJOR_DEVICE_CLASS_UNCATEGORIZED, 0x1F));
+}
+
+BluetoothClassDeviceMajor::~BluetoothClassDeviceMajor()
+{
+}
+
+BluetoothClassDeviceMajor* BluetoothClassDeviceMajor::getInstance()
+{
+    static BluetoothClassDeviceMajor instance;
+    return &instance;
+}
+
+unsigned long BluetoothClassDeviceMajor::getMajorValue(std::string major)
+{
+    return mMajorStringMap.find(major)->second;
+}
+
+unsigned long BluetoothClassDeviceMajor::getMajorValue(
+    bt_major_device_class_e major)
+{
+    return mMajorEnumMap.find(major)->second;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothClassDeviceMajor.h b/src/Bluetooth/BluetoothClassDeviceMajor.h
new file mode 100644 (file)
index 0000000..e57c927
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
+#define __TIZEN_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
+
+#include <string>
+#include <map>
+#include <bluetooth.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClassDeviceMajor
+{
+public:
+
+    BluetoothClassDeviceMajor();
+    virtual ~BluetoothClassDeviceMajor();
+
+    static BluetoothClassDeviceMajor* getInstance();
+    unsigned long getMajorValue(std::string major);
+    unsigned long getMajorValue(bt_major_device_class_e major);
+
+private:
+    std::map<std::string, unsigned long> mMajorStringMap;
+    std::map<bt_major_device_class_e, unsigned long> mMajorEnumMap;
+};
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
diff --git a/src/Bluetooth/BluetoothClassDeviceMinor.cpp b/src/Bluetooth/BluetoothClassDeviceMinor.cpp
new file mode 100644 (file)
index 0000000..a3695a1
--- /dev/null
@@ -0,0 +1,347 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+
+#include "BluetoothClassDeviceMinor.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothClassDeviceMinor::BluetoothClassDeviceMinor()
+{
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "COMPUTER_UNCATEGORIZED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "COMPUTER_DESKTOP", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "COMPUTER_SERVER", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "COMPUTER_LAPTOP", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "COMPUTER_HANDHELD_PC_OR_PDA", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "COMPUTER_PALM_PC_OR_PDA", 0x5));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "COMPUTER_WEARABLE", 0x06));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PHONE_UNCATEGORIZED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PHONE_CELLULAR", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PHONE_CORDLESS", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PHONE_SMARTPHONE", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PHONE_MODEM_OR_GATEWAY", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PHONE_ISDN", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_UNRECOGNIZED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_WEARABLE_HEADSET", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_HANDSFREE", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_MICROPHONE", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_LOUDSPEAKER", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_HEADPHONES", 0x06));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_PORTABLE_AUDIO", 0x07));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_CAR_AUDIO", 0x08));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_SETTOP_BOX", 0x09));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_HIFI", 0x0a));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_VCR", 0x0b));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_VIDEO_CAMERA", 0x0c));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_CAMCORDER", 0x0d));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_MONITOR", 0x0e));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_DISPLAY_AND_LOUDSPEAKER", 0x0f));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_VIDEO_CONFERENCING", 0x10));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "AV_GAMING_TOY", 0x12));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_UNCATEGORIZED", 0));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_KEYBOARD", 0x10));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_POINTING_DEVICE", 0x20));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_KEYBOARD_AND_POINTING_DEVICE", 0x30));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_JOYSTICK", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_GAMEPAD", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_REMOTE_CONTROL", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_SENSING_DEVICE", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_DEGITIZER_TABLET", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_CARD_READER", 0x06));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_DIGITAL_PEN", 0x07));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_HANDHELD_SCANNER", 0x08));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "PERIPHERAL_HANDHELD_INPUT_DEVICE", 0x09));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "IMAGING_UNCATEGORIZED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "IMAGING_DISPLAY", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "IMAGING_CAMERA", 0x08));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "IMAGING_SCANNER", 0x10));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "IMAGING_PRINTER", 0x20));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "WEARABLE_WRITST_WATCH", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "WEARABLE_PAGER", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "WEARABLE_JACKET", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "WEARABLE_HELMET", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "WEARABLE_GLASSES", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "TOY_ROBOT", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "TOY_VEHICLE", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "TOY_DOLL", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "TOY_CONTROLLER", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "TOY_GAME", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_UNDEFINED", 0x00));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_BLOOD_PRESSURE_MONITOR", 0x01));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_THERMOMETER", 0x02));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_WEIGHING_SCALE", 0x03));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_GLUCOSE_METER", 0x04));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_PULSE_OXIMETER", 0x05));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_PULSE_RATE_MONITOR", 0x06));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_DATA_DISPLAY", 0x07));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_STEP_COUNTER", 0x08));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_BODY_COMPOSITION_ANALYZER", 0x09));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_PEAK_FLOW_MONITOR", 0x0a));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_MEDICATION_MONITOR", 0x0b));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_KNEE_PROSTHESIS", 0x0c));
+    mMinorStringMap.insert(std::pair<std::string, unsigned long>(
+        "HEALTH_ANKLE_PROSTHESIS", 0x0d));
+
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_COMPUTER_UNCATEGORIZED, 0x00));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_COMPUTER_DESKTOP_WORKSTATION , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_COMPUTER_SERVER_CLASS , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_COMPUTER_LAPTOP , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_COMPUTER_HANDHELD_PC_OR_PDA , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_COMPUTER_PALM_SIZED_PC_OR_PDA, 0x5));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_COMPUTER_WEARABLE_COMPUTER , 0x06));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PHONE_UNCATEGORIZED , 0x00));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PHONE_CELLULAR , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PHONE_CORDLESS , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PHONE_SMART_PHONE , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PHONE_WIRED_MODEM_OR_VOICE_GATEWAY , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PHONE_COMMON_ISDN_ACCESS , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_UNCATEGORIZED , 0x00));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_WEARABLE_HEADSET , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HANDS_FREE , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_MICROPHONE , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_LOUDSPEAKER , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HEADPHONES , 0x06));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_PORTABLE_AUDIO , 0x07));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_CAR_AUDIO , 0x08));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_SET_TOP_BOX , 0x09));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_HIFI_AUDIO_DEVICE , 0x0a));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VCR , 0x0b));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_CAMERA , 0x0c));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_CAMCORDER , 0x0d));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_MONITOR , 0x0e));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_DISPLAY_LOUDSPEAKER , 0x0f));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_VIDEO_CONFERENCING , 0x10));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_AUDIO_VIDEO_GAMING_TOY , 0x12));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERA_UNCATEGORIZED , 0));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_KEY_BOARD , 0x10));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_POINTING_DEVICE , 0x20));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_COMBO_KEYBOARD_POINTING_DEVICE , 0x30));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_JOYSTICK , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_GAME_PAD , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_REMOTE_CONTROL , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_SENSING_DEVICE , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_DIGITIZER_TABLET , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_CARD_READER , 0x06));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_DIGITAL_PEN , 0x07));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_HANDHELD_SCANNER , 0x08));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_PERIPHERAL_HANDHELD_GESTURAL_INPUT_DEVICE , 0x09));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_IMAGING_DISPLAY , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_IMAGING_CAMERA , 0x08));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_IMAGING_SCANNER , 0x10));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_IMAGING_PRINTER, 0x20));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_WEARABLE_WRIST_WATCH , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_WEARABLE_PAGER , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_WEARABLE_JACKET , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_WEARABLE_HELMET , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_WEARABLE_GLASSES , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_TOY_ROBOT , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_TOY_VEHICLE , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_TOY_DOLL_ACTION , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_TOY_CONTROLLER , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_TOY_GAME , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_UNCATEGORIZED , 0x00));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_BLOOD_PRESSURE_MONITOR , 0x01));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_THERMOMETER , 0x02));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_WEIGHING_SCALE , 0x03));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_GLUCOSE_METER , 0x04));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_PULSE_OXIMETER , 0x05));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_HEART_PULSE_RATE_MONITOR , 0x06));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_DATA_DISPLAY , 0x07));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_STEP_COUNTER , 0x08));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_BODY_COMPOSITION_ANALYZER , 0x09));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_PEAK_FLOW_MONITOR , 0x0a));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_MEDICATION_MONITOR , 0x0b));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_KNEE_PROSTHESIS , 0x0c));
+    mMinorEnumMap.insert(std::pair<bt_minor_device_class_e, unsigned long>(
+        BT_MINOR_DEVICE_CLASS_HEALTH_ANKLE_PROSTHESIS , 0x0d));
+}
+
+BluetoothClassDeviceMinor::~BluetoothClassDeviceMinor()
+{
+}
+
+BluetoothClassDeviceMinor* BluetoothClassDeviceMinor::getInstance()
+{
+    static BluetoothClassDeviceMinor instance;
+    return &instance;
+}
+
+unsigned long BluetoothClassDeviceMinor::getMinorValue(std::string minor)
+{
+    return mMinorStringMap.find(minor)->second;
+}
+
+unsigned long BluetoothClassDeviceMinor::getMinorValue(
+    bt_minor_device_class_e minor)
+{
+    // F/W provides more minor deivce class
+    auto iter = mMinorEnumMap.find(minor);
+    if(iter != mMinorEnumMap.end()) {
+        return iter->second;
+    }
+
+    return 0;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothClassDeviceMinor.h b/src/Bluetooth/BluetoothClassDeviceMinor.h
new file mode 100644 (file)
index 0000000..90f62da
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CLASS_DEVICE_MINOR_H__
+#define __TIZEN_BLUETOOTH_CLASS_DEVICE_MINOR_H__
+
+#include <string>
+#include <map>
+#include <bluetooth.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClassDeviceMinor
+{
+public:
+    BluetoothClassDeviceMinor();
+    virtual ~BluetoothClassDeviceMinor();
+
+    static BluetoothClassDeviceMinor* getInstance();
+    unsigned long getMinorValue(std::string minor);
+    unsigned long getMinorValue(bt_minor_device_class_e minor);
+
+private:
+    std::map<std::string, unsigned long> mMinorStringMap;
+    std::map<bt_minor_device_class_e, unsigned long> mMinorEnumMap;
+};
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_CLASS_DEVICE_MINOR_H__
diff --git a/src/Bluetooth/BluetoothClassDeviceService.cpp b/src/Bluetooth/BluetoothClassDeviceService.cpp
new file mode 100644 (file)
index 0000000..b2502db
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+
+#include "BluetoothClassDeviceService.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothClassDeviceService::BluetoothClassDeviceService()
+{
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>(
+        "LIMITED_DISCOVERABILITY", 0x0001));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>(
+        "POSITIONING", 0x0008));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>(
+        "NETWORKING", 0x0010));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>(
+        "RENDERING", 0x0020));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>(
+        "CAPTURING", 0x0040));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>(
+        "OBJECT_TRANSFER", 0x0080));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>(
+        "AUDIO", 0x0100));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>(
+        "TELEPHONY", 0x0200));
+    mServiceStringMap.insert(std::pair<std::string, unsigned long>(
+        "INFORMATION", 0x0400));
+
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(
+        BT_MAJOR_SERVICE_CLASS_LIMITED_DISCOVERABLE_MODE, 0x0001));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(
+        BT_MAJOR_SERVICE_CLASS_POSITIONING, 0x0008));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(
+        BT_MAJOR_SERVICE_CLASS_NETWORKING, 0x0010));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(
+        BT_MAJOR_SERVICE_CLASS_RENDERING, 0x0020));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(
+        BT_MAJOR_SERVICE_CLASS_CAPTURING, 0x0040));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(
+        BT_MAJOR_SERVICE_CLASS_OBJECT_TRANSFER, 0x0080));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(
+        BT_MAJOR_SERVICE_CLASS_AUDIO, 0x0100));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(
+        BT_MAJOR_SERVICE_CLASS_TELEPHONY, 0x0200));
+    mServiceEnumMap.insert(std::pair<bt_major_service_class_e, unsigned long>(
+        BT_MAJOR_SERVICE_CLASS_INFORMATION, 0x0400));
+}
+
+BluetoothClassDeviceService::~BluetoothClassDeviceService()
+{
+}
+
+BluetoothClassDeviceService* BluetoothClassDeviceService::getInstance()
+{
+    static BluetoothClassDeviceService instance;
+    return &instance;
+}
+
+unsigned long BluetoothClassDeviceService::getServiceValue(std::string service)
+{
+    return mServiceStringMap.find(service)->second;
+}
+
+unsigned long BluetoothClassDeviceService::getServiceValue(
+    bt_major_service_class_e service)
+{
+    return mServiceEnumMap.find(service)->second;
+}
+
+std::vector<unsigned long> BluetoothClassDeviceService::getServiceValues(
+    int serviceMask)
+{
+    std::vector<unsigned long> ret;
+    for(auto iter = mServiceEnumMap.begin();
+        iter != mServiceEnumMap.end(); iter++) {
+
+        if(iter->first & serviceMask) {
+            ret.push_back(iter->second);
+        }
+    }
+
+    return ret;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothClassDeviceService.h b/src/Bluetooth/BluetoothClassDeviceService.h
new file mode 100644 (file)
index 0000000..7d05f9b
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
+#define __TIZEN_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
+
+#include <string>
+#include <map>
+#include <vector>
+#include <bluetooth.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClassDeviceService
+{
+public:
+    BluetoothClassDeviceService();
+    virtual ~BluetoothClassDeviceService();
+
+    static BluetoothClassDeviceService* getInstance();
+    unsigned long getServiceValue(std::string service);
+    unsigned long getServiceValue(bt_major_service_class_e service);
+    std::vector<unsigned long> getServiceValues(int serviceMask);
+
+private:
+    std::map<std::string, unsigned long> mServiceStringMap;
+    std::map<bt_major_service_class_e, unsigned long> mServiceEnumMap;
+};
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
diff --git a/src/Bluetooth/BluetoothDevice.cpp b/src/Bluetooth/BluetoothDevice.cpp
new file mode 100644 (file)
index 0000000..728acc0
--- /dev/null
@@ -0,0 +1,199 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+
+#include "plugin_config.h"
+#include "BluetoothDevice.h"
+#include "BluetoothAdapter.h"
+#include "BluetoothUtil.h"
+#include "JSBluetoothClass.h"
+
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothDevice::BluetoothDevice(
+    bt_adapter_device_discovery_info_s *discoveryInfo)
+{
+    Common::SecurityAccessor();
+    mName = std::string(discoveryInfo->remote_name);
+    mAddress = std::string(discoveryInfo->remote_address);
+    mDeviceClass = BluetoothClassSharedPtr(
+        new BluetoothClass(discoveryInfo->bt_class));
+
+    for(int i = 0; i < discoveryInfo->service_count; i++) {
+        mUUIDs.push_back(std::string(discoveryInfo->service_uuid[i]));
+    }
+    isUpdated = true;
+}
+
+BluetoothDevice::BluetoothDevice(bt_device_info_s *deviceInfo)
+{
+    Common::SecurityAccessor();
+    mName = std::string(deviceInfo->remote_name);
+    mAddress = std::string(deviceInfo->remote_address);
+    mDeviceClass = BluetoothClassSharedPtr(
+        new BluetoothClass(deviceInfo->bt_class));
+
+    for(int i = 0; i < deviceInfo->service_count; i++) {
+        mUUIDs.push_back(std::string(deviceInfo->service_uuid[i]));
+    }
+    isUpdated = true;
+}
+
+BluetoothDevice::~BluetoothDevice()
+{
+    BluetoothAdapter::getInstance()->removeConnReq(mAddress);
+}
+
+void BluetoothDevice::updateInfo(bt_device_info_s *deviceInfo)
+{
+    mName = std::string(deviceInfo->remote_name);
+    mUUIDs.clear();
+    for(int i = 0; i < deviceInfo->service_count; i++) {
+        mUUIDs.push_back(std::string(deviceInfo->service_uuid[i]));
+    }
+    isUpdated = true;
+}
+
+std::string BluetoothDevice::getName() const
+{
+    return mName;
+}
+
+std::string BluetoothDevice::getAddress() const
+{
+    return mAddress;
+}
+
+void BluetoothDevice::copyAceCheckAccessFunction(
+    const Common::SecurityAccessor *securityAccessor)
+{
+    Common::SecurityAccessor::copyAceCheckAccessFunction(securityAccessor);
+    mDeviceClass->copyAceCheckAccessFunction(securityAccessor);
+}
+
+JSValueRef BluetoothDevice::getDeviceClass(JSContextRef context)
+{
+    return JSBluetoothClass::createJSObject(context, mDeviceClass);
+}
+
+bool BluetoothDevice::isBonded() const
+{
+    bool isBonded = false;
+    int ret = 0;
+    bt_device_info_s *deviceInfo = NULL;
+
+    try {
+        ret = bt_adapter_get_bonded_device_info(mAddress.c_str(), &deviceInfo);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_get_bonded_device_info failed");
+        }
+        if (!deviceInfo) {
+            LOGE("deviceInfo is null");
+            throw UnknownException("deviceInfo is null");
+        }
+
+        isBonded = deviceInfo->is_bonded;
+        ret = bt_adapter_free_device_info(deviceInfo);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_free_device_info failed");
+        }
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+    }
+    return isBonded;
+}
+
+bool BluetoothDevice::isTrusted() const
+{
+    bool isTrusted = false;
+    int ret = 0;
+    bt_device_info_s *deviceInfo = NULL;
+
+    try {
+        ret = bt_adapter_get_bonded_device_info(mAddress.c_str(), &deviceInfo);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_get_bonded_device_info failed");
+        }
+        if (!deviceInfo) {
+            LOGE("deviceInfo is null");
+            throw UnknownException("deviceInfo is null");
+        }
+
+        isTrusted = deviceInfo->is_authorized;
+        ret = bt_adapter_free_device_info(deviceInfo);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_free_device_info failed");
+        }
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+    }
+    return isTrusted;
+}
+
+bool BluetoothDevice::isConnected() const
+{
+    bool isConnected = false;
+    int ret = 0;
+    bt_device_info_s *deviceInfo = NULL;
+
+    try {
+        ret = bt_adapter_get_bonded_device_info(mAddress.c_str(), &deviceInfo);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_get_bonded_device_info failed");
+        }
+        if (!deviceInfo) {
+            LOGE("deviceInfo is null");
+            throw UnknownException("deviceInfo is null");
+        }
+
+        isConnected = deviceInfo->is_connected;
+        ret = bt_adapter_free_device_info(deviceInfo);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_adapter_free_device_info failed");
+        }
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+    }
+    return isConnected;
+}
+
+JSValueRef BluetoothDevice::getUUIDs(JSContextRef context)
+{
+    return JSUtil::toJSValueRef(context, mUUIDs);
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothDevice.h b/src/Bluetooth/BluetoothDevice.h
new file mode 100644 (file)
index 0000000..703932c
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_DEVICE_H__
+#define __TIZEN_BLUETOOTH_DEVICE_H__
+
+#include <string>
+#include <vector>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <bluetooth.h>
+#include <memory>
+#include <PropertyBag.h>
+#include <Security.h>
+#include "BluetoothClass.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothDevice : public Common::SecurityAccessor
+{
+public:
+    BluetoothDevice(bt_adapter_device_discovery_info_s *discoveryInfo);
+    BluetoothDevice(bt_device_info_s *deviceInfo);
+    virtual ~BluetoothDevice();
+
+    void updateInfo(bt_device_info_s *deviceInfo);
+    std::string getName() const;
+    std::string getAddress() const;
+    JSValueRef getDeviceClass(JSContextRef context);
+    bool isBonded() const;
+    bool isTrusted() const;
+    bool isConnected() const;
+    JSValueRef getUUIDs(JSContextRef context);
+    void copyAceCheckAccessFunction(
+        const Common::SecurityAccessor *securityAccessor);
+private:
+    std::string mName;
+    std::string mAddress;
+    BluetoothClassSharedPtr mDeviceClass;
+    std::vector<std::string> mUUIDs;
+    bool isUpdated;
+};
+
+typedef std::shared_ptr<BluetoothDevice> BluetoothDeviceSharedPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_DEVICE_H__
diff --git a/src/Bluetooth/BluetoothHealthApplication.cpp b/src/Bluetooth/BluetoothHealthApplication.cpp
new file mode 100644 (file)
index 0000000..c32a6e4
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "BluetoothHealthApplication.h"
+#include "plugin_config.h"
+
+#include <bluetooth.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothHealthApplication::BluetoothHealthApplication(std::string appID,
+    std::string name, unsigned short dataType)
+{
+    Common::SecurityAccessor();
+    mAppID = appID;
+    mName = name;
+    mDataType = dataType;
+    mIsRegistered = true;
+}
+
+BluetoothHealthApplication::~BluetoothHealthApplication()
+{
+    if(mIsRegistered)
+        bt_hdp_unregister_sink_app(mAppID.c_str());
+}
+
+std::string BluetoothHealthApplication::getAppID() const
+{
+    return mAppID;
+}
+
+unsigned short BluetoothHealthApplication::getDataType() const
+{
+    return mDataType;
+}
+
+std::string BluetoothHealthApplication::getName() const
+{
+    return mName;
+}
+
+bool BluetoothHealthApplication::setOnConnect(JSContextRef context,
+    JSObjectRef onConnect)
+{
+    LOGD("Enter");
+
+    MultiCallbackUserDataPtr callback(
+        new MultiCallbackUserData(GlobalContextManager::getInstance()->
+            getGlobalContext(context)));
+
+    if(!callback){
+        LOGW("Can't create MultiCallbackUserData");
+        return false;
+    }
+    callback->setCallback("onconnect", onConnect);
+    mOnConnect = callback;
+
+    return mLocalProperty.setProperty(context,
+        BLUETOOTH_HEALTH_APPLICATION_ONCONNECT, onConnect);
+}
+
+MultiCallbackUserDataPtr BluetoothHealthApplication::getOnConnect() const
+{
+    return mOnConnect;
+}
+
+JSValueRef BluetoothHealthApplication::getOnConnect(JSContextRef context)
+{
+    LOGD("Enter");
+
+    JSValueRef onConnect = mLocalProperty.getProperty(context,
+        BLUETOOTH_HEALTH_APPLICATION_ONCONNECT);
+
+    if(onConnect == NULL) {
+        LOGD("onconnect is null");
+        return JSValueMakeNull(context);
+    }
+
+    return onConnect;
+}
+
+bool BluetoothHealthApplication::getRegistrationState() const
+{
+    return mIsRegistered;
+}
+
+void BluetoothHealthApplication::setRegistrationState(bool isRegistered)
+{
+    mIsRegistered = isRegistered;
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothHealthApplication.h b/src/Bluetooth/BluetoothHealthApplication.h
new file mode 100644 (file)
index 0000000..fabe01a
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_HEALTH_APPLICATION_H__
+#define __TIZEN_BLUETOOTH_HEALTH_APPLICATION_H__
+
+#include <string>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <memory>
+
+#include <MultiCallbackUserData.h>
+#include <PropertyBag.h>
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothHealthApplication : public Common::SecurityAccessor
+{
+public:
+    BluetoothHealthApplication(std::string appID, std::string name, unsigned short dataType);
+    virtual ~BluetoothHealthApplication();
+
+    std::string getAppID() const;
+    unsigned short getDataType() const;
+    std::string getName() const;
+    bool getRegistrationState() const;
+    void setRegistrationState(bool isRegistered);
+    Common::MultiCallbackUserDataPtr getOnConnect() const;
+    JSValueRef getOnConnect(JSContextRef context);
+    bool setOnConnect(JSContextRef context, JSObjectRef onConnect);
+
+
+private:
+    std::string mAppID;
+    std::string mName;
+    bool mIsRegistered;
+    Common::MultiCallbackUserDataPtr mOnConnect;
+    unsigned short mDataType;
+    Common::PropertyBag mLocalProperty;
+};
+
+typedef std::shared_ptr<BluetoothHealthApplication> BluetoothHealthApplicationSharedPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_HEALTH_APPLICATION_H__
diff --git a/src/Bluetooth/BluetoothHealthChannel.cpp b/src/Bluetooth/BluetoothHealthChannel.cpp
new file mode 100644 (file)
index 0000000..6019220
--- /dev/null
@@ -0,0 +1,147 @@
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+#include "BluetoothHealthChannel.h"
+#include "BluetoothUtil.h"
+#include "JSBluetoothDevice.h"
+#include "JSBluetoothHealthApplication.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothHealthChannel::BluetoothHealthChannel(unsigned int channel,
+    BluetoothDeviceSharedPtr remoteDevice, bt_hdp_channel_type_e type,
+    BluetoothHealthApplicationSharedPtr application)
+{
+    Common::SecurityAccessor();
+    mChannel = channel;
+    mRemoteDevice = remoteDevice;
+    if(type == BT_HDP_CHANNEL_TYPE_RELIABLE) {
+        mChannelTypeStr = "RELIABLE";
+    }
+    else {
+        mChannelTypeStr = "STREAMING";
+    }
+    mChannelType = type;
+    mApp = application;
+    mIsConnected = true;
+}
+
+BluetoothHealthChannel::~BluetoothHealthChannel()
+{
+    if(mIsConnected) {
+        bt_hdp_disconnect(mRemoteDevice->getAddress().c_str(), mChannel);
+    }
+}
+
+bool BluetoothHealthChannel::getConnectionState() const
+{
+    return mIsConnected;
+}
+
+void BluetoothHealthChannel::setConnectionState(bool isConnected)
+{
+    mIsConnected = isConnected;
+}
+
+unsigned int BluetoothHealthChannel::getChannel() const
+{
+    return mChannel;
+}
+
+std::string BluetoothHealthChannel::getChannelTypeStr() const
+{
+    return mChannelTypeStr;
+}
+
+bt_hdp_channel_type_e BluetoothHealthChannel::getChannelType() const
+{
+    return mChannelType;
+}
+
+JSValueRef BluetoothHealthChannel::getApp(JSContextRef context)
+{
+    return JSBluetoothHealthApplication::createJSObject(context, mApp);
+}
+
+JSValueRef BluetoothHealthChannel::getPeer(JSContextRef context)
+{
+    return JSBluetoothDevice::createJSObject(context, mRemoteDevice);
+}
+
+Common::MultiCallbackUserDataPtr BluetoothHealthChannel::getListener() const
+{
+    return mListener;
+}
+
+unsigned long BluetoothHealthChannel::sendData(char* data, unsigned long size)
+{
+    int ret = 0;
+    TIME_TRACER_ITEM_BEGIN("sendData::bt_hdp_send_data", 1);
+    ret = bt_hdp_send_data(mChannel, data, static_cast<unsigned int>(size));
+    TIME_TRACER_ITEM_END("sendData::bt_hdp_send_data", 1);
+
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret, "bt_hdp_send_data failed");
+    }
+
+    LOGD("bt_hdp_send_data() succeeded");
+    return size;
+}
+
+void BluetoothHealthChannel::close()
+{
+    LOGD("Enter");
+
+    if(!mIsConnected) {
+        LOGD("Already disconnected");
+        return;
+    }
+
+    int ret = 0;
+    TIME_TRACER_ITEM_BEGIN("close::bt_hdp_disconnect", 1);
+    ret = bt_hdp_disconnect(mRemoteDevice->getAddress().c_str(), mChannel);
+    TIME_TRACER_ITEM_END("close::bt_hdp_disconnect", 1);
+
+    if(ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret, "bt_hdp_disconnect failed");
+    }
+
+    mIsConnected = false;
+}
+
+void BluetoothHealthChannel::setListener(MultiCallbackUserDataPtr callback)
+{
+    mListener = callback;
+}
+
+void BluetoothHealthChannel::unsetListener()
+{
+    mListener.reset();
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothHealthChannel.h b/src/Bluetooth/BluetoothHealthChannel.h
new file mode 100644 (file)
index 0000000..eca0bbb
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_HEALTH_CHANNEL_H__
+#define __TIZEN_BLUETOOTH_HEALTH_CHANNEL_H__
+
+#include <string>
+#include <bluetooth.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <Security.h>
+#include <MultiCallbackUserData.h>
+#include "BluetoothDevice.h"
+#include "BluetoothHealthApplication.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothHealthChannel : public Common::SecurityAccessor
+{
+public:
+    BluetoothHealthChannel(unsigned int channel, BluetoothDeviceSharedPtr remoteDevice, bt_hdp_channel_type_e type, BluetoothHealthApplicationSharedPtr application);
+    virtual ~BluetoothHealthChannel();
+
+    bool getConnectionState() const;
+    void setConnectionState(bool isConnected);
+    unsigned int getChannel() const;
+    std::string getChannelTypeStr() const;
+    bt_hdp_channel_type_e getChannelType() const;
+    JSValueRef getApp(JSContextRef context);
+    JSValueRef getPeer(JSContextRef context);
+    Common::MultiCallbackUserDataPtr getListener() const;
+
+    unsigned long sendData(char* data, unsigned long size);
+    void close();
+    void setListener(Common::MultiCallbackUserDataPtr callback);
+    void unsetListener();
+
+private:
+    unsigned int mChannel;
+    bool mIsConnected;
+    std::string mChannelTypeStr;
+    bt_hdp_channel_type_e mChannelType;
+    BluetoothDeviceSharedPtr mRemoteDevice;
+    BluetoothHealthApplicationSharedPtr mApp;
+
+    Common::MultiCallbackUserDataPtr mListener;
+};
+
+typedef BluetoothHealthChannel* BluetoothHealthChannelPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_HEALTH_CHANNEL_H__
diff --git a/src/Bluetooth/BluetoothHealthProfileHandler.cpp b/src/Bluetooth/BluetoothHealthProfileHandler.cpp
new file mode 100644 (file)
index 0000000..973e698
--- /dev/null
@@ -0,0 +1,388 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include <TimeTracer.h>
+
+#include "BluetoothHealthProfileHandler.h"
+#include "BluetoothHealthProfileHandlerCallback.h"
+#include "JSBluetoothHealthApplication.h"
+#include "JSBluetoothDevice.h"
+#include "JSBluetoothHealthChannel.h"
+#include "BluetoothHealthChannel.h"
+#include "BluetoothUtil.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+void BluetoothHealthProfileHandler::onConnected(int result,
+    const char *remote_address, const char *app_id, bt_hdp_channel_type_e type,
+    unsigned int channel, void *userData)
+{
+    LOGD("Enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    HealthProfileHandlerPtr object =
+        static_cast<HealthProfileHandlerPtr>(userData);
+
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    if(result != BT_ERROR_NONE) {
+        LOGD("Not BT_ERROR_NONE %d", result);
+    }
+
+    LOGD("Connected app: %s", app_id);
+    LOGD("Connected channel: %d", channel);
+
+    std::string appID(app_id);
+    auto iter = object->mRegisteredHealthAppMap.find(appID);
+    if(iter == object->mRegisteredHealthAppMap.end()) {
+        LOGW("This app is not registered");
+        return;
+    }
+    BluetoothHealthApplicationSharedPtr application = iter->second;
+
+    bool isChannelInserted = false;
+    BluetoothHealthChannelPtr healthChannel = NULL;
+
+    //  call BluetoothHealthApplication.onconnect
+    if(result == BT_ERROR_NONE) {
+        Common::MultiCallbackUserDataPtr callback = application->getOnConnect();
+        if(callback) {
+            bt_device_info_s *deviceInfo = NULL;
+            if(bt_adapter_get_bonded_device_info(remote_address, &deviceInfo)
+                == BT_ERROR_NONE && deviceInfo != NULL) {
+
+                BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
+
+                // need to check
+                device->copyAceCheckAccessFunction(getInstance());
+                bt_adapter_free_device_info(deviceInfo);
+
+                LOGD("invoke BluetoothHealthApplication.onconnect");
+                healthChannel =
+                    new BluetoothHealthChannel(channel, device, type, application);
+                healthChannel->copyAceCheckAccessFunction(getInstance());
+                object->mConnectedSocketMap.insert(
+                    std::pair<unsigned int, BluetoothHealthChannelPtr>(
+                        channel, healthChannel));
+                isChannelInserted = true;
+                callback->invokeCallback("onconnect",
+                    JSBluetoothHealthChannel::createJSObject(
+                        callback->getContext(), healthChannel));
+            }
+            else {
+                LOGE("Can't call BluetoothHealthApplication.onconnect because failed to get device info");
+            }
+        }
+        else {
+            LOGD("BluetoothHealthApplication.onconnect is not set");
+        }
+    }
+
+    // in case of connectToSource()
+    HealthConnReqMapT::iterator i = object->mHealthConnReqMap.find(application);
+    if(i != object->mHealthConnReqMap.end()) {
+        LOGD("Requested connection");
+        Common::MultiCallbackUserDataPtr callback = i->second->mUserData;
+        if(callback) {
+            if(result == BT_ERROR_NONE) {
+                if(isChannelInserted == false) {
+                    healthChannel = new BluetoothHealthChannel(channel,
+                        i->second->mRemoteDevice, type, application);
+                    healthChannel->copyAceCheckAccessFunction(getInstance());
+                    object->mConnectedSocketMap.insert(
+                        std::pair<unsigned int, BluetoothHealthChannelPtr>(
+                            channel, healthChannel));
+                }
+                callback->invokeCallback("success",
+                    JSBluetoothHealthChannel::createJSObject(
+                        callback->getContext(), healthChannel));
+            }
+            else {
+                LOGE("Failed to establish a connection with health profile");
+                callback->invokeCallback("error",
+                    JSWebAPIErrorFactory::makeErrorObject(
+                        callback->getContext(),
+                        UnknownException("Failed to establish a connection with health profile")));
+            }
+        }
+
+        // Update mHealthConnReqMap
+        object->mHealthConnReqMap.erase(i);
+    }
+    else {
+        LOGD("There is no connection request");
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothHealthProfileHandler::onDisconnected(int result,
+    const char *remote_address, unsigned int channel, void *userData)
+{
+    LOGD("Enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    HealthProfileHandlerPtr object =
+        static_cast<HealthProfileHandlerPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    LOGD("Disconnected channel: %d", channel);
+    auto iter = object->mConnectedSocketMap.find(channel);
+    if(iter == object->mConnectedSocketMap.end()) {
+        LOGW("Unexpected health disconnection event");
+        return;
+    }
+
+    if(result == BT_ERROR_NONE) {
+        BluetoothHealthChannelPtr healthChannel = iter->second;
+        object->mConnectedSocketMap.erase(iter);
+
+        healthChannel->setConnectionState(false);
+        MultiCallbackUserDataPtr callback = healthChannel->getListener();
+        if(callback)
+            callback->invokeCallback("onclose");
+    }
+    else {
+        LOGW("Failed to disconnect a connection");
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+    LOGD("End");
+}
+
+void BluetoothHealthProfileHandler::onDataReceivedCB(unsigned int channel,
+    const char *data, unsigned int size, void *userData)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    HealthProfileHandlerPtr object =
+        static_cast<HealthProfileHandlerPtr>(userData);
+    if(!object) {
+        LOGW("userData is NULL");
+        return;
+    }
+
+    LOGD("data channel: %d", channel);
+    LOGD("sent data size: %d", size);
+    auto iter = object->mConnectedSocketMap.find(channel);
+    if(iter == object->mConnectedSocketMap.end()) {
+        LOGW("Unexpected health data received event");
+        return;
+    }
+
+    BluetoothHealthChannelPtr healthChannel = iter->second;
+    MultiCallbackUserDataPtr callback = healthChannel->getListener();
+    if(callback) {
+        std::vector<signed char> receivedData;
+        for(unsigned int i = 0; i < size; i++) {
+            receivedData.push_back(static_cast<signed char>(data[i]));
+        }
+        callback->invokeCallback("onmessage",
+            JSUtil::toJSValueRef_(callback->getContext(), receivedData));
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+BluetoothHealthProfileHandler* BluetoothHealthProfileHandler::getInstance()
+{
+    static BluetoothHealthProfileHandler instance;
+    return &instance;
+}
+
+BluetoothHealthProfileHandler::BluetoothHealthProfileHandler()
+{
+    Common::SecurityAccessor();
+
+    int ret = 0;
+    ret = bt_hdp_set_connection_state_changed_cb(onConnected, onDisconnected,
+        this);
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_hdp_set_connection_state_changed_cb() failed");
+    }
+
+    ret = bt_hdp_set_data_received_cb(onDataReceivedCB, this);
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_hdp_set_data_received_cb() failed");
+    }
+}
+
+
+BluetoothHealthProfileHandler::~BluetoothHealthProfileHandler()
+{
+    // unset platform callback
+    bt_hdp_unset_connection_state_changed_cb();
+    bt_hdp_unset_data_received_cb();
+
+    mHealthConnReqMap.clear();
+    mConnectedSocketMap.clear();
+    mRegisteredHealthAppMap.clear();
+}
+
+void BluetoothHealthProfileHandler::registerSinkApp(unsigned short dataType,
+    std::string name, Common::MultiCallbackUserDataPtr callback)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+    BluetoothHealthProfileHandlerCallback::syncToAsyncRegisterCB(callback,
+        dataType, name);
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothHealthProfileHandler::returnRegisteringSinkAppResult(
+    unsigned short dataType, std::string name,
+    Common::MultiCallbackUserDataPtr callback)
+{
+    LOGD("Enter");
+
+    if (!callback) {
+        LOGE("callback is null");
+        return;
+    }
+
+    try {
+        char *app_id = NULL;
+        int ret = bt_hdp_register_sink_app(dataType, &app_id);
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_hdp_register_sink_app failed");
+        }
+
+        LOGD("Registered app: %s", app_id);
+        std::string appID(app_id);
+        BluetoothHealthApplicationSharedPtr application(
+            new BluetoothHealthApplication(appID, name, dataType));
+        application->copyAceCheckAccessFunction(getInstance());
+
+        mRegisteredHealthAppMap.insert(
+            std::pair<std::string, BluetoothHealthApplicationSharedPtr>(
+                appID, application));
+        callback->invokeCallback("success",
+            JSBluetoothHealthApplication::createJSObject(callback->getContext(),
+                application));
+
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        callback->invokeCallback("error",
+            JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), e));
+    }
+}
+
+void BluetoothHealthProfileHandler::unregisterApp(std::string appID,
+    Common::MultiCallbackUserDataPtr callback)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+    BluetoothHealthProfileHandlerCallback::syncToAsyncUnregisterCB(callback,
+        appID);
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+void BluetoothHealthProfileHandler::returnUnregisteringAppResult(
+    std::string appID, Common::MultiCallbackUserDataPtr callback)
+{
+    if (!callback) {
+        LOGE("callback is null");
+        return;
+    }
+
+    auto iter = mRegisteredHealthAppMap.find(appID);
+    BluetoothHealthApplicationSharedPtr application;
+    if(iter != mRegisteredHealthAppMap.end()) {
+        LOGE("registered Health Application is found");
+        application = iter->second;
+    }
+    else {
+        LOGD("Already unregistered");
+        callback->invokeCallback("success");
+        return;
+    }
+
+    try {
+        int ret = bt_hdp_unregister_sink_app(appID.c_str());
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%s", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_hdp_unregister_sink_app failed");
+        }
+
+        mRegisteredHealthAppMap.erase(iter);
+        application->setRegistrationState(false);
+        callback->invokeCallback("success");
+
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        callback->invokeCallback("error",
+            JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), e));
+    }
+}
+
+void BluetoothHealthProfileHandler::connectToSource(JSObjectRef remoteDeviceObj,
+    JSObjectRef appObj, Common::MultiCallbackUserDataPtr callback)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    BluetoothDeviceSharedPtr device =
+        JSBluetoothDevice::toBluetoothDevice(remoteDeviceObj);
+    BluetoothHealthApplicationSharedPtr app =
+        JSBluetoothHealthApplication::toBluetoothHealthApplication(appObj);
+
+    LOGD("address: %s", device->getAddress().c_str());
+    LOGD("app ID: %s", app->getAppID().c_str());
+
+    try {
+        int ret = bt_hdp_connect_to_source(device->getAddress().c_str(),
+            app->getAppID().c_str());
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_hdp_connect_to_source failed");
+        }
+
+        HealthConnReqPtr connReq = new HealthConnReq(device, callback);
+        mHealthConnReqMap.insert(
+            std::pair<BluetoothHealthApplicationSharedPtr, HealthConnReqPtr>(
+                app, connReq));
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothHealthProfileHandlerCallback::syncToAsyncErrorCB(callback, e);
+    }
+    TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothHealthProfileHandler.h b/src/Bluetooth/BluetoothHealthProfileHandler.h
new file mode 100644 (file)
index 0000000..4e086e8
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_HEALTH_PROFILE_HANDLER_H__
+#define __TIZEN_HEALTH_PROFILE_HANDLER_H__
+
+#include <string>
+#include <map>
+#include <vector>
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <bluetooth.h>
+
+#include "BluetoothHealthChannel.h"
+#include "BluetoothHealthApplication.h"
+#include "BluetoothDevice.h"
+
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class HealthConnReq
+{
+public:
+    HealthConnReq(BluetoothDeviceSharedPtr remoteDevice,
+        Common::MultiCallbackUserDataPtr userData)
+    {
+        mRemoteDevice = remoteDevice;
+        mUserData = userData;
+    };
+
+    BluetoothDeviceSharedPtr mRemoteDevice;
+    Common::MultiCallbackUserDataPtr mUserData;
+};
+typedef HealthConnReq* HealthConnReqPtr;
+
+class BluetoothHealthProfileHandler : public Common::SecurityAccessor
+{
+public:
+    static BluetoothHealthProfileHandler* getInstance();
+    void registerSinkApp(unsigned short dataType, std::string name,
+        Common::MultiCallbackUserDataPtr callback);
+    void returnRegisteringSinkAppResult(unsigned short dataType,
+        std::string name, Common::MultiCallbackUserDataPtr callback);
+    void unregisterApp(std::string appID,
+        Common::MultiCallbackUserDataPtr callback);
+    void returnUnregisteringAppResult(std::string appID,
+        Common::MultiCallbackUserDataPtr callback);
+    void connectToSource(JSObjectRef remoteDeviceObj, JSObjectRef appObj,
+        Common::MultiCallbackUserDataPtr callback);
+
+private:
+    BluetoothHealthProfileHandler();
+    virtual ~BluetoothHealthProfileHandler();
+
+    static void onConnected(int result, const char *remote_address,
+        const char *app_id, bt_hdp_channel_type_e type, unsigned int channel,
+        void *userData);
+    static void onDisconnected(int result, const char *remote_address,
+        unsigned int channel, void *userData);
+    static void onDataReceivedCB(unsigned int channel, const char *data,
+        unsigned int size, void *userData);
+
+    typedef std::map<BluetoothHealthApplicationSharedPtr, HealthConnReqPtr>
+        HealthConnReqMapT;
+
+    // <channel, BluetoothHealthChannelPtr>
+    typedef std::map<unsigned int, BluetoothHealthChannelPtr>
+        HealthConnectedSocketMapT;
+
+    // <app_id, BluetoothHealthApplicationSharedPtr>
+    typedef std::map<std::string, BluetoothHealthApplicationSharedPtr>
+        RegisteredHealthAppMapT;
+
+    HealthConnReqMapT mHealthConnReqMap;
+    HealthConnectedSocketMapT mConnectedSocketMap;
+    RegisteredHealthAppMapT mRegisteredHealthAppMap;
+};
+
+typedef BluetoothHealthProfileHandler* HealthProfileHandlerPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_HEALTH_PROFILE_HANDLER_H__
diff --git a/src/Bluetooth/BluetoothHealthProfileHandlerCallback.cpp b/src/Bluetooth/BluetoothHealthProfileHandlerCallback.cpp
new file mode 100644 (file)
index 0000000..198a59b
--- /dev/null
@@ -0,0 +1,117 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Ecore.h>
+
+#include <JSUtil.h>
+#include <Logger.h>
+
+#include "BluetoothHealthProfileHandlerCallback.h"
+#include "BluetoothHealthProfileHandler.h"
+
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+
+class HealthProfileHandlerCallbackData
+{
+public:
+    HealthProfileHandlerCallbackData(MultiCallbackUserDataPtr callback,
+        unsigned short dataType, std::string name)
+    {
+        mCallback = callback;
+        mDataType = dataType;
+        mName = name;
+        mIsRegistering = true;
+    };
+
+    HealthProfileHandlerCallbackData(MultiCallbackUserDataPtr callback,
+        std::string appID)
+    {
+        mCallback = callback;
+        mAppID = appID;
+        mIsRegistering = false;
+    };
+
+    virtual ~HealthProfileHandlerCallbackData()
+    {
+    };
+
+    MultiCallbackUserDataPtr mCallback;
+    unsigned short mDataType;
+    std::string mName;
+    std::string mAppID;
+    bool mIsRegistering;
+};
+
+typedef HealthProfileHandlerCallbackData* HealthProfileHandlerCallbackDataPtr;
+
+
+static Eina_Bool idlerCallback(void *userData){
+    HealthProfileHandlerCallbackDataPtr data =
+        static_cast<HealthProfileHandlerCallbackDataPtr>(userData);
+
+    if(!data) {
+        LOGW("BluetoothCallbackDataPtr is NULL");
+        return false;
+    }
+
+    if(!(data->mCallback)) {
+        LOGW("MulticallbackUserData is NULL");
+        delete data;
+        return false;
+    }
+
+    if(data->mIsRegistering) {  // registerSinkApplication
+        LOGD("In case of registerSinkApplication");
+        BluetoothHealthProfileHandler::getInstance()->
+            returnRegisteringSinkAppResult(data->mDataType, data->mName,
+                data->mCallback);
+    }
+    else {  // unregisterSinkApplication
+        LOGD("In case of unregisterSinkApplication");
+        BluetoothHealthProfileHandler::getInstance()->
+            returnUnregisteringAppResult(data->mAppID, data->mCallback);
+    }
+
+    delete data;
+    return false;
+}
+
+void BluetoothHealthProfileHandlerCallback::syncToAsyncRegisterCB(
+    MultiCallbackUserDataPtr callback,
+    unsigned short dataType, std::string name)
+{
+    HealthProfileHandlerCallbackDataPtr data =
+        new HealthProfileHandlerCallbackData(callback, dataType, name);
+    ecore_idler_add(idlerCallback, data);
+}
+
+void BluetoothHealthProfileHandlerCallback::syncToAsyncUnregisterCB(
+    MultiCallbackUserDataPtr callback, std::string appID)
+{
+    HealthProfileHandlerCallbackDataPtr data =
+        new HealthProfileHandlerCallbackData(callback, appID);
+    ecore_idler_add(idlerCallback, data);
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothHealthProfileHandlerCallback.h b/src/Bluetooth/BluetoothHealthProfileHandlerCallback.h
new file mode 100644 (file)
index 0000000..036dcf3
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_HEALTH_PROFILE_HANDLER_CALLBACK_H__
+#define __TIZEN_HEALTH_PROFILE_HANDLER_CALLBACK_H__
+
+#include <string>
+#include <MultiCallbackUserData.h>
+#include <JavaScriptCore/JavaScript.h>
+
+#include "BluetoothCallback.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+
+class BluetoothHealthProfileHandlerCallback : public BluetoothCallback
+{
+public:
+    static void syncToAsyncRegisterCB(
+        DeviceAPI::Common::MultiCallbackUserDataPtr callback,
+        unsigned short dataType, std::string name);
+    static void syncToAsyncUnregisterCB(
+        DeviceAPI::Common::MultiCallbackUserDataPtr callback,
+        std::string appID);
+};
+
+} // Bluetooth
+} // DeviceAPI
+
+
+
+#endif // __TIZEN_HEALTH_PROFILE_HANDLER_CALLBACK_H__
diff --git a/src/Bluetooth/BluetoothServiceHandler.cpp b/src/Bluetooth/BluetoothServiceHandler.cpp
new file mode 100644 (file)
index 0000000..77ac99b
--- /dev/null
@@ -0,0 +1,150 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+#include "BluetoothServiceHandler.h"
+#include "BluetoothAdapter.h"
+#include "BluetoothCallbackUtil.h"
+#include "BluetoothUtil.h"
+#include "plugin_config.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothServiceHandler::BluetoothServiceHandler(std::string uuid,
+    std::string name, int registeredSocket)
+{
+    Common::SecurityAccessor();
+
+    mUUID = uuid;
+    mName = name;
+    mRegisteredSocket = registeredSocket;
+    mIsRegistered = true;
+    mIsConnected = false;
+}
+
+BluetoothServiceHandler::~BluetoothServiceHandler()
+{
+    if(mIsRegistered) {
+        BluetoothAdapter::getInstance()->unregisterUUID(mUUID);
+        int ret = bt_socket_destroy_rfcomm(mRegisteredSocket);
+        if(ret != BT_ERROR_NONE) {
+            LOGW("Already destroyed %d", ret);
+        }
+    }
+}
+
+bool BluetoothServiceHandler::setOnConnect(JSContextRef context,
+    JSObjectRef onConnect)
+{
+    MultiCallbackUserDataPtr callback(
+        new MultiCallbackUserData(GlobalContextManager::getInstance()->
+            getGlobalContext(context)));
+    if(!callback){
+        LOGW("Can't create MultiCallbackUserData");
+        return false;
+    }
+    callback->setCallback("onconnect", onConnect);
+    mOnConnect = callback;
+
+    return mLocalProperty.setProperty(context,
+        BLUETOOTH_SERVICE_HANDLER_ONCONNECT, onConnect);
+}
+
+std::string BluetoothServiceHandler::getUUID() const
+{
+    return mUUID;
+}
+
+std::string BluetoothServiceHandler::getName() const
+{
+    return mName;
+}
+
+int BluetoothServiceHandler::getRegisteredSocket() const
+{
+    return mRegisteredSocket;
+}
+
+MultiCallbackUserDataPtr BluetoothServiceHandler::getOnConnect() const
+{
+    return mOnConnect;
+}
+
+JSValueRef BluetoothServiceHandler::getOnConnect(JSContextRef context)
+{
+    JSValueRef onConnect = mLocalProperty.getProperty(context,
+        BLUETOOTH_SERVICE_HANDLER_ONCONNECT);
+    if(onConnect == NULL) {
+        LOGD("onconnect is null");
+        return JSValueMakeNull(context);
+    }
+
+    return onConnect;
+}
+
+void BluetoothServiceHandler::setConnectionState(bool isConnected)
+{
+    mIsConnected = isConnected;
+}
+
+bool BluetoothServiceHandler::getConnectionState() const
+{
+    return mIsConnected;
+}
+
+void BluetoothServiceHandler::unregister(MultiCallbackUserDataPtr userData)
+{
+    if (!BluetoothAdapter::getInstance()->getPowered()) {
+        LOGE("Bluetooth device is turned off");
+        ServiceNotAvailableException e("Bluetooth device is turned off");
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+        return;
+    }
+
+    int ret = 0;
+
+    TIME_TRACER_ITEM_BEGIN("unregister::bt_socket_destroy_rfcomm", 1);
+    ret = bt_socket_destroy_rfcomm(mRegisteredSocket);
+    TIME_TRACER_ITEM_END("unregister::bt_socket_destroy_rfcomm", 1);
+
+    try {
+        if (ret != BT_ERROR_NONE) {
+            LOGE("%d", ret);
+            BluetoothUtil::throwBluetoothException(ret,
+                "bt_socket_destroy_rfcomm failed");
+        }
+
+        mIsRegistered = false;
+        BluetoothAdapter::getInstance()->unregisterUUID(mUUID);
+        BluetoothCallbackUtil::syncToAsyncSuccessCallback(userData);
+
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        BluetoothCallbackUtil::syncToAsyncErrorCallback(userData, e);
+    }
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothServiceHandler.h b/src/Bluetooth/BluetoothServiceHandler.h
new file mode 100644 (file)
index 0000000..3bf064d
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_SERVICE_HANDLER_H__
+#define __TIZEN_BLUETOOTH_SERVICE_HANDLER_H__
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+//#include <boost/shared_ptr.hpp>
+#include <MultiCallbackUserData.h>
+#include <PropertyBag.h>
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothServiceHandler : public Common::SecurityAccessor
+{
+public:
+    BluetoothServiceHandler(std::string uuid, std::string name, int registeredSocket);
+    virtual ~BluetoothServiceHandler();
+
+    std::string getUUID() const;
+    std::string getName() const;
+    int getRegisteredSocket() const;
+    bool getConnectionState() const;
+    Common::MultiCallbackUserDataPtr getOnConnect() const;
+    JSValueRef getOnConnect(JSContextRef context);
+
+    void setConnectionState(bool isConnected);
+    bool setOnConnect(JSContextRef context, JSObjectRef onConnect);
+
+    void unregister(Common::MultiCallbackUserDataPtr userData);
+
+private:
+    std::string mUUID;
+    std::string mName;
+    int mRegisteredSocket;
+    bool mIsConnected;
+    bool mIsRegistered;
+    Common::MultiCallbackUserDataPtr mOnConnect;
+    Common::PropertyBag mLocalProperty;
+};
+
+typedef BluetoothServiceHandler* BluetoothServiceHandlerPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_SERVICE_HANDLER_H__
diff --git a/src/Bluetooth/BluetoothSocket.cpp b/src/Bluetooth/BluetoothSocket.cpp
new file mode 100755 (executable)
index 0000000..2bc6245
--- /dev/null
@@ -0,0 +1,273 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+#include "BluetoothSocket.h"
+#include "BluetoothAdapter.h"
+#include "BluetoothUtil.h"
+#include "plugin_config.h"
+#include "JSBluetoothDevice.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+BluetoothSocket::BluetoothSocket(bt_socket_connection_s *connection,
+    Common::SecurityAccessor* accessor)
+{
+    Common::SecurityAccessor();
+    Common::SecurityAccessor::copyAceCheckAccessFunction(accessor);
+
+    mConnectedSocket = connection->socket_fd;
+    mUUID = std::string(connection->service_uuid);
+    mIsConnected = true;
+
+    bt_device_info_s *deviceInfo = NULL;
+    int ret = 0;
+    ret = bt_adapter_get_bonded_device_info(connection->remote_address,
+        &deviceInfo);
+    if (!deviceInfo) {
+        LOGE("deviceInfo is null");
+        throw UnknownException("deviceInfo is null");
+    }
+
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_adapter_get_bonded_device_info failed");
+    }
+
+    BluetoothDeviceSharedPtr device(new BluetoothDevice(deviceInfo));
+    device->copyAceCheckAccessFunction(accessor);
+    mPeer = device;
+
+    ret = bt_adapter_free_device_info(deviceInfo);
+    if (ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_adapter_free_device_info failed");
+    }
+}
+
+BluetoothSocket::~BluetoothSocket()
+{
+    if(mIsConnected) {
+        int ret = 0;
+
+        ret = bt_socket_disconnect_rfcomm(mConnectedSocket);
+        if(ret != BT_ERROR_NONE) {
+            LOGE("Already disconnected: %d", ret);
+        }
+
+        if(!BluetoothAdapter::getInstance()->closeConnectedSocket(
+            mConnectedSocket)) {
+
+            LOGE("Already done");
+        }
+    }
+}
+
+bool BluetoothSocket::setOnMessage(JSContextRef context, JSObjectRef onMessage)
+{
+    MultiCallbackUserDataPtr callback(
+        new MultiCallbackUserData(GlobalContextManager::getInstance()->
+            getGlobalContext(context)));
+
+    if (!callback){
+        LOGW("Can't create MultiCallbackUserData");
+        return false;
+    }
+    callback->setCallback("onmessage", onMessage);
+    mOnMessage = callback;
+
+    return mLocalProperty.setProperty(context, BLUETOOTH_SOCKET_ONMESSAGE,
+        onMessage);
+}
+
+bool BluetoothSocket::setOnClose(JSContextRef context, JSObjectRef onClose)
+{
+    MultiCallbackUserDataPtr callback(
+        new MultiCallbackUserData(GlobalContextManager::getInstance()->
+            getGlobalContext(context)));
+
+    if(!callback){
+        LOGW("Can't create MultiCallbackUserData");
+        return false;
+    }
+    callback->setCallback("onclose", onClose);
+    mOnClose = callback;
+
+    return mLocalProperty.setProperty(context, BLUETOOTH_SOCKET_ONCLOSE,
+        onClose);
+}
+
+bool BluetoothSocket::setOnError(JSContextRef context, JSObjectRef onError)
+{
+    MultiCallbackUserDataPtr callback(
+        new MultiCallbackUserData(GlobalContextManager::getInstance()->
+            getGlobalContext(context)));
+
+    if(!callback){
+        LOGW("Can't create MultiCallbackUserData");
+        return false;
+    }
+    callback->setCallback("onerror", onError);
+    mOnError = callback;
+
+    return mLocalProperty.setProperty(context, BLUETOOTH_SOCKET_ONERROR,
+        onError);
+}
+
+std::string BluetoothSocket::getUUID() const
+{
+    return mUUID;
+}
+
+void BluetoothSocket::setConnectionState(bool isConnected)
+{
+    mIsConnected = isConnected;
+}
+
+bool BluetoothSocket::getConnectionState()
+{
+    return mIsConnected;
+}
+
+JSValueRef BluetoothSocket::getPeer(JSContextRef context)
+{
+    return JSBluetoothDevice::createJSObject(context, mPeer);
+}
+
+MultiCallbackUserDataPtr BluetoothSocket::getOnMessage() const
+{
+    return mOnMessage;
+}
+
+JSValueRef BluetoothSocket::getOnMessage(JSContextRef context)
+{
+    JSValueRef onMessage = mLocalProperty.getProperty(context,
+        BLUETOOTH_SOCKET_ONMESSAGE);
+    if(onMessage == NULL) {
+        LOGD("onmessage is null");
+        return JSValueMakeNull(context);
+    }
+
+    return onMessage;
+}
+
+MultiCallbackUserDataPtr BluetoothSocket::getOnClose() const
+{
+    return mOnClose;
+}
+
+JSValueRef BluetoothSocket::getOnClose(JSContextRef context)
+{
+    JSValueRef onClose = mLocalProperty.getProperty(context,
+        BLUETOOTH_SOCKET_ONCLOSE);
+    if(onClose == NULL) {
+        LOGD("onclose is null");
+        return JSValueMakeNull(context);
+    }
+
+    return onClose;
+}
+
+MultiCallbackUserDataPtr BluetoothSocket::getOnError() const
+{
+    return mOnError;
+}
+
+JSValueRef BluetoothSocket::getOnError(JSContextRef context)
+{
+    JSValueRef onError = mLocalProperty.getProperty(context,
+        BLUETOOTH_SOCKET_ONERROR);
+    if(onError == NULL) {
+        LOGD("onerror is null");
+        return JSValueMakeNull(context);
+    }
+
+    return onError;
+}
+
+unsigned long BluetoothSocket::writeData(char* data, unsigned long size)
+{
+    int ret = 0;
+
+    TIME_TRACER_ITEM_BEGIN("writeData::bt_socket_send_data", 1);
+    LOGD("Enter %d", mConnectedSocket);
+    ret = bt_socket_send_data(mConnectedSocket, data, static_cast<int>(size));
+    TIME_TRACER_ITEM_END("writeData::bt_socket_send_data", 1);
+    if (ret < 0) {
+        LOGD("Enter %d", ret);
+        throw UnknownException("Unknown error");
+    }
+    else {
+        TIME_TRACER_ITEM_END("writeData::bt_socket_send_data", 1);
+        LOGD("bt_socket_send_data() succeeded");
+    }
+
+    return static_cast<unsigned long>(ret);
+}
+
+void BluetoothSocket::storeRecivedData(char *data, unsigned long size)
+{
+    for(unsigned long i = 0; i < size; i++) {
+        mReceivedData.push_back(static_cast<signed char>(data[i]));
+    }
+}
+
+std::vector<signed char> BluetoothSocket::readData()
+{
+    std::vector<signed char> result (mReceivedData);
+    mReceivedData.clear();
+    LOGD("Enter %d", mConnectedSocket);
+
+    return result;
+}
+
+void BluetoothSocket::close()
+{
+    LOGD("enter");
+    int ret = BT_ERROR_NONE;
+    if(!mIsConnected) {
+        LOGD("Already disconnected");
+        return;
+    }
+
+    LOGD("Already disconnected %d", mConnectedSocket);
+
+    TIME_TRACER_ITEM_BEGIN("close::bt_socket_disconnect_rfcomm", 1);
+    ret = bt_socket_disconnect_rfcomm(mConnectedSocket);
+    TIME_TRACER_ITEM_END("close::bt_socket_disconnect_rfcomm", 1);
+
+    if(ret != BT_ERROR_NONE) {
+        LOGE("%d", ret);
+        BluetoothUtil::throwBluetoothException(ret,
+            "bt_socket_disconnect_rfcomm failed");
+    }
+
+    mIsConnected = false;
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothSocket.h b/src/Bluetooth/BluetoothSocket.h
new file mode 100644 (file)
index 0000000..b72bde3
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_SOCKET_H__
+#define __TIZEN_BLUETOOTH_SOCKET_H__
+
+#include <string>
+#include <bluetooth.h>
+#include <JavaScriptCore/JavaScript.h>
+
+//#include <boost/shared_ptr.hpp>
+#include <MultiCallbackUserData.h>
+#include <PropertyBag.h>
+#include <Security.h>
+#include "BluetoothDevice.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothSocket : public Common::SecurityAccessor
+{
+public:
+    BluetoothSocket(bt_socket_connection_s *connection,
+        Common::SecurityAccessor* accessor);
+    virtual ~BluetoothSocket();
+
+    std::string getUUID() const;
+    bool getConnectionState();
+    JSValueRef getPeer(JSContextRef context);
+    Common::MultiCallbackUserDataPtr getOnMessage() const;
+    JSValueRef getOnMessage(JSContextRef context);
+    Common::MultiCallbackUserDataPtr getOnClose() const;
+    JSValueRef getOnClose(JSContextRef context);
+    Common::MultiCallbackUserDataPtr getOnError() const;
+    JSValueRef getOnError(JSContextRef context);
+    bool setOnMessage(JSContextRef context, JSObjectRef onMessage);
+    bool setOnClose(JSContextRef context, JSObjectRef onClose);
+    bool setOnError(JSContextRef context, JSObjectRef onError);
+    void storeRecivedData(char *data, unsigned long size);
+    void setConnectionState(bool isConnected);
+
+    unsigned long writeData(char* data, unsigned long size);
+    std::vector<signed char> readData();
+    void close();
+
+private:
+    std::string mUUID;
+    int mConnectedSocket;
+    bool mIsConnected;
+    BluetoothDeviceSharedPtr mPeer;
+    std::vector<signed char> mReceivedData;
+    Common::MultiCallbackUserDataPtr mOnMessage;
+    Common::MultiCallbackUserDataPtr mOnClose;
+    Common::MultiCallbackUserDataPtr mOnError;
+    Common::PropertyBag mLocalProperty;
+};
+
+typedef BluetoothSocket* BluetoothSocketPtr;
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_BLUETOOTH_SOCKET_H__
diff --git a/src/Bluetooth/BluetoothUtil.cpp b/src/Bluetooth/BluetoothUtil.cpp
new file mode 100644 (file)
index 0000000..572d512
--- /dev/null
@@ -0,0 +1,107 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "BluetoothUtil.h"
+
+#include <sstream>
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+void BluetoothUtil::throwBluetoothException(const int error_code,
+    const std::string &hint)
+{
+    std::stringstream ss;
+    ss << hint << " : " << getBluetoothErrorMessage(error_code);
+    LOGE("%s", ss.str().c_str());
+
+    switch (error_code) {
+        case BT_ERROR_RESOURCE_BUSY:
+            throw ServiceNotAvailableException(ss.str().c_str());
+        case BT_ERROR_REMOTE_DEVICE_NOT_FOUND:
+            throw NotFoundException(ss.str().c_str());
+        case BT_ERROR_INVALID_PARAMETER:
+            throw InvalidValuesException(ss.str().c_str());
+        case BT_ERROR_NOW_IN_PROGRESS:
+            throw ServiceNotAvailableException(ss.str().c_str());
+        case BT_ERROR_NOT_ENABLED:
+            throw ServiceNotAvailableException(ss.str().c_str());
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+std::string BluetoothUtil::getBluetoothErrorMessage(const int error_code)
+{
+    switch (error_code)
+    {
+        case BT_ERROR_CANCELLED:
+            return "Operation cancelled";
+        case BT_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case BT_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case BT_ERROR_RESOURCE_BUSY:
+            return "Bluetooth device is busy";
+        case BT_ERROR_TIMED_OUT:
+            return "Timeout error";
+        case BT_ERROR_NOW_IN_PROGRESS:
+            return "Operation now in progress";
+        case BT_ERROR_NOT_SUPPORTED:
+            return "Not Supported";
+        case BT_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case BT_ERROR_QUOTA_EXCEEDED:
+            return "Quota exceeded";
+        case BT_ERROR_NOT_INITIALIZED:
+            return "Local adapter not initialized";
+        case BT_ERROR_NOT_ENABLED:
+            return "Local adapter not enabled";
+        case BT_ERROR_ALREADY_DONE:
+            return "Operation already done";
+        case BT_ERROR_OPERATION_FAILED:
+            return "Operation failed";
+        case BT_ERROR_NOT_IN_PROGRESS:
+            return "Operation not in progress";
+        case BT_ERROR_REMOTE_DEVICE_NOT_BONDED:
+            return "Remote device not bonded";
+        case BT_ERROR_AUTH_REJECTED:
+            return "Authentication rejected";
+        case BT_ERROR_AUTH_FAILED:
+            return "Authentication failed";
+        case BT_ERROR_REMOTE_DEVICE_NOT_FOUND:
+            return "Remote device not found";
+        case BT_ERROR_SERVICE_SEARCH_FAILED:
+            return "Service search failed";
+        case BT_ERROR_REMOTE_DEVICE_NOT_CONNECTED:
+            return "Remote device is not connected";
+        case BT_ERROR_AGAIN:
+            return "Resource temporarily unavailable";
+        case BT_ERROR_SERVICE_NOT_FOUND:
+            return "Service Not Found";
+        default:
+            return "Unknown Error";
+    }
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/BluetoothUtil.h b/src/Bluetooth/BluetoothUtil.h
new file mode 100644 (file)
index 0000000..afc605a
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BLUETOOTH_BLUETOOTH_UTIL_H_
+#define __TIZEN_BLUETOOTH_BLUETOOTH_UTIL_H_
+
+#include <string>
+#include <bluetooth.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothUtil {
+public:
+    static void throwBluetoothException(const int errorCode,
+        const std::string &hint);
+    static std::string getBluetoothErrorMessage(const int errorCode);
+};
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_ACCOUNT_UTIL_H_
diff --git a/src/Bluetooth/CMakeLists.txt b/src/Bluetooth/CMakeLists.txt
new file mode 100644 (file)
index 0000000..9f81a9c
--- /dev/null
@@ -0,0 +1,80 @@
+SET(TARGET_NAME ${bluetooth_target})
+SET(DESTINATION_NAME ${bluetooth_dest})
+SET(TARGET_IMPL_NAME ${bluetooth_impl})
+
+IF(ENABLE_OPTIONAL_BT)
+PKG_CHECK_MODULES(platform_pkgs_bluetooth REQUIRED
+    capi-appfw-application
+    capi-network-bluetooth
+    capi-system-info
+)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${TOP}/Bluetooth
+    ${platform_pkgs_bluetooth_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSBluetoothManager.cpp
+    JSBluetoothAdapter.cpp
+    JSBluetoothDevice.cpp
+    JSBluetoothSocket.cpp
+    JSBluetoothClass.cpp
+    JSBluetoothClassDeviceMajor.cpp
+    JSBluetoothClassDeviceMinor.cpp
+    JSBluetoothClassDeviceService.cpp
+    JSBluetoothServiceHandler.cpp
+    JSBluetoothHealthApplication.cpp
+    JSBluetoothHealthChannel.cpp
+    JSBluetoothProfileHandler.cpp
+    JSBluetoothHealthProfileHandler.cpp
+    BluetoothAdapter.cpp
+    BluetoothDevice.cpp
+    BluetoothSocket.cpp
+    BluetoothClass.cpp
+    BluetoothClassDeviceMajor.cpp
+    BluetoothClassDeviceMinor.cpp
+    BluetoothClassDeviceService.cpp
+    BluetoothServiceHandler.cpp
+    BluetoothCallbackUtil.cpp
+    BluetoothCallback.cpp
+    BluetoothHealthApplication.cpp
+    BluetoothHealthChannel.cpp
+    BluetoothHealthProfileHandlerCallback.cpp
+    BluetoothHealthProfileHandler.cpp
+    BluetoothUtil.cpp
+)
+
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${platform_pkgs_bluetooth_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_BT)
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/bluetooth
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Bluetooth/JSBluetoothAdapter.cpp b/src/Bluetooth/JSBluetoothAdapter.cpp
new file mode 100644 (file)
index 0000000..2a1686c
--- /dev/null
@@ -0,0 +1,958 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothAdapter.h"
+#include "BluetoothAdapter.h"
+#include "BluetoothHealthProfileHandler.h"
+#include "JSBluetoothHealthProfileHandler.h"
+
+#include <system_info.h>
+#include <TimeTracer.h>
+#include <Logger.h>
+#include "plugin_config_impl.h"
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothAdapter::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothAdapter",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothAdapter::m_property[] = {
+    {
+        BLUETOOTH_ADAPTER_NAME,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_ADAPTER_POWERED,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_ADAPTER_VISIBLE,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_ADAPTER_ADDRESS,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothAdapter::m_function[] = {
+    {
+        BLUETOOTH_ADAPTER_API_SET_NAME,
+        setName,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_SET_POWERED,
+        setPowered,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_SET_VISIBLE,
+        setVisible,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES,
+        discoverDevices,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_STOP_DISCOVERY,
+        stopDiscovery,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES,
+        getKnownDevices,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_GET_DEVICE,
+        getDevice,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_CREATE_BONDING,
+        createBonding,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_DESTROY_BONDING,
+        destroyBonding,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID,
+        registerRFCOMMServiceByUUID,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_GET_BLUETOOTH_PROFILE_HANDLER,
+        getBluetoothProfileHandler,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER,
+        setChangeListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER,
+        unsetChangeListener,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothAdapter::m_jsClassRef =
+    JSClassCreate(JSBluetoothAdapter::getClassInfo());
+
+const JSClassRef JSBluetoothAdapter::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothAdapter::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothAdapter::createJSObject(JSContextRef context)
+{
+    return JSObjectMake(context, getClassRef(), NULL);
+}
+
+void JSBluetoothAdapter::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+
+void JSBluetoothAdapter::finalize(JSObjectRef object)
+{
+    // do nothing
+}
+
+JSValueRef JSBluetoothAdapter::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_ADAPTER_NAME)) {
+            std::string name = BluetoothAdapter::getInstance()->getName();
+            return JSUtil::toJSValueRef(context, name);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_ADAPTER_POWERED)) {
+            return JSUtil::toJSValueRef(context,
+                BluetoothAdapter::getInstance()->getPowered());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_ADAPTER_VISIBLE)) {
+            return JSUtil::toJSValueRef(context,
+                BluetoothAdapter::getInstance()->getVisible());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_DEVICE_ADDRESS)) {
+            std::string address = BluetoothAdapter::getInstance()->getAddress();
+            return JSUtil::toJSValueRef(context, address);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+JSValueRef JSBluetoothAdapter::setName(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("setName::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_SET_NAME);
+    TIME_TRACER_ITEM_END("setName::ACE", 1);
+
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // name
+        std::string name = validator.toString(0);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(1, true);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->setName(name, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.setName().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::setPowered(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("setPowered::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_SET_POWERED);
+    TIME_TRACER_ITEM_END("setPowered::ACE", 1);
+
+    try {
+        // Check whether BT is supported or not
+        bool supported = false;
+        if(system_info_get_platform_bool("tizen.org/feature/network.bluetooth",
+            &supported) != SYSTEM_INFO_ERROR_NONE) {
+            LOGW("Can't check BT is supported or not");
+        }
+
+        if(supported == false) {
+            LOGW("BT is not supported");
+            throw NotSupportedException("Bluetooth is not supported");
+        }
+        else {
+            LOGD("BT is supported");
+        }
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // state
+        bool state = validator.toBool(0);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(1, true);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+           new MultiCallbackUserData(GlobalContextManager::getInstance()->
+            getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->setPowered(state, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.setPowered().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::setVisible(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("setVisible::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_SET_VISIBLE);
+    TIME_TRACER_ITEM_END("setVisible::ACE", 1);
+
+
+    try {
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // mode
+        bool mode = validator.toBool(0);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(1, true);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+
+        // timeout
+        unsigned long timeout = validator.toULong(3, true, 180);
+        if(timeout > 65535)
+            timeout = 180;
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->setVisible(mode, timeout, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException
+            err("Unknown Error in BluetoothAdapter.setVisible().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::discoverDevices(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("discoverDevices::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES);
+    TIME_TRACER_ITEM_END("discoverDevices::ACE", 1);
+
+
+    try {
+        TIME_TRACER_ITEM_BEGIN("discoverDevices::parameter", 1);
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toCallbackObject(0, false,
+            "onstarted", "ondevicefound", "ondevicedisappeared", "onfinished",
+            NULL);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);
+
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiMultiCallbackUserData");
+        }
+        else {
+            // onstarted
+            JSValueRef onstartedValue = JSUtil::getProperty(context,
+                successCallback, "onstarted");
+            if(!JSValueIsUndefined(context, onstartedValue)) {
+                LOGD("There is a onstarted()");
+                callback->setCallback("onstarted",
+                    JSUtil::JSValueToObject(context, onstartedValue));
+            }
+
+            // ondevicefound
+            JSValueRef ondevicefoundValue = JSUtil::getProperty(context,
+                successCallback, "ondevicefound");
+            if(!JSValueIsUndefined(context, ondevicefoundValue)) {
+                LOGD("There is a ondevicefound()");
+                callback->setCallback("ondevicefound",
+                    JSUtil::JSValueToObject(context, ondevicefoundValue));
+            }
+
+            // ondevicedisappeared
+            JSValueRef ondevicedisappearedValue = JSUtil::getProperty(context,
+                successCallback, "ondevicedisappeared");
+            if(!JSValueIsUndefined(context, ondevicedisappearedValue)) {
+                LOGD("There is a ondevicedisappeared()");
+                callback->setCallback("ondevicedisappeared",
+                    JSUtil::JSValueToObject(context, ondevicedisappearedValue));
+            }
+
+            // onfinished
+            JSValueRef onfinishedValue = JSUtil::getProperty(context,
+                successCallback, "onfinished");
+            if(!JSValueIsUndefined(context, onfinishedValue)) {
+                LOGD("There is a onfinished()");
+                callback->setCallback("onfinished",
+                    JSUtil::JSValueToObject(context, onfinishedValue));
+            }
+
+            callback->setCallback("error", errorCallback);
+        }
+        TIME_TRACER_ITEM_END("discoverDevices::parameter", 1);
+
+        // perform
+        BluetoothAdapter::getInstance()->discoverDevices(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.discoverDevices().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::stopDiscovery(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("stopDiscovery::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_STOP_DISCOVERY);
+    TIME_TRACER_ITEM_END("stopDiscovery::ACE", 1);
+
+    try {
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(0, true);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->stopDiscovery(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.stopDiscovery().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::getKnownDevices(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("getKnownDevices::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES);
+    TIME_TRACER_ITEM_END("getKnownDevices::ACE", 1);
+
+
+    try {
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(0);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->getKnownDevices(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.getKnownDevices().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::getDevice(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("getDevice::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_GET_DEVICE);
+    TIME_TRACER_ITEM_END("getDevice::ACE", 1);
+
+
+    try {
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // address
+        std::string address = validator.toString(0);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(1);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->getDevice(address, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown Error in BluetoothAdapter.getDevice().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::createBonding(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("createBonding::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_CREATE_BONDING);
+    TIME_TRACER_ITEM_END("createBonding::ACE", 1);
+
+
+    try {
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // address
+        std::string address = validator.toString(0);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(1);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->createBonding(address, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.createBonding().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::destroyBonding(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("destroyBonding::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_DESTROY_BONDING);
+    TIME_TRACER_ITEM_END("destroyBonding::ACE", 1);
+
+    try {
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // address
+        std::string address = validator.toString(0);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(1, true);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->destroyBonding(address, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.destroyBonding().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::registerRFCOMMServiceByUUID(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("registerRFCOMMServiceByUUID::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception, BluetoothAdapter::getInstance(),
+        BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID);
+    TIME_TRACER_ITEM_END("registerRFCOMMServiceByUUID::ACE", 1);
+
+
+    try {
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // uuid
+        std::string uuid = validator.toString(0);
+
+        // name
+        std::string name = validator.toString(1);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(2);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(3, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->
+            registerRFCOMMServiceByUUID(uuid, name, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.registerRFCOMMServiceByUUID().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::getBluetoothProfileHandler(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // profileType
+        std::string type = validator.toString(0);
+
+        // perform
+        JSObjectRef profileHandler;
+        bool isCorrectParameter = false;
+        if(type.compare("HEALTH") == 0) {
+            isCorrectParameter = true;
+            BluetoothHealthProfileHandler::getInstance()->
+                copyAceCheckAccessFunction(BluetoothAdapter::getInstance());
+
+            profileHandler =
+                JSBluetoothHealthProfileHandler::createJSObject(context);
+        }
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        if(!isCorrectParameter) {
+            throw TypeMismatchException("Type Mismatch");
+        }
+
+        return profileHandler;
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.registerRFCOMMServiceByUUID().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::setChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef changeCallbackObj = validator.toCallbackObject(0, false,
+            "onstatechanged", "onnamechanged", "onvisibilitychanged", NULL);
+
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiMultiCallbackUserData");
+        }
+        else {
+            // onstatechanged
+            JSValueRef onstatechangedValue = JSUtil::getProperty(context,
+                changeCallbackObj, "onstatechanged");
+            if(!JSValueIsUndefined(context, onstatechangedValue)) {
+                LOGD("There is a onstatechanged()");
+                callback->setCallback("onstatechanged",
+                    JSUtil::JSValueToObject(context, onstatechangedValue));
+            }
+
+            // onnamechanged
+            JSValueRef onnamechangedValue = JSUtil::getProperty(context,
+                changeCallbackObj, "onnamechanged");
+            if(!JSValueIsUndefined(context, onnamechangedValue)) {
+                LOGD("There is a onnamechanged()");
+                callback->setCallback("onnamechanged",
+                    JSUtil::JSValueToObject(context, onnamechangedValue));
+            }
+
+            // onvisibilitychanged
+            JSValueRef onvisibilitychangedValue = JSUtil::getProperty(context,
+                changeCallbackObj, "onvisibilitychanged");
+            if(!JSValueIsUndefined(context, onvisibilitychangedValue)) {
+                LOGD("There is a onvisibilitychanged()");
+                callback->setCallback("onvisibilitychanged",
+                    JSUtil::JSValueToObject(context, onvisibilitychangedValue));
+            }
+        }
+
+        // perform
+        BluetoothAdapter::getInstance()->setChangeListener(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.registerRFCOMMServiceByUUID().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothAdapter::unsetChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        // perform
+        BluetoothAdapter::getInstance()->unsetChangeListener();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.registerRFCOMMServiceByUUID().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothAdapter.h b/src/Bluetooth/JSBluetoothAdapter.h
new file mode 100644 (file)
index 0000000..f25a49f
--- /dev/null
@@ -0,0 +1,169 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_ADAPTER_H__
+#define __TIZEN_JS_BLUETOOTH_ADAPTER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothAdapter
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef setName(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setPowered(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setVisible(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef discoverDevices(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef stopDiscovery(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getKnownDevices(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getDevice(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef createBonding(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef destroyBonding(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef registerRFCOMMServiceByUUID(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getBluetoothProfileHandler(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Bluetooth/JSBluetoothClass.cpp b/src/Bluetooth/JSBluetoothClass.cpp
new file mode 100644 (file)
index 0000000..85c1d7f
--- /dev/null
@@ -0,0 +1,207 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+
+#include "JSBluetoothClass.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothClass::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothClass",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothClass::m_property[] = {
+    {
+        BLUETOOTH_CLASS_MAJOR,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_CLASS_MINOR,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_CLASS_SERVICES,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothClass::m_function[] = {
+    {
+        BLUETOOTH_CLASS_API_HAS_SERVICE,
+        hasService,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothClass::m_jsClassRef =
+    JSClassCreate(JSBluetoothClass::getClassInfo());
+
+const JSClassRef JSBluetoothClass::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothClass::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothClass::createJSObject(JSContextRef context,
+    BluetoothClassSharedPtr bluetoothClass)
+{
+    BluetoothClassHolderPtr holder = new BluetoothClassHolder(bluetoothClass);
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+}
+
+void JSBluetoothClass::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothClass::finalize(JSObjectRef object)
+{
+    BluetoothClassHolderPtr priv =
+        static_cast<BluetoothClassHolderPtr>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothClass::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothClassHolderPtr priv =
+            static_cast<BluetoothClassHolderPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_CLASS_MAJOR)) {
+            return JSUtil::toJSValueRef(context, priv->mClass->getMajor());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_CLASS_MINOR)) {
+            return JSUtil::toJSValueRef(context, priv->mClass->getMinor());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_CLASS_SERVICES)) {
+            return priv->mClass->getServices(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed: %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+JSValueRef JSBluetoothClass::hasService(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        // Private Object
+        BluetoothClassHolderPtr priv =
+            static_cast<BluetoothClassHolderPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+            // Access Check
+        BluetoothClass* btclass = priv->mClass.get();
+        TIME_TRACER_ITEM_BEGIN("hasService::ACE", 1);
+        TIZEN_CHECK_ACCESS(context, exception, btclass,
+            BLUETOOTH_CLASS_API_HAS_SERVICE);
+        TIME_TRACER_ITEM_END("hasService::ACE", 1);
+
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        unsigned long service = validator.toULong(0);  // uuid
+
+        JSValueRef result = JSUtil::toJSValueRef(context,
+            priv->mClass->hasService(service));
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return result;
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothClass.hasService().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothClass.h b/src/Bluetooth/JSBluetoothClass.h
new file mode 100644 (file)
index 0000000..2dc0057
--- /dev/null
@@ -0,0 +1,93 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_CLASS_H__
+#define __TIZEN_JS_BLUETOOTH_CLASS_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "BluetoothClass.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothClassHolder
+{
+public:
+    BluetoothClassHolder(BluetoothClassSharedPtr bluetoothClass) { mClass = bluetoothClass;}
+    BluetoothClassSharedPtr mClass;
+};
+typedef BluetoothClassHolder* BluetoothClassHolderPtr;
+
+class JSBluetoothClass
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothClassSharedPtr bluetoothClass);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef hasService(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Bluetooth/JSBluetoothClassDeviceMajor.cpp b/src/Bluetooth/JSBluetoothClassDeviceMajor.cpp
new file mode 100644 (file)
index 0000000..e00b57c
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSUtil.h>
+#include "plugin_config.h"
+#include "JSBluetoothClassDeviceMajor.h"
+#include "BluetoothClassDeviceMajor.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothClassDeviceMajor::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothClassDeviceMajor",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSClassRef JSBluetoothClassDeviceMajor::m_jsClassRef = JSClassCreate(JSBluetoothClassDeviceMajor::getClassInfo());
+
+JSStaticValue JSBluetoothClassDeviceMajor::m_property[] = {
+    { "MISC", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "COMPUTER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "PHONE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "NETWORK", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "AUDIO_VIDEO", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "PERIPHERAL", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "IMAGING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "WEARABLE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "TOY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "HEALTH", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+
+const JSClassRef JSBluetoothClassDeviceMajor::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothClassDeviceMajor::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothClassDeviceMajor::createJSObject(JSContextRef context)
+{
+    return JSObjectMake(context, getClassRef(), NULL);
+}
+
+void JSBluetoothClassDeviceMajor::initialize(JSContextRef context, JSObjectRef object)
+{
+    // Do nothing
+}
+
+void JSBluetoothClassDeviceMajor::finalize(JSObjectRef object)
+{
+    // Do nothing
+}
+
+JSValueRef JSBluetoothClassDeviceMajor::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        std::string name = JSUtil::JSStringToString(context, propertyName);
+        return JSUtil::toJSValueRef(context, BluetoothClassDeviceMajor::getInstance()->getMajorValue(name));
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed: %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothClassDeviceMajor.h b/src/Bluetooth/JSBluetoothClassDeviceMajor.h
new file mode 100644 (file)
index 0000000..b61d84f
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
+#define __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_MAJOR_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothClassDeviceMajor
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Bluetooth/JSBluetoothClassDeviceMinor.cpp b/src/Bluetooth/JSBluetoothClassDeviceMinor.cpp
new file mode 100644 (file)
index 0000000..e0a1baf
--- /dev/null
@@ -0,0 +1,175 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSUtil.h>
+#include "plugin_config.h"
+#include "JSBluetoothClassDeviceMinor.h"
+#include "BluetoothClassDeviceMinor.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothClassDeviceMinor::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothClassDeviceMinor",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+
+JSClassRef JSBluetoothClassDeviceMinor::m_jsClassRef = JSClassCreate(JSBluetoothClassDeviceMinor::getClassInfo());
+
+JSStaticValue JSBluetoothClassDeviceMinor::m_property[] = {
+    {"COMPUTER_UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_DESKTOP", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_SERVER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_LAPTOP", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_HANDHELD_PC_OR_PDA", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_PALM_PC_OR_PDA", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"COMPUTER_WEARABLE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_CELLULAR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_CORDLESS", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_SMARTPHONE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_MODEM_OR_GATEWAY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PHONE_ISDN", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_UNRECOGNIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_WEARABLE_HEADSET", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_HANDSFREE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_MICROPHONE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_LOUDSPEAKER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_HEADPHONES", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_PORTABLE_AUDIO", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_CAR_AUDIO", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_SETTOP_BOX", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_HIFI", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_VCR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_VIDEO_CAMERA", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_CAMCORDER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_DISPLAY_AND_LOUDSPEAKER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_VIDEO_CONFERENCING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"AV_GAMING_TOY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_KEYBOARD", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_POINTING_DEVICE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_KEYBOARD_AND_POINTING_DEVICE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_JOYSTICK", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_GAMEPAD", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_REMOTE_CONTROL", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_SENSING_DEVICE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_DEGITIZER_TABLET", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_CARD_READER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_DIGITAL_PEN", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_HANDHELD_SCANNER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"PERIPHERAL_HANDHELD_INPUT_DEVICE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_UNCATEGORIZED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_DISPLAY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_CAMERA", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_SCANNER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"IMAGING_PRINTER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_WRITST_WATCH", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_PAGER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_JACKET", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_HELMET", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"WEARABLE_GLASSES", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_ROBOT", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_VEHICLE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_DOLL", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_CONTROLLER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"TOY_GAME", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_UNDEFINED", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_BLOOD_PRESSURE_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_THERMOMETER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_WEIGHING_SCALE", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_GLUCOSE_METER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_PULSE_OXIMETER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_PULSE_RATE_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_DATA_DISPLAY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_STEP_COUNTER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_BODY_COMPOSITION_ANALYZER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_PEAK_FLOW_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_MEDICATION_MONITOR", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_KNEE_PROSTHESIS", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    {"HEALTH_ANKLE_PROSTHESIS", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef JSBluetoothClassDeviceMinor::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothClassDeviceMinor::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothClassDeviceMinor::createJSObject(JSContextRef context)
+{
+    return JSObjectMake(context, getClassRef(), NULL);
+}
+
+void JSBluetoothClassDeviceMinor::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothClassDeviceMinor::finalize(JSObjectRef object)
+{
+    // do nothing
+}
+
+JSValueRef JSBluetoothClassDeviceMinor::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        std::string name = JSUtil::JSStringToString(context, propertyName);
+        return JSUtil::toJSValueRef(context, BluetoothClassDeviceMinor::getInstance()->getMinorValue(name));
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed: %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothClassDeviceMinor.h b/src/Bluetooth/JSBluetoothClassDeviceMinor.h
new file mode 100644 (file)
index 0000000..1877cc5
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_MINOR_H__
+#define __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_MINOR_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothClassDeviceMinor
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Bluetooth/JSBluetoothClassDeviceService.cpp b/src/Bluetooth/JSBluetoothClassDeviceService.cpp
new file mode 100644 (file)
index 0000000..6e990df
--- /dev/null
@@ -0,0 +1,113 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSUtil.h>
+#include "plugin_config.h"
+#include "JSBluetoothClassDeviceService.h"
+#include "BluetoothClassDeviceService.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothClassDeviceService::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothClassDeviceService",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+
+
+JSClassRef JSBluetoothClassDeviceService::m_jsClassRef = JSClassCreate(JSBluetoothClassDeviceService::getClassInfo());
+
+JSStaticValue JSBluetoothClassDeviceService::m_property[] = {
+    { "LIMITED_DISCOVERABILITY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "POSITIONING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "NETWORKING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "RENDERING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "CAPTURING", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "OBJECT_TRANSFER", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "AUDIO", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "TELEPHONY", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { "INFORMATION", getProperty, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef JSBluetoothClassDeviceService::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothClassDeviceService::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothClassDeviceService::createJSObject(JSContextRef context)
+{
+    return JSObjectMake(context, getClassRef(), NULL);
+}
+
+void JSBluetoothClassDeviceService::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothClassDeviceService::finalize(JSObjectRef object)
+{
+    // do nothing
+}
+
+JSValueRef JSBluetoothClassDeviceService::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        std::string name = JSUtil::JSStringToString(context, propertyName);
+        return JSUtil::toJSValueRef(context, BluetoothClassDeviceService::getInstance()->getServiceValue(name));
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed: %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothClassDeviceService.h b/src/Bluetooth/JSBluetoothClassDeviceService.h
new file mode 100644 (file)
index 0000000..5ae6fce
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
+#define __TIZEN_JS_BLUETOOTH_CLASS_DEVICE_SERVICE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothClassDeviceService
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Bluetooth/JSBluetoothDevice.cpp b/src/Bluetooth/JSBluetoothDevice.cpp
new file mode 100644 (file)
index 0000000..1ffe785
--- /dev/null
@@ -0,0 +1,285 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <MultiCallbackUserData.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothDevice.h"
+#include "BluetoothDevice.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothDevice::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothDevice",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothDevice::m_property[] = {
+    {
+        BLUETOOTH_DEVICE_NAME,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_DEVICE_ADDRESS,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_DEVICE_DEVICE_CLASS,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_DEVICE_IS_BONDED,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_DEVICE_IS_TRUSTED,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_DEVICE_IS_CONNECTED,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_DEVICE_UUIDS,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothDevice::m_function[] = {
+    {
+        BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID,
+        connectToServiceByUUID,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothDevice::m_jsClassRef =
+    JSClassCreate(JSBluetoothDevice::getClassInfo());
+
+const JSClassRef JSBluetoothDevice::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothDevice::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothDevice::createJSObject(JSContextRef context,
+    BluetoothDeviceSharedPtr device)
+{
+    BluetoothDeviceHolderPtr holder = new BluetoothDeviceHolder(device);
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+}
+
+BluetoothDeviceSharedPtr JSBluetoothDevice::toBluetoothDevice(
+    JSObjectRef deviceObj)
+{
+    BluetoothDeviceHolderPtr priv =
+        static_cast<BluetoothDeviceHolderPtr>(JSObjectGetPrivate(deviceObj));
+    return priv->mDevice;
+}
+
+void JSBluetoothDevice::initialize(JSContextRef context, JSObjectRef object)
+{
+    // Do nothing
+}
+
+void JSBluetoothDevice::finalize(JSObjectRef object)
+{
+    BluetoothDeviceHolderPtr priv =
+        static_cast<BluetoothDeviceHolderPtr>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothDevice::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothDeviceHolderPtr priv =
+            static_cast<BluetoothDeviceHolderPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_DEVICE_NAME)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->getName());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_DEVICE_ADDRESS)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->getAddress());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_DEVICE_DEVICE_CLASS)) {
+            return priv->mDevice->getDeviceClass(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_DEVICE_IS_BONDED)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->isBonded());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_DEVICE_IS_TRUSTED)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->isTrusted());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_DEVICE_IS_CONNECTED)) {
+            return JSUtil::toJSValueRef(context, priv->mDevice->isConnected());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_DEVICE_UUIDS)) {
+            return priv->mDevice->getUUIDs(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed: %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+JSValueRef JSBluetoothDevice::connectToServiceByUUID(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        // Private Object
+        BluetoothDeviceHolderPtr priv =
+            static_cast<BluetoothDeviceHolderPtr>(
+                JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+          // Access Check
+        TIME_TRACER_ITEM_BEGIN("connectToServiceByUUID::ACE", 1);
+        TIZEN_CHECK_ACCESS(context, exception, priv->mDevice.get(),
+            BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID);
+        TIME_TRACER_ITEM_END("connectToServiceByUUID::ACE", 1);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // uuid
+        std::string uuid = validator.toString(0);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(1);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(2, true);
+
+        // remote address
+        std::string remoteAddress = priv->mDevice->getAddress();
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothAdapter::getInstance()->connectToServiceByUUID(remoteAddress,
+            uuid, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothDevice.connectToServiceByUUID().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothDevice.h b/src/Bluetooth/JSBluetoothDevice.h
new file mode 100644 (file)
index 0000000..44e51d2
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_DEVICE_H__
+#define __TIZEN_JS_BLUETOOTH_DEVICE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "BluetoothDevice.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothDeviceHolder
+{
+public:
+    BluetoothDeviceHolder(BluetoothDeviceSharedPtr device)  : mDevice(device) {}
+    BluetoothDeviceSharedPtr mDevice;
+};
+typedef BluetoothDeviceHolder* BluetoothDeviceHolderPtr;
+
+class JSBluetoothDevice
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothDeviceSharedPtr device);
+    static BluetoothDeviceSharedPtr toBluetoothDevice(JSObjectRef deviceObj);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef connectToServiceByUUID(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Bluetooth/JSBluetoothHealthApplication.cpp b/src/Bluetooth/JSBluetoothHealthApplication.cpp
new file mode 100644 (file)
index 0000000..b4145d8
--- /dev/null
@@ -0,0 +1,285 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <MultiCallbackUserData.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothHealthApplication.h"
+#include "BluetoothHealthProfileHandler.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothHealthApplication::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothHealthApplication",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothHealthApplication::m_property[] = {
+    {
+        BLUETOOTH_HEALTH_APPLICATION_DATA_TYPE,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_HEALTH_APPLICATION_NAME,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_HEALTH_APPLICATION_ONCONNECT,
+        getProperty,
+        setProperty,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothHealthApplication::m_function[] = {
+    {
+        "unregister",
+        unregister,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothHealthApplication::m_jsClassRef =
+    JSClassCreate(JSBluetoothHealthApplication::getClassInfo());
+
+const JSClassRef JSBluetoothHealthApplication::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothHealthApplication::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothHealthApplication::createJSObject(JSContextRef context,
+    BluetoothHealthApplicationSharedPtr app)
+{
+    BluetoothHealthApplicationHolderPtr holder =
+        new BluetoothHealthApplicationHolder(app);
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+}
+
+BluetoothHealthApplicationSharedPtr
+JSBluetoothHealthApplication::toBluetoothHealthApplication(JSObjectRef appObj)
+{
+    BluetoothHealthApplicationHolderPtr priv =
+        static_cast<BluetoothHealthApplicationHolderPtr>(
+            JSObjectGetPrivate(appObj));
+    return priv->mApp;
+}
+
+void JSBluetoothHealthApplication::initialize(JSContextRef context,
+    JSObjectRef object)
+{
+    // Do nothing
+}
+
+void JSBluetoothHealthApplication::finalize(JSObjectRef object)
+{
+    BluetoothHealthApplicationHolderPtr priv =
+        static_cast<BluetoothHealthApplicationHolderPtr>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothHealthApplication::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    try {
+        BluetoothHealthApplicationHolderPtr priv =
+            static_cast<BluetoothHealthApplicationHolderPtr>(
+                JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName,
+                BLUETOOTH_HEALTH_APPLICATION_DATA_TYPE)) {
+            return JSValueMakeNumber(context, priv->mApp->getDataType());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_HEALTH_APPLICATION_NAME)) {
+            return JSUtil::toJSValueRef(context, priv->mApp->getName());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_HEALTH_APPLICATION_ONCONNECT)) {
+            LOGD("get onconnect");
+            return priv->mApp->getOnConnect(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed: %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+bool JSBluetoothHealthApplication::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    try {
+        BluetoothHealthApplicationHolderPtr priv =
+            static_cast<BluetoothHealthApplicationHolderPtr>(
+            JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_HEALTH_APPLICATION_ONCONNECT)) {
+            LOGD("Set onconnect");
+            JSObjectRef onconnectObj = NULL;
+            if(!JSValueIsNull(context, value)) {
+                if(!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+
+                onconnectObj = JSUtil::JSValueToObject(context, value);
+
+                if(!JSObjectIsFunction(context, onconnectObj)) {
+                    throw TypeMismatchException("Not function");
+                }
+            }
+            else {
+                LOGD("onconnect() is NULL");
+            }
+
+            return priv->mApp->setOnConnect(context, onconnectObj);
+        }
+    } catch (const BasePlatformException &err) {
+        JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return false;
+}
+
+
+JSValueRef JSBluetoothHealthApplication::unregister(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        BluetoothHealthApplicationHolderPtr priv =
+            static_cast<BluetoothHealthApplicationHolderPtr>(
+                JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+        TIME_TRACER_ITEM_BEGIN("unregister::ACE", 1);
+        TIZEN_CHECK_ACCESS(context, exception, priv->mApp.get(),
+            BLUETOOTH_HEALTH_APPLICATION_API_UNREGISTER);
+        TIME_TRACER_ITEM_END("unregister::ACE", 1);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(0, true);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothHealthProfileHandler::getInstance()->unregisterApp(
+            priv->mApp->getAppID(), callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothHealthApplication::unregister().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothHealthApplication.h b/src/Bluetooth/JSBluetoothHealthApplication.h
new file mode 100644 (file)
index 0000000..6636268
--- /dev/null
@@ -0,0 +1,99 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_HEALTH_APPLICATION_H__
+#define __TIZEN_JS_BLUETOOTH_HEALTH_APPLICATION_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "BluetoothHealthApplication.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class BluetoothHealthApplicationHolder
+{
+public:
+    BluetoothHealthApplicationHolder(BluetoothHealthApplicationSharedPtr app){mApp = app;}
+    BluetoothHealthApplicationSharedPtr mApp;
+};
+typedef BluetoothHealthApplicationHolder* BluetoothHealthApplicationHolderPtr;
+
+class JSBluetoothHealthApplication
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothHealthApplicationSharedPtr app);
+    static BluetoothHealthApplicationSharedPtr toBluetoothHealthApplication(JSObjectRef appObj);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef unregister(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_BLUETOOTH_HEALTH_APPLICATION_H__
diff --git a/src/Bluetooth/JSBluetoothHealthChannel.cpp b/src/Bluetooth/JSBluetoothHealthChannel.cpp
new file mode 100644 (file)
index 0000000..c0294e1
--- /dev/null
@@ -0,0 +1,390 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <vector>
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <MultiCallbackUserData.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothHealthChannel.h"
+#include "BluetoothHealthProfileHandler.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothHealthChannel::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothHealthChannel",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothHealthChannel::m_property[] = {
+    {
+        BLUETOOTH_HEALTH_CHANNEL_PEER,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_HEALTH_CHANNEL_TYPE,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_HEALTH_CHANNEL_APP,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_HEALTH_CHANNEL_IS_CONNECTED,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothHealthChannel::m_function[] = {
+    {
+        BLUETOOTH_HEALTH_CHANNEL_API_SEND_DATA,
+        sendData,
+        kJSPropertyAttributeNone
+    },
+    {
+        "close",
+        close,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_HEALTH_CHANNEL_API_SET_LISTENER,
+        setListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_HEALTH_CHANNEL_API_UNSET_LISTENER,
+        unsetListener,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothHealthChannel::m_jsClassRef =
+    JSClassCreate(JSBluetoothHealthChannel::getClassInfo());
+
+const JSClassRef JSBluetoothHealthChannel::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothHealthChannel::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothHealthChannel::createJSObject(JSContextRef context,
+    BluetoothHealthChannelPtr channel)
+{
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(channel));
+}
+
+void JSBluetoothHealthChannel::initialize(JSContextRef context,
+    JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothHealthChannel::finalize(JSObjectRef object)
+{
+    BluetoothHealthChannelPtr priv =
+        static_cast<BluetoothHealthChannelPtr>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothHealthChannel::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothHealthChannelPtr priv =
+            static_cast<BluetoothHealthChannelPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_HEALTH_CHANNEL_PEER)) {
+            return priv->getPeer(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_HEALTH_CHANNEL_TYPE)) {
+            return JSUtil::toJSValueRef(context, priv->getChannelTypeStr());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_HEALTH_CHANNEL_APP)) {
+            return priv->getApp(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_HEALTH_CHANNEL_IS_CONNECTED)) {
+            return JSUtil::toJSValueRef(context, priv->getConnectionState());
+        }
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed: %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+JSValueRef JSBluetoothHealthChannel::sendData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);;
+
+    try {
+        // Private Object
+        BluetoothHealthChannelPtr priv =
+            static_cast<BluetoothHealthChannelPtr>(
+                JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw Common::UnknownException("Private object is NULL.");
+        }
+
+        // Access Check
+        TIME_TRACER_ITEM_BEGIN("sendData::ACE", 1);;
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+            BLUETOOTH_HEALTH_CHANNEL_API_SEND_DATA);
+        TIME_TRACER_ITEM_END("sendData::ACE", 1);;
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef dataArrayObj  = validator.toArrayObject(0);  // data
+        size_t size = JSGetArrayLength(context, dataArrayObj);
+        char *buffer = new char[size];
+        for(size_t i = 0; i < size; ++i) {
+            JSValueRef element = JSGetArrayElement(context, dataArrayObj, i);
+            buffer[i] =
+                static_cast<char>(JSUtil::JSValueToByte(context, element));
+        }
+
+        JSValueRef result = JSUtil::toJSValueRef(context,
+            priv->sendData(buffer, size));
+        delete [] buffer;
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);;
+
+        return result;
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothHealthChannel::close(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        // Private Object
+        BluetoothHealthChannelPtr priv =
+            static_cast<BluetoothHealthChannelPtr>(
+                JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw Common::UnknownException("Private object is NULL.");
+        }
+        // Access Check
+        TIME_TRACER_ITEM_BEGIN("close::ACE", 1);;
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+            BLUETOOTH_HEALTH_CHANNEL_API_CLOSE);
+        TIME_TRACER_ITEM_END("close::ACE", 1);;
+
+        priv->close();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);;
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothHealthChannel::setListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);;
+
+    try {
+        // Private Object
+        BluetoothHealthChannelPtr priv =
+            static_cast<BluetoothHealthChannelPtr>(
+                JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw Common::UnknownException("Private object is NULL.");
+        }
+
+        // Access Check
+        TIME_TRACER_ITEM_BEGIN("setListener::ACE", 1);;
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+            BLUETOOTH_HEALTH_CHANNEL_API_SET_LISTENER);
+        TIME_TRACER_ITEM_END("setListener::ACE", 1);;
+
+
+        // Validate arguments
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        JSObjectRef successCallback =
+            validator.toCallbackObject(0, false, "onmessage", "onclose", NULL);
+
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiMultiCallbackUserData");
+        }
+        else {
+            // onmessage
+            JSValueRef onmessageValue = JSUtil::getProperty(context,
+                successCallback, "onmessage");
+            if(!JSValueIsUndefined(context, onmessageValue)) {
+                LOGD("There is a onmessage()");
+                callback->setCallback("onmessage",
+                    JSUtil::JSValueToObject(context, onmessageValue));
+            }
+
+            // onclose
+            JSValueRef oncloseValue = JSUtil::getProperty(context,
+                successCallback, "onclose");
+            if(!JSValueIsUndefined(context, oncloseValue)) {
+                LOGD("There is a onclose()");
+                callback->setCallback("onclose",
+                    JSUtil::JSValueToObject(context, oncloseValue));
+            }
+        }
+
+        priv->setListener(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);;
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothHealthChannel::unsetListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);;
+
+    try {
+        // Private Object
+        BluetoothHealthChannelPtr priv =
+            static_cast<BluetoothHealthChannelPtr>(
+                JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw Common::UnknownException("Private object is NULL.");
+        }
+        // Access Check
+        TIME_TRACER_ITEM_BEGIN("unsetListener::ACE", 1);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+            BLUETOOTH_HEALTH_CHANNEL_API_UNSET_LISTENER);
+        TIME_TRACER_ITEM_END("unsetListener::ACE", 1);
+
+        priv->unsetListener();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);;
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothHealthChannel.h b/src/Bluetooth/JSBluetoothHealthChannel.h
new file mode 100644 (file)
index 0000000..41db670
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_HEALTH_CHANNEL_H__
+#define __TIZEN_JS_BLUETOOTH_HEALTH_CHANNEL_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "BluetoothHealthChannel.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothHealthChannel
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothHealthChannelPtr channel);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef close(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    static JSValueRef sendData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    static JSValueRef setListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    static JSValueRef unsetListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_BLUETOOTH_HEALTH_CHANNEL_H__
diff --git a/src/Bluetooth/JSBluetoothHealthProfileHandler.cpp b/src/Bluetooth/JSBluetoothHealthProfileHandler.cpp
new file mode 100644 (file)
index 0000000..ffb62bd
--- /dev/null
@@ -0,0 +1,241 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothHealthProfileHandler.h"
+#include "JSBluetoothProfileHandler.h"
+#include "JSBluetoothHealthApplication.h"
+#include "JSBluetoothDevice.h"
+#include "BluetoothHealthProfileHandler.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothHealthProfileHandler::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothHealthProfileHandler",
+    JSBluetoothProfileHandler::getClassRef(), //ParentClass
+    NULL, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSBluetoothHealthProfileHandler::m_function[] = {
+    {
+        BLUETOOTH_HEALTH_PROFILE_HANDLER_API_REGISTER_SINK_APPLICATION,
+        registerSinkApplication,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_HEALTH_PROFILE_HANDLER_API_CONNECT_TO_SOURCE,
+        connectToSource,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothHealthProfileHandler::m_jsClassRef =
+    JSClassCreate(JSBluetoothHealthProfileHandler::getClassInfo());
+
+const JSClassRef JSBluetoothHealthProfileHandler::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothHealthProfileHandler::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothHealthProfileHandler::createJSObject(
+    JSContextRef context)
+{
+    return JSObjectMake(context, getClassRef(), NULL);
+}
+
+void JSBluetoothHealthProfileHandler::initialize(JSContextRef context,
+    JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothHealthProfileHandler::finalize(JSObjectRef object)
+{
+    // do nothing
+}
+
+JSValueRef JSBluetoothHealthProfileHandler::registerSinkApplication(
+    JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+            // Access Check
+    TIME_TRACER_ITEM_BEGIN("registerSinkApplication::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception,
+        BluetoothHealthProfileHandler::getInstance(),
+        BLUETOOTH_HEALTH_PROFILE_HANDLER_API_REGISTER_SINK_APPLICATION);
+    TIME_TRACER_ITEM_END("registerSinkApplication::ACE", 1);
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // dataType
+        unsigned short dataType =
+            static_cast<unsigned short>(validator.toULong(0));
+
+        // name
+        std::string name = validator.toString(1);
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(2);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(3, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothHealthProfileHandler::getInstance()->
+            registerSinkApp(dataType, name, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.setName().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothHealthProfileHandler::connectToSource(
+    JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    // Access Check
+    TIME_TRACER_ITEM_BEGIN("connectToSource::ACE", 1);
+    TIZEN_CHECK_ACCESS(context, exception,
+        BluetoothHealthProfileHandler::getInstance(),
+        BLUETOOTH_HEALTH_PROFILE_HANDLER_API_CONNECT_TO_SOURCE);
+    TIME_TRACER_ITEM_END("connectToSource::ACE", 1);
+
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // remote device
+        JSObjectRef remoteObj = validator.toObject(0);
+        if(!JSValueIsObjectOfClass(context, remoteObj,
+            JSBluetoothDevice::getClassRef())) {
+            throw TypeMismatchException(
+                "remoteDevice is not a BluetoothDevice object");
+        }
+
+        // application
+        JSObjectRef appObj = validator.toObject(1);
+        if(!JSValueIsObjectOfClass(context, appObj,
+            JSBluetoothHealthApplication::getClassRef())) {
+            throw TypeMismatchException(
+                "application is not a BluetoothHealthApplication object");
+        }
+
+        // successCallback
+        JSObjectRef successCallback = validator.toFunction(2);
+
+        // errorCallback
+        JSObjectRef errorCallback = validator.toFunction(3, true);
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+            new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        BluetoothHealthProfileHandler::getInstance()->connectToSource(
+            remoteObj, appObj, callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothAdapter.setName().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothHealthProfileHandler.h b/src/Bluetooth/JSBluetoothHealthProfileHandler.h
new file mode 100644 (file)
index 0000000..6b292a5
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_HEALTH_PROFILE_HANDLER_H__
+#define __TIZEN_JS_HEALTH_PROFILE_HANDLER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothHealthProfileHandler
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef registerSinkApplication(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    static JSValueRef connectToSource(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_HEALTH_PROFILE_HANDLER_H__
diff --git a/src/Bluetooth/JSBluetoothManager.cpp b/src/Bluetooth/JSBluetoothManager.cpp
new file mode 100644 (file)
index 0000000..d6e46c4
--- /dev/null
@@ -0,0 +1,217 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <PropertyBag.h>
+#include <bluetooth.h>
+
+#include "plugin_config_impl.h"
+#include "JSBluetoothManager.h"
+#include "JSBluetoothClassDeviceMajor.h"
+#include "JSBluetoothClassDeviceMinor.h"
+#include "JSBluetoothClassDeviceService.h"
+#include "JSBluetoothAdapter.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothManager",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothManager::m_property[] = {
+    {
+        BLUETOOTH_MANAGER_DEVICE_MAJOR,
+        getReadOnlyProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_MANAGER_DEVICE_MINOR,
+        getReadOnlyProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_MANAGER_DEVICE_SERVICE,
+        getReadOnlyProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothManager::m_function[] = {
+    {
+        BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER,
+        getDefaultAdapter,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothManager::m_jsClassRef =
+    JSClassCreate(JSBluetoothManager::getClassInfo());
+
+const JSClassRef JSBluetoothManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSBluetoothManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("initialize");
+
+    if (!JSObjectGetPrivate(object)) {
+        JSBluetoothManagerPriv* priv = new JSBluetoothManagerPriv();
+
+        if(priv) {
+        // deviceMajor
+            priv->setProperty(context, BLUETOOTH_MANAGER_DEVICE_MAJOR,
+            JSBluetoothClassDeviceMajor::createJSObject(context));
+
+            // deviceMinor
+            priv->setProperty(context, BLUETOOTH_MANAGER_DEVICE_MINOR,
+            JSBluetoothClassDeviceMinor::createJSObject(context));
+
+            // deviceService
+            priv->setProperty(context, BLUETOOTH_MANAGER_DEVICE_SERVICE,
+            JSBluetoothClassDeviceService::createJSObject(context));
+
+            if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+                LOGW("Failed to set private data");
+                delete priv;
+            }
+            LOGD("Private creation ok");
+        }
+        else {
+            LOGW("Failed to create private data");
+        }
+    }
+    else {
+        LOGW("already has private data");
+    }
+}
+
+void JSBluetoothManager::finalize(JSObjectRef object)
+{
+    JSBluetoothManagerPriv *priv =
+        static_cast<JSBluetoothManagerPriv*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothManager::getReadOnlyProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    JSBluetoothManagerPriv *priv =
+        static_cast<JSBluetoothManagerPriv*>(JSObjectGetPrivate(object));
+    if(!priv) {
+        LOGW("There is no private data");
+        return NULL;
+    }
+
+    std::string name = JSUtil::JSStringToString(context, propertyName);
+    return priv->getProperty(context, propertyName);
+}
+
+JSValueRef JSBluetoothManager::getDefaultAdapter(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    JSBluetoothManagerPriv *priv =
+        static_cast<JSBluetoothManagerPriv*>(JSObjectGetPrivate(thisObject));
+
+    if (!priv)
+    {
+        TypeMismatchException err("Private Object is null");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    TIME_TRACER_ITEM_BEGIN("getDefaultAdapter", 1);
+    TIZEN_CHECK_ACCESS(context, exception, priv,
+        BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER);
+    TIME_TRACER_ITEM_END("getDefaultAdapter::ACE", 1);
+
+    try {
+        BluetoothAdapter::getInstance()->copyAceCheckAccessFunction(priv);
+        JSObjectRef adapter = JSBluetoothAdapter::createJSObject(context);
+
+        TIME_TRACER_ITEM_END("getDefaultAdapter", 1);
+        return adapter;
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothManager.getDefaultAdapter().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothManager.h b/src/Bluetooth/JSBluetoothManager.h
new file mode 100644 (file)
index 0000000..4e4ed40
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_MANAGER_H__
+#define __TIZEN_JS_BLUETOOTH_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <PropertyBag.h>
+#include <memory>
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+
+class JSBluetoothManagerPriv :
+    public DeviceAPI::Common::SecurityAccessor,
+    public DeviceAPI::Common::PropertyBag
+{
+public:
+    JSBluetoothManagerPriv() :
+            DeviceAPI::Common::SecurityAccessor(),
+            DeviceAPI::Common::PropertyBag()
+    {
+    }
+    virtual ~JSBluetoothManagerPriv() {}
+};
+
+class JSBluetoothManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getReadOnlyProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDefaultAdapter(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Bluetooth/JSBluetoothProfileHandler.cpp b/src/Bluetooth/JSBluetoothProfileHandler.cpp
new file mode 100644 (file)
index 0000000..74d5e25
--- /dev/null
@@ -0,0 +1,126 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothProfileHandler.h"
+#include "JSBluetoothHealthProfileHandler.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothProfileHandler::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothProfileHandler",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothProfileHandler::m_property[] = {
+    {
+        BLUETOOTH_PROFILE_TYPE,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothProfileHandler::m_jsClassRef =
+    JSClassCreate(JSBluetoothProfileHandler::getClassInfo());
+
+const JSClassRef JSBluetoothProfileHandler::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothProfileHandler::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSBluetoothProfileHandler::initialize(JSContextRef context,
+    JSObjectRef object)
+{
+    // Do nothing
+}
+
+void JSBluetoothProfileHandler::finalize(JSObjectRef object)
+{
+    // Do nothing
+}
+
+JSValueRef JSBluetoothProfileHandler::getProperty(JSContextRef context,
+    JSObjectRef object, JSStringRef propertyName, JSValueRef* exception) {
+    LOGD("Enter");
+
+    try {
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_PROFILE_TYPE)) {
+            if(object) {
+                if(JSValueIsObjectOfClass(context, object,
+                    JSBluetoothHealthProfileHandler::getClassRef())) {
+
+                    std::string profileType("HEALTH");
+                    LOGD("profileType: %s", profileType.c_str());
+                    return JSUtil::toJSValueRef(context, profileType);
+                }
+            }
+            else {
+                LOGE("object is NULL");
+            }
+        }
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothProfileHandler.h b/src/Bluetooth/JSBluetoothProfileHandler.h
new file mode 100644 (file)
index 0000000..38c9370
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_PROFILE_HANDLER_H__
+#define __TIZEN_JS_BLUETOOTH_PROFILE_HANDLER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothProfileHandler
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_BLUETOOTH_PROFILE_HANDLER_H__
diff --git a/src/Bluetooth/JSBluetoothServiceHandler.cpp b/src/Bluetooth/JSBluetoothServiceHandler.cpp
new file mode 100644 (file)
index 0000000..e5fd90a
--- /dev/null
@@ -0,0 +1,268 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <MultiCallbackUserData.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothServiceHandler.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothServiceHandler::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothServiceHandler",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothServiceHandler::m_property[] = {
+    {
+        BLUETOOTH_SERVICE_HANDLER_UUID,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_SERVICE_HANDLER_NAME,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_SERVICE_HANDLER_IS_CONNECTED,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_SERVICE_HANDLER_ONCONNECT,
+        getProperty,
+        setProperty,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothServiceHandler::m_function[] = {
+    {
+        BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER,
+        unregister,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothServiceHandler::m_jsClassRef =
+    JSClassCreate(JSBluetoothServiceHandler::getClassInfo());
+
+const JSClassRef JSBluetoothServiceHandler::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothServiceHandler::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothServiceHandler::createJSObject(JSContextRef context,
+    BluetoothServiceHandlerPtr service)
+{
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(service));
+}
+
+void JSBluetoothServiceHandler::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothServiceHandler::finalize(JSObjectRef object)
+{
+    BluetoothServiceHandlerPtr priv =
+        static_cast<BluetoothServiceHandlerPtr>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothServiceHandler::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothServiceHandlerPtr priv =
+            static_cast<BluetoothServiceHandlerPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SERVICE_HANDLER_UUID)) {
+            return JSUtil::toJSValueRef(context, priv->getUUID());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SERVICE_HANDLER_NAME)) {
+            return JSUtil::toJSValueRef(context, priv->getName());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SERVICE_HANDLER_IS_CONNECTED)) {
+            return JSUtil::toJSValueRef(context, priv->getConnectionState());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SERVICE_HANDLER_ONCONNECT)) {
+            return priv->getOnConnect(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed: %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+bool JSBluetoothServiceHandler::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothServiceHandlerPtr priv =
+            static_cast<BluetoothServiceHandlerPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SERVICE_HANDLER_ONCONNECT)) {
+            JSObjectRef object = NULL;
+            if(!JSValueIsNull(context, value)) {
+                if(!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+
+                object = JSUtil::JSValueToObject(context, value);
+
+                if(!JSObjectIsFunction(context, object)) {
+                    throw TypeMismatchException("Not function");
+                }
+            }
+            else {
+                LOGD("onconnect() is NULL");
+            }
+
+            return priv->setOnConnect(context, object);
+        }
+    } catch (const BasePlatformException &err) {
+        JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return false;
+}
+
+JSValueRef JSBluetoothServiceHandler::unregister(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        // Private Object
+        BluetoothServiceHandlerPtr priv =
+            static_cast<BluetoothServiceHandlerPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        // Access Check
+        TIME_TRACER_ITEM_BEGIN("unregister::ACE", 1);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+            BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER);
+        TIME_TRACER_ITEM_END("unregister::ACE", 1);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCallback = validator.toFunction(0, true);  // successCallback
+        JSObjectRef errorCallback = validator.toFunction(1, true);  // errorCallback
+
+        // perform
+        MultiCallbackUserDataPtr callback(
+                new MultiCallbackUserData(GlobalContextManager::getInstance()->
+                    getGlobalContext(context)));
+        if(!callback){
+            LOGW("Can't create MultiCallbackUserData");
+        }
+        else {
+            callback->setCallback("success", successCallback);
+            callback->setCallback("error", errorCallback);
+        }
+
+        priv->unregister(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothServiceHandler.unregister().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothServiceHandler.h b/src/Bluetooth/JSBluetoothServiceHandler.h
new file mode 100644 (file)
index 0000000..c59540d
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_SERVICE_HANDLER_H__
+#define __TIZEN_JS_BLUETOOTH_SERVICE_HANDLER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "BluetoothServiceHandler.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothServiceHandler
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothServiceHandlerPtr service);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef unregister(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Bluetooth/JSBluetoothSocket.cpp b/src/Bluetooth/JSBluetoothSocket.cpp
new file mode 100644 (file)
index 0000000..d3941c9
--- /dev/null
@@ -0,0 +1,422 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <vector>
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <MultiCallbackUserData.h>
+
+#include "plugin_config.h"
+#include "JSBluetoothSocket.h"
+#include "BluetoothSocket.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+JSClassDefinition JSBluetoothSocket::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "BluetoothSocket",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSBluetoothSocket::m_property[] = {
+    {
+        BLUETOOTH_SOCKET_UUID,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_SOCKET_STATE,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_SOCKET_PEER,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeReadOnly |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_SOCKET_ONMESSAGE,
+        getProperty,
+        setProperty,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_SOCKET_ONCLOSE,
+        getProperty,
+        setProperty,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeDontDelete
+    },
+    {
+        BLUETOOTH_SOCKET_ONERROR,
+        getProperty,
+        setProperty,
+        kJSPropertyAttributeNone |
+        kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSBluetoothSocket::m_function[] = {
+    {
+        BLUETOOTH_SOCKET_API_WRITE_DATA,
+        writeData,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_SOCKET_API_READ_DATA,
+        readData,
+        kJSPropertyAttributeNone
+    },
+    {
+        BLUETOOTH_SOCKET_API_CLOSE,
+        close,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSBluetoothSocket::m_jsClassRef =
+    JSClassCreate(JSBluetoothSocket::getClassInfo());
+
+const JSClassRef JSBluetoothSocket::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBluetoothSocket::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSBluetoothSocket::createJSObject(JSContextRef context,
+    BluetoothSocketPtr socket)
+{
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(socket));
+}
+
+void JSBluetoothSocket::initialize(JSContextRef context, JSObjectRef object)
+{
+    // do nothing
+}
+
+void JSBluetoothSocket::finalize(JSObjectRef object)
+{
+    BluetoothSocketPtr priv =
+        static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSBluetoothSocket::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        BluetoothSocketPtr priv =
+            static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, BLUETOOTH_SOCKET_UUID)) {
+            return JSUtil::toJSValueRef(context, priv->getUUID());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SOCKET_STATE)) {
+            LOGD("get state");
+            std::string state;
+            if(priv->getConnectionState()) {
+                state = "OPEN";
+            }
+            else {
+                state = "CLOSED";
+            }
+            LOGD("state: %s", state.c_str());
+            return JSUtil::toJSValueRef(context, state);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SOCKET_PEER)) {
+            return priv->getPeer(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SOCKET_ONMESSAGE)) {
+            return priv->getOnMessage(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SOCKET_ONCLOSE)) {
+            return priv->getOnClose(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SOCKET_ONERROR)) {
+            return priv->getOnError(context);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGW("Getting property is failed: %s", err.getMessage().c_str());
+    }
+
+    return NULL;
+}
+
+bool JSBluetoothSocket::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    try {
+        BluetoothSocketPtr priv =
+            static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SOCKET_ONMESSAGE)) {
+            JSObjectRef object = NULL;
+            if(!JSValueIsNull(context, value)) {
+                if(!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+
+                object = JSUtil::JSValueToObject(context, value);
+
+                if(!JSObjectIsFunction(context, object)) {
+                    throw TypeMismatchException("Not function");
+                }
+            }
+            else {
+                LOGD("onmessage() is NULL");
+            }
+
+            return priv->setOnMessage(context, object);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SOCKET_ONCLOSE)) {
+            JSObjectRef object = NULL;
+            if(!JSValueIsNull(context, value)) {
+                if(!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+
+                object = JSUtil::JSValueToObject(context, value);
+
+                if(!JSObjectIsFunction(context, object)) {
+                    throw TypeMismatchException("Not function");
+                }
+            }
+            else {
+                LOGD("onclose() is NULL");
+            }
+
+            return priv->setOnClose(context, object);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+            BLUETOOTH_SOCKET_ONERROR)) {
+            JSObjectRef object = NULL;
+            if(!JSValueIsNull(context, value)) {
+                if(!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+
+                object = JSUtil::JSValueToObject(context, value);
+
+                if(!JSObjectIsFunction(context, object)) {
+                    throw TypeMismatchException("Not function");
+                }
+            }
+            else {
+                LOGD("onerror() is NULL");
+            }
+
+            return priv->setOnError(context, object);
+        }
+    } catch (const BasePlatformException &err) {
+        JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return false;
+}
+
+JSValueRef JSBluetoothSocket::writeData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        // Private Object
+        BluetoothSocketPtr priv =
+            static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw Common::UnknownException("Private object is NULL.");
+        }
+
+        // Access Check
+        TIME_TRACER_ITEM_BEGIN("writeData::ACE", 1);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+            BLUETOOTH_SOCKET_API_WRITE_DATA);
+        TIME_TRACER_ITEM_END("writeData::ACE", 1);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef dataArrayObj  = validator.toArrayObject(0);  // data
+        size_t size = JSGetArrayLength(context, dataArrayObj);
+        char *buffer = new char[size];
+        for(size_t i = 0; i < size; ++i) {
+            JSValueRef element = JSGetArrayElement(context, dataArrayObj, i);
+            buffer[i] = static_cast<char>(
+                JSUtil::JSValueToByte(context, element));
+        }
+
+        JSValueRef result = JSUtil::toJSValueRef(context,
+            priv->writeData(buffer, size));
+        delete [] buffer;
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);;
+
+        return result;
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothSocket.writeData().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothSocket::readData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+
+    try {
+        // Private Object
+        BluetoothSocketPtr priv =
+            static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw Common::UnknownException("Private object is NULL.");
+        }
+
+        // Access Check
+        TIME_TRACER_ITEM_BEGIN("readData::ACE", 1);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+            BLUETOOTH_SOCKET_API_READ_DATA);
+        TIME_TRACER_ITEM_END("readData::ACE", 1);
+
+
+        std::vector<signed char> data = priv->readData();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+
+        return JSUtil::toJSValueRef_(context, data);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothSocket.readData().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSBluetoothSocket::close(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);;
+
+    try {
+        // Private Object
+        BluetoothSocketPtr priv =
+            static_cast<BluetoothSocketPtr>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw Common::UnknownException("Private object is NULL.");
+        }
+
+        // Access Check
+        TIME_TRACER_ITEM_BEGIN("close::ACE", 1);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+            BLUETOOTH_SOCKET_API_CLOSE);
+        TIME_TRACER_ITEM_END("close::ACE", 1);
+
+        priv->close();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 1);;
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err(
+            "Unknown Error in BluetoothSocket.close().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/JSBluetoothSocket.h b/src/Bluetooth/JSBluetoothSocket.h
new file mode 100644 (file)
index 0000000..26ec403
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_BLUETOOTH_SOCKET_H__
+#define __TIZEN_JS_BLUETOOTH_SOCKET_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "BluetoothSocket.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+class JSBluetoothSocket
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef createJSObject(JSContextRef context, BluetoothSocketPtr socket);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef writeData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef readData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef close(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Bluetooth
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Bluetooth/config.xml b/src/Bluetooth/config.xml
new file mode 100644 (file)
index 0000000..e3c942f
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-bluetooth.so</library-name>
+    <feature-install-uri>bluetooth.install.uri</feature-install-uri>
+    <api-feature>
+        <name>http://tizen.org/privilege/bluetooth.gap</name>
+        <device-capability>bluetooth.gap</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bluetooth.admin</name>
+        <device-capability>bluetooth.admin</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bluetoothmanager</name>
+        <device-capability>bluetoothmanager</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bluetooth.spp</name>
+        <device-capability>bluetooth.spp</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bluetooth.health</name>
+        <device-capability>bluetooth.health</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/Bluetooth/plugin_config.cpp b/src/Bluetooth/plugin_config.cpp
new file mode 100644 (file)
index 0000000..3f0d746
--- /dev/null
@@ -0,0 +1,398 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define BLUETOOTH_FEATURE_API_ADMIN "http://tizen.org/privilege/bluetooth.admin"
+#define BLUETOOTH_FEATURE_API_GAP "http://tizen.org/privilege/bluetooth.gap"
+#define BLUETOOTH_FEATURE_API_SPP "http://tizen.org/privilege/bluetooth.spp"
+#define BLUETOOTH_FEATURE_API_MANAGER "http://tizen.org/privilege/bluetoothmanager"
+#define BLUETOOTH_FEATURE_API_HDP "http://tizen.org/privilege/bluetooth.health"
+
+#define BLUETOOTH_DEVICE_CAP_ADMIN "bluetooth.admin"
+#define BLUETOOTH_DEVICE_CAP_GAP "bluetooth.gap"
+#define BLUETOOTH_DEVICE_CAP_SPP "bluetooth.spp"
+#define BLUETOOTH_DEVICE_CAP_MANAGER "bluetoothmanager"
+#define BLUETOOTH_DEVICE_CAP_HDP "bluetooth.health"
+
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+static FunctionMapping createBluetoothFunctions();
+static FunctionMapping BluetoothFunctions = createBluetoothFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(Bluetooth, BluetoothFunctions);
+
+#pragma GCC visibility pop
+
+static FunctionMapping createBluetoothFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BLUETOOTH_ADMIN, BLUETOOTH_DEVICE_CAP_ADMIN);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BLUETOOTH_ADMIN);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BLUETOOTH_ADMIN, DEVICE_CAP_BLUETOOTH_ADMIN);
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BLUETOOTH_GAP, BLUETOOTH_DEVICE_CAP_GAP);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BLUETOOTH_GAP);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BLUETOOTH_GAP, DEVICE_CAP_BLUETOOTH_GAP);
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BLUETOOTH_SPP, BLUETOOTH_DEVICE_CAP_SPP);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BLUETOOTH_SPP);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BLUETOOTH_SPP, DEVICE_CAP_BLUETOOTH_SPP);
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BLUETOOTH_MANAGER, BLUETOOTH_DEVICE_CAP_MANAGER);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BLUETOOTH_MANAGER);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BLUETOOTH_MANAGER, DEVICE_CAP_BLUETOOTH_MANAGER);
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BLUETOOTH_HDP, BLUETOOTH_DEVICE_CAP_HDP);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BLUETOOTH_HDP);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BLUETOOTH_HDP, DEVICE_CAP_BLUETOOTH_HDP);
+
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_ADMIN, BLUETOOTH_FEATURE_API_ADMIN);
+    ACE_CREATE_FEATURE_LIST(BLUETOOTH_FEATURES_BLUETOOTH_ADMIN);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_ADMIN, FEATURE_ADMIN);
+
+    ACE_CREATE_FEATURE(FEATURE_GAP, BLUETOOTH_FEATURE_API_GAP);
+    ACE_CREATE_FEATURE_LIST(BLUETOOTH_FEATURES_BLUETOOTH_GAP);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_GAP, FEATURE_GAP);
+
+    ACE_CREATE_FEATURE(FEATURE_SPP, BLUETOOTH_FEATURE_API_SPP);
+    ACE_CREATE_FEATURE_LIST(BLUETOOTH_FEATURES_BLUETOOTH_SPP);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_SPP, FEATURE_SPP);
+
+    ACE_CREATE_FEATURE(FEATURE_MANAGER, BLUETOOTH_FEATURE_API_MANAGER);
+    ACE_CREATE_FEATURE_LIST(BLUETOOTH_FEATURES_BLUETOOTH_MANAGER);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_MANAGER, FEATURE_MANAGER);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_MANAGER, FEATURE_ADMIN);   // for backward compatibility
+
+    ACE_CREATE_FEATURE(FEATURE_HDP, BLUETOOTH_FEATURE_API_HDP);
+    ACE_CREATE_FEATURE_LIST(BLUETOOTH_FEATURES_BLUETOOTH_HDP);
+    ACE_ADD_API_FEATURE(BLUETOOTH_FEATURES_BLUETOOTH_HDP, FEATURE_HDP);
+
+
+    /**
+     * Functions
+     */
+    FunctionMapping BluetoothMapping;
+
+    // getDefaultAdapter()
+    AceFunction getDefaultAdapterFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER,
+            BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER,
+            getDefaultAdapterFunc));
+
+    // setName()
+    AceFunction setNameFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_SET_NAME,
+            BLUETOOTH_ADAPTER_API_SET_NAME,
+            BLUETOOTH_FEATURES_BLUETOOTH_ADMIN,
+            DEVICE_LIST_BLUETOOTH_ADMIN);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_SET_NAME,
+            setNameFunc));
+
+    // setPowered()
+    AceFunction setPoweredFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_SET_POWERED,
+            BLUETOOTH_ADAPTER_API_SET_POWERED,
+            BLUETOOTH_FEATURES_BLUETOOTH_ADMIN,
+            DEVICE_LIST_BLUETOOTH_ADMIN);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_SET_POWERED,
+            setPoweredFunc));
+
+    // setVisible()
+    AceFunction setVisibleFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_SET_VISIBLE,
+            BLUETOOTH_ADAPTER_API_SET_VISIBLE,
+            BLUETOOTH_FEATURES_BLUETOOTH_MANAGER,
+            DEVICE_LIST_BLUETOOTH_MANAGER);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_SET_VISIBLE,
+            setVisibleFunc));
+
+    // setChangeListener()
+    AceFunction setChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER,
+            BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER,
+            BLUETOOTH_FEATURES_BLUETOOTH_ADMIN,
+            DEVICE_LIST_BLUETOOTH_ADMIN);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER,
+            setChangeListenerFunc));
+
+    // unsetChangeListener()
+    AceFunction unsetChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER,
+            BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER,
+            BLUETOOTH_FEATURES_BLUETOOTH_ADMIN,
+            DEVICE_LIST_BLUETOOTH_ADMIN);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER,
+            unsetChangeListenerFunc));
+
+    // discoverDevices()
+    AceFunction discoverDevicesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES,
+            BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES,
+            discoverDevicesFunc));
+
+    //  stopDiscovery()
+    AceFunction  stopDiscoveryFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_STOP_DISCOVERY,
+            BLUETOOTH_ADAPTER_API_STOP_DISCOVERY,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_STOP_DISCOVERY,
+            stopDiscoveryFunc));
+
+    //  getKnownDevices()
+    AceFunction  getKnownDevicesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES,
+            BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES,
+            getKnownDevicesFunc));
+
+    //  getDevice()
+    AceFunction  getDeviceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_GET_DEVICE,
+            BLUETOOTH_ADAPTER_API_GET_DEVICE,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_GET_DEVICE,
+            getDeviceFunc));
+
+    //  createBonding()
+    AceFunction  createBondingFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_CREATE_BONDING,
+            BLUETOOTH_ADAPTER_API_CREATE_BONDING,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_CREATE_BONDING,
+            createBondingFunc));
+
+    //  destroyBonding()
+    AceFunction  destroyBondingFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_DESTROY_BONDING,
+            BLUETOOTH_ADAPTER_API_DESTROY_BONDING,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_DESTROY_BONDING,
+            destroyBondingFunc));
+
+    //  registerRFCOMMServiceByUUID()
+    AceFunction  registerRFCOMMServiceByUUIDFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID,
+            BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID,
+            registerRFCOMMServiceByUUIDFunc));
+
+    //  connectToServiceByUUID()
+    AceFunction  connectToServiceByUUIDFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID,
+            BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID,
+            connectToServiceByUUIDFunc));
+
+    //  writeData()
+    AceFunction  writeDataFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_SOCKET_API_WRITE_DATA,
+            BLUETOOTH_SOCKET_API_WRITE_DATA,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_SOCKET_API_WRITE_DATA,
+            writeDataFunc));
+
+    //  readData()
+    AceFunction  readDataFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_SOCKET_API_READ_DATA,
+            BLUETOOTH_SOCKET_API_READ_DATA,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_SOCKET_API_READ_DATA,
+            readDataFunc));
+
+    //  close()
+    AceFunction  closeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_SOCKET_API_CLOSE,
+            BLUETOOTH_SOCKET_API_CLOSE,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_SOCKET_API_CLOSE,
+            closeFunc));
+
+    //  hasService()
+    AceFunction  hasServiceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_CLASS_API_HAS_SERVICE,
+            BLUETOOTH_CLASS_API_HAS_SERVICE,
+            BLUETOOTH_FEATURES_BLUETOOTH_GAP,
+            DEVICE_LIST_BLUETOOTH_GAP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_CLASS_API_HAS_SERVICE,
+            hasServiceFunc));
+
+    //  unregister()
+    AceFunction  unregisterFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER,
+            BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER,
+            BLUETOOTH_FEATURES_BLUETOOTH_SPP,
+            DEVICE_LIST_BLUETOOTH_SPP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER,
+            unregisterFunc));
+
+    //  registerSinkApplication()
+    AceFunction  registerSinkApplicationFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_HEALTH_PROFILE_HANDLER_API_REGISTER_SINK_APPLICATION,
+            BLUETOOTH_HEALTH_PROFILE_HANDLER_API_REGISTER_SINK_APPLICATION,
+            BLUETOOTH_FEATURES_BLUETOOTH_HDP,
+            DEVICE_LIST_BLUETOOTH_HDP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_HEALTH_PROFILE_HANDLER_API_REGISTER_SINK_APPLICATION,
+            registerSinkApplicationFunc));
+
+    //  connectToSource()
+    AceFunction  connectToSourceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_HEALTH_PROFILE_HANDLER_API_CONNECT_TO_SOURCE,
+            BLUETOOTH_HEALTH_PROFILE_HANDLER_API_CONNECT_TO_SOURCE,
+            BLUETOOTH_FEATURES_BLUETOOTH_HDP,
+            DEVICE_LIST_BLUETOOTH_HDP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_HEALTH_PROFILE_HANDLER_API_CONNECT_TO_SOURCE,
+            connectToSourceFunc));
+
+    //  unregister()
+    AceFunction  unregisterHDPFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_HEALTH_APPLICATION_API_UNREGISTER,
+            BLUETOOTH_HEALTH_APPLICATION_API_UNREGISTER,
+            BLUETOOTH_FEATURES_BLUETOOTH_HDP,
+            DEVICE_LIST_BLUETOOTH_HDP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_HEALTH_APPLICATION_API_UNREGISTER,
+            unregisterHDPFunc));
+
+    //  close()
+    AceFunction  closeHDPFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_HEALTH_CHANNEL_API_CLOSE,
+            BLUETOOTH_HEALTH_CHANNEL_API_CLOSE,
+            BLUETOOTH_FEATURES_BLUETOOTH_HDP,
+            DEVICE_LIST_BLUETOOTH_HDP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_HEALTH_CHANNEL_API_CLOSE,
+            closeHDPFunc));
+
+    //  sendData()
+    AceFunction  sendDataFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_HEALTH_CHANNEL_API_SEND_DATA,
+            BLUETOOTH_HEALTH_CHANNEL_API_SEND_DATA,
+            BLUETOOTH_FEATURES_BLUETOOTH_HDP,
+            DEVICE_LIST_BLUETOOTH_HDP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_HEALTH_CHANNEL_API_SEND_DATA,
+            sendDataFunc));
+
+    //  setListener()
+    AceFunction  setListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_HEALTH_CHANNEL_API_SET_LISTENER,
+            BLUETOOTH_HEALTH_CHANNEL_API_SET_LISTENER,
+            BLUETOOTH_FEATURES_BLUETOOTH_HDP,
+            DEVICE_LIST_BLUETOOTH_HDP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_HEALTH_CHANNEL_API_SET_LISTENER,
+            setListenerFunc));
+
+    //  unsetListener()
+    AceFunction  unsetListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_BLUETOOTH_HEALTH_CHANNEL_API_UNSET_LISTENER,
+            BLUETOOTH_HEALTH_CHANNEL_API_UNSET_LISTENER,
+            BLUETOOTH_FEATURES_BLUETOOTH_HDP,
+            DEVICE_LIST_BLUETOOTH_HDP);
+
+    BluetoothMapping.insert(std::make_pair(
+            BLUETOOTH_HEALTH_CHANNEL_API_UNSET_LISTENER,
+            unsetListenerFunc));
+
+    return BluetoothMapping;
+}
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bluetooth/plugin_config.h b/src/Bluetooth/plugin_config.h
new file mode 100644 (file)
index 0000000..a44485a
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _BLUETOOTH_PLUGIN_CONFIG_H_
+#define _BLUETOOTH_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+DECLARE_FUNCTION_GETTER(Bluetooth);
+
+#define BLUETOOTH_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getBluetoothFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _BLUETOOTH_PLUGIN_CONFIG_H_
\ No newline at end of file
diff --git a/src/Bluetooth/plugin_config_impl.h b/src/Bluetooth/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..4d7668a
--- /dev/null
@@ -0,0 +1,75 @@
+#ifndef _BLUETOOTH_PLUGIN_CONFIG_IMPL_H_\r
+#define _BLUETOOTH_PLUGIN_CONFIG_IMPL_H_\r
+\r
+namespace DeviceAPI {\r
+namespace Bluetooth {\r
+\r
+// attributes\r
+#define BLUETOOTH_MANAGER_DEVICE_MAJOR "deviceMajor"\r
+#define BLUETOOTH_MANAGER_DEVICE_MINOR "deviceMinor"\r
+#define BLUETOOTH_MANAGER_DEVICE_SERVICE "deviceService"\r
+#define BLUETOOTH_ADAPTER_NAME "name"\r
+#define BLUETOOTH_ADAPTER_ADDRESS "address"\r
+#define BLUETOOTH_ADAPTER_POWERED "powered"\r
+#define BLUETOOTH_ADAPTER_VISIBLE "visible"\r
+#define BLUETOOTH_DEVICE_NAME "name"\r
+#define BLUETOOTH_DEVICE_ADDRESS "address"\r
+#define BLUETOOTH_DEVICE_DEVICE_CLASS "deviceClass"\r
+#define BLUETOOTH_DEVICE_IS_BONDED "isBonded"\r
+#define BLUETOOTH_DEVICE_IS_TRUSTED "isTrusted"\r
+#define BLUETOOTH_DEVICE_IS_CONNECTED "isConnected"\r
+#define BLUETOOTH_DEVICE_UUIDS "uuids"\r
+#define BLUETOOTH_SOCKET_UUID "uuid"\r
+#define BLUETOOTH_SOCKET_STATE "state"\r
+#define BLUETOOTH_SOCKET_PEER "peer"\r
+#define BLUETOOTH_SOCKET_ONMESSAGE "onmessage"\r
+#define BLUETOOTH_SOCKET_ONCLOSE "onclose"\r
+#define BLUETOOTH_SOCKET_ONERROR "onerror"\r
+#define BLUETOOTH_CLASS_MAJOR "major"\r
+#define BLUETOOTH_CLASS_MINOR "minor"\r
+#define BLUETOOTH_CLASS_SERVICES "services"\r
+#define BLUETOOTH_SERVICE_HANDLER_UUID "uuid"\r
+#define BLUETOOTH_SERVICE_HANDLER_NAME "name"\r
+#define BLUETOOTH_SERVICE_HANDLER_IS_CONNECTED "isConnected"\r
+#define BLUETOOTH_SERVICE_HANDLER_ONCONNECT "onconnect"\r
+#define BLUETOOTH_PROFILE_TYPE "profileType"\r
+#define BLUETOOTH_HEALTH_APPLICATION_DATA_TYPE "dataType"\r
+#define BLUETOOTH_HEALTH_APPLICATION_NAME "name"\r
+#define BLUETOOTH_HEALTH_APPLICATION_ONCONNECT "onconnect"\r
+#define BLUETOOTH_HEALTH_CHANNEL_PEER "peer"\r
+#define BLUETOOTH_HEALTH_CHANNEL_TYPE "channelType"\r
+#define BLUETOOTH_HEALTH_CHANNEL_APP "application"\r
+#define BLUETOOTH_HEALTH_CHANNEL_IS_CONNECTED "isConnected"\r
+\r
+\r
+// functions\r
+#define BLUETOOTH_MANAGER_API_GET_DEFAULT_ADAPTER "getDefaultAdapter"\r
+#define BLUETOOTH_ADAPTER_API_SET_NAME "setName"\r
+#define BLUETOOTH_ADAPTER_API_SET_POWERED "setPowered"\r
+#define BLUETOOTH_ADAPTER_API_SET_VISIBLE "setVisible"\r
+#define BLUETOOTH_ADAPTER_API_DISCOVER_DEVICES "discoverDevices"\r
+#define BLUETOOTH_ADAPTER_API_STOP_DISCOVERY "stopDiscovery"\r
+#define BLUETOOTH_ADAPTER_API_GET_KNOWN_DEVICES "getKnownDevices"\r
+#define BLUETOOTH_ADAPTER_API_GET_DEVICE "getDevice"\r
+#define BLUETOOTH_ADAPTER_API_CREATE_BONDING "createBonding"\r
+#define BLUETOOTH_ADAPTER_API_DESTROY_BONDING "destroyBonding"\r
+#define BLUETOOTH_ADAPTER_API_REGISTER_RFCOMMSERVICE_BY_UUID "registerRFCOMMServiceByUUID"\r
+#define BLUETOOTH_ADAPTER_API_GET_BLUETOOTH_PROFILE_HANDLER "getBluetoothProfileHandler"\r
+#define BLUETOOTH_ADAPTER_API_SET_CHANGE_LISTENER "setChangeListener"\r
+#define BLUETOOTH_ADAPTER_API_UNSET_CHANGE_LISTENER "unsetChangeListener"\r
+#define BLUETOOTH_DEVICE_API_CONNECT_TO_SERVICE_BY_UUID "connectToServiceByUUID"\r
+#define BLUETOOTH_SOCKET_API_WRITE_DATA "writeData"\r
+#define BLUETOOTH_SOCKET_API_READ_DATA "readData"\r
+#define BLUETOOTH_SOCKET_API_CLOSE "close"\r
+#define BLUETOOTH_CLASS_API_HAS_SERVICE "hasService"\r
+#define BLUETOOTH_SERVICE_HANDLER_API_UNREGISTER "unregister"\r
+#define BLUETOOTH_HEALTH_PROFILE_HANDLER_API_REGISTER_SINK_APPLICATION "registerSinkApplication"\r
+#define BLUETOOTH_HEALTH_APPLICATION_API_UNREGISTER "healthUnregister"\r
+#define BLUETOOTH_HEALTH_PROFILE_HANDLER_API_CONNECT_TO_SOURCE "connectToSource"\r
+#define BLUETOOTH_HEALTH_CHANNEL_API_SEND_DATA "sendData"\r
+#define BLUETOOTH_HEALTH_CHANNEL_API_SET_LISTENER "setListener"\r
+#define BLUETOOTH_HEALTH_CHANNEL_API_UNSET_LISTENER "unsetListener"\r
+#define BLUETOOTH_HEALTH_CHANNEL_API_CLOSE "healthClose"\r
+}\r
+}\r
+#endif\r
diff --git a/src/Bluetooth/plugin_initializer.cpp b/src/Bluetooth/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..24379df
--- /dev/null
@@ -0,0 +1,111 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Security.h>
+#include <GlobalContextManager.h>
+#include "plugin_config.h"
+#include "JSBluetoothManager.h"
+#include "BluetoothAdapter.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bluetooth {
+
+AceSecurityStatus bluetoothAceCheckAccessFunction(const char* functionName)
+{
+    return BLUETOOTH_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerBluetoothSetter,
+    JSBluetoothManagerPriv, gSecurityAccessor);
+
+class_definition_options_t BluetoothOptions =
+{
+    JS_CLASS,
+    CREATE_INSTANCE,
+    ALWAYS_NOTICE,
+    USE_OVERLAYED,
+    AceCheckerBluetoothSetter,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Bluetooth] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor,
+        bluetoothAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Bluetooth] on_widget_stop_callback (%d)", widgetId);
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"Bluetooth");
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void *context)
+{
+    LOGD("[Tizen\\Bluetooth] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(
+        static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void *context)
+{
+    LOGD("[Tizen\\Bluetooth] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(
+        static_cast<JSContextRef>(context));
+    BluetoothAdapter::getInstance()->unloadFrame(
+        static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+    "bluetooth",
+    (js_class_template_getter)JSBluetoothManager::getClassRef,
+    &BluetoothOptions)
+PLUGIN_CLASS_MAP_END
+
+} // Bluetooth
+} // DeviceAPI
diff --git a/src/Bookmark/BookmarkData.h b/src/Bookmark/BookmarkData.h
new file mode 100755 (executable)
index 0000000..9422d94
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <boost/shared_ptr.hpp>
+#include <memory>
+
+#ifndef _BOOKMARKDATA_H_
+#define _BOOKMARKDATA_H_
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+#define UNDEFINED_ID -1
+
+enum bookmarkType {
+    BOOKMARKITEM_TYPE = 0,
+    BOOKMARKFOLDER_TYPE = 1
+};
+
+class BookmarkData {
+public:
+    BookmarkData(bookmarkType type, const std::string& title, const std::string& url, const int id = UNDEFINED_ID)
+        : m_type(type), m_title(title), m_url(url), m_id(id) {};
+    bookmarkType m_type;
+    std::string m_title;
+    std::string m_url;
+    int m_id;
+};
+
+typedef std::shared_ptr<BookmarkData> BookmarkDataPtr;
+}
+}
+#endif //_BOOKMARKDATA_H_
diff --git a/src/Bookmark/BookmarkManager.cpp b/src/Bookmark/BookmarkManager.cpp
new file mode 100755 (executable)
index 0000000..4ff92cd
--- /dev/null
@@ -0,0 +1,436 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "BookmarkManager.h"
+#include "BookmarkUtil.h"
+#include "JSBookmarkFolder.h"
+#include "JSBookmarkItem.h"
+#include <queue>
+#include <Ecore.h>
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <web_bookmark.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Bookmark{
+
+BookmarkDataPtr BookmarkManager::_makeBookmarkData(int id) {
+    LOGD("Enter id: %d", id);
+    bookmarkType type = BOOKMARKFOLDER_TYPE;
+    char *bpUrl = NULL;
+    char *bpTitle = NULL;
+    try {
+        if (id != rootFolderId) {
+            int bpType = 0;
+            if (bp_bookmark_adaptor_get_type(id, &bpType) < 0) {
+                LOGE("Can't get bookmark type");
+                throw bp_bookmark_adaptor_get_errorcode();
+            }
+            LOGD("type: %d", bpType);
+            if (bpType == 0) {
+                type = BOOKMARKITEM_TYPE;
+                if (bp_bookmark_adaptor_get_url(id, &bpUrl) < 0) {
+                    LOGE("Can't get bookmark url");
+                    throw bp_bookmark_adaptor_get_errorcode();
+                }
+                LOGD("url: %s", bpUrl);
+            } else {
+                type = BOOKMARKFOLDER_TYPE;
+            }
+            if (bp_bookmark_adaptor_get_title(id, &bpTitle) < 0) {
+                LOGE("Can't get bookmark title");
+                throw bp_bookmark_adaptor_get_errorcode();
+            }
+            LOGD("title: %s", bpTitle);
+        } else {
+            LOGD("root folder");
+        }
+    } catch (int err) {
+        if (bpUrl)
+            free(bpUrl);
+        if (bpTitle)
+            free(bpTitle);
+        throw err;
+    }
+    std::string url, title;
+    if (bpUrl) {
+        url = bpUrl;
+        free(bpUrl);
+    }
+    if (bpTitle) {
+        title = bpTitle;
+        free(bpTitle);
+    }
+    return BookmarkDataPtr(new BookmarkData(type, title, url, id));
+}
+
+int BookmarkManager::_get(int parentId, int** ids) {
+    LOGD("Enter: %d", parentId);
+    int ret = 0;
+    if (parentId != rootFolderId) {
+        //type check
+        int bpType = 0;
+        if (bp_bookmark_adaptor_get_type(parentId, &bpType) < 0) {
+            LOGE("Can't get bookmark type");
+            ret = bp_bookmark_adaptor_get_errorcode();
+            LOGE("ret : %d", ret);
+            BookmarkUtil::throwBookmarkException<NotFoundException>(ret, "bp_bookmark_adaptor_get_type()");
+        }
+        if (bpType != 1)
+            throw TypeMismatchException("Not folder");
+    }
+    int count = 0;
+    //get
+    if (bp_bookmark_adaptor_get_ids_p(ids, &count, -1/*No limitation*/
+            , 0/*offset*/, parentId/*parent id*/
+            , -1/*type:both item and folder*/, 0/*is_operator:made by user */
+            , -1/*is_editable:both*/,BP_BOOKMARK_O_DATE_CREATED/*order_offset*/
+            , 0/*ordering:ASC*/) < 0) {
+        LOGE("bp_bookmark_adaptor_get_ids_p failed");
+        ret = bp_bookmark_adaptor_get_errorcode();
+        if (ret == BP_BOOKMARK_ERROR_NO_DATA) {
+            LOGD("No data");
+            count = 0;
+        } else if (ret == BP_BOOKMARK_ERROR_DISK_BUSY) {
+            LOGE("ret : %d", ret);
+            BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_get_ids_p()");
+        } else if (ret == BP_BOOKMARK_ERROR_ID_NOT_FOUND) {
+            LOGE("ret : %d", ret);
+            BookmarkUtil::throwBookmarkException<NotFoundException>(ret, "bp_bookmark_adaptor_get_ids_p()");
+        } else {
+            LOGE("ret : %d", ret);
+            BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_get_ids_p()");
+        }
+    }
+    return count;
+}
+std::vector<BookmarkDataPtr> BookmarkManager::get(BookmarkSearchDataPtr &searchData){
+    LOGD("Entered");
+    if (!bInit) {
+        if (!_initialize())
+            throw UnknownException("Unknown Error");
+    }
+    int count = -1;
+    int *ids = NULL;
+    int *childIds = NULL;
+    std::vector<BookmarkDataPtr> bookmarkArray;
+
+    int parentId;
+    if (searchData->m_bookmark)
+        parentId = searchData->m_bookmark->m_id;
+    else
+        parentId = rootFolderId;
+
+    bool bRecursive = searchData->m_recursive;
+    try {
+        if (bRecursive && (parentId == rootFolderId)) { // get all items
+            bp_bookmark_property_cond_fmt properties;
+            bp_bookmark_rows_cond_fmt conds; //conditions for querying
+            memset(&properties, 0x00, sizeof(bp_bookmark_property_cond_fmt));
+            memset(&conds, 0x00, sizeof(bp_bookmark_rows_cond_fmt));
+            properties.parent = -1;
+            properties.type = -1;
+            properties.is_operator = -1;
+            properties.is_editable = -1;
+            conds.limit = -1;
+            conds.offset = 0;
+            conds.order_offset = BP_BOOKMARK_O_DATE_CREATED;
+            conds.ordering = 0;
+            conds.period_offset = BP_BOOKMARK_O_DATE_CREATED;
+            conds.period_type = BP_BOOKMARK_DATE_ALL;
+            if (bp_bookmark_adaptor_get_cond_ids_p(&ids, &count,
+                &properties, &conds, 0, NULL, 0) < 0) {
+                LOGE("bp_bookmark_adaptor_get_cond_ids_p is failed");
+                int ret = bp_bookmark_adaptor_get_errorcode();
+                std::string errMessage = BookmarkUtil::getBookmarkErrorMessage(ret);
+                LOGE("error: %s", errMessage.c_str());
+                if (ret == BP_BOOKMARK_ERROR_NO_DATA) {
+                    LOGD("No data");
+                    count = 0;
+                } else if (ret == BP_BOOKMARK_ERROR_DISK_BUSY) {
+                    LOGE("ret : %d", ret);
+                    BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_get_cond_ids_p()");
+                } else
+                    throw UnknownException("Unknown Error");
+            }
+            bRecursive = false;
+        } else {
+            count = _get(parentId, &ids);
+            LOGD("count:", count);
+        }
+        for (int i=0; i<count; i++) {
+            BookmarkDataPtr bookmark;
+            try {
+                LOGD("id: %d", ids[i]);
+                bookmark = _makeBookmarkData(ids[i] );
+                bookmarkArray.push_back(bookmark);
+            } catch (int errCode) {
+                LOGE("Error occurs during making BookmarkData: %s", BookmarkUtil::getBookmarkErrorMessage(errCode).c_str());
+            }
+            //If recursive is true and bookmark's type is folder, it has to get sub items.
+            if (bookmark && bRecursive && (bookmark->m_type == BOOKMARKFOLDER_TYPE)) {
+                int childCount = _get(ids[i], &childIds);
+                LOGD("child count: %d", childCount);
+                //add child ids to ids
+                if (childIds && (childCount > 0)) {
+                    int *tempIds = (int *)calloc(count+childCount, sizeof(int));
+                    memcpy(tempIds, ids, count*sizeof(int));
+                    memcpy(tempIds+count, tempIds, childCount*sizeof(int));
+                    free(childIds);
+                    childIds = NULL;
+                    free(ids);
+                    count += childCount;
+                    ids = tempIds;
+                }
+            }
+        }
+    } catch ( const BasePlatformException& err) {
+        if (ids)
+            free(ids);
+        if (childIds)
+            free(childIds);
+        throw err;
+    }
+    if (ids)
+        free(ids);
+    if (childIds)
+        free(childIds);
+    return bookmarkArray;
+}
+
+int BookmarkManager::add(bookmarkType type, const int parent_id, const std::string& title, const std::string& url) {
+    LOGD("Entered");
+    if (!bInit) {
+        if (!_initialize())
+            throw UnknownException("Unknown Error");
+    }
+
+    if (title.length() == 0)
+        throw InvalidValuesException("empty title");
+    if  ((type == BOOKMARKITEM_TYPE) && (url.length() == 0))
+        throw InvalidValuesException("empty url");
+
+    int newId = UNDEFINED_ID;
+    int count = -1;
+    int *ids = NULL;
+    int ret = BP_BOOKMARK_ERROR_NONE;
+    std::string errMessage;
+    try {
+        if (bp_bookmark_adaptor_create(&newId) < 0) {
+            ret = bp_bookmark_adaptor_get_errorcode();
+            errMessage = BookmarkUtil::getBookmarkErrorMessage(ret);
+            LOGE("Failed to create new bookmark: %s", errMessage.c_str());
+            if (ret == BP_BOOKMARK_ERROR_IO_ERROR)
+                BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_create()");
+            else
+                throw UnknownException("Unknown Error");
+        }
+
+        if (bp_bookmark_adaptor_set_parent_id(newId, parent_id) < 0) {
+            ret = bp_bookmark_adaptor_get_errorcode();
+            errMessage = BookmarkUtil::getBookmarkErrorMessage(ret);
+            LOGE("failed to set parent: %s", errMessage.c_str());
+            if (ret == BP_BOOKMARK_ERROR_ID_NOT_FOUND)
+                BookmarkUtil::throwBookmarkException<NotFoundException>(ret, "bp_bookmark_adaptor_set_parent_id()");
+            else
+                throw UnknownException("Unknown Error");
+        }
+
+        bp_bookmark_property_cond_fmt properties;
+        bp_bookmark_rows_cond_fmt conds; //conditions for querying
+        memset(&properties, 0x00, sizeof(bp_bookmark_property_cond_fmt));
+        memset(&conds, 0x00, sizeof(bp_bookmark_rows_cond_fmt));
+        if (type == BOOKMARKITEM_TYPE) {
+            properties.parent = -1; /*parent id:root*/
+            properties.type = 0; /*type:item*/
+            properties.is_operator = 0; /*is_operator:made by user*/
+            properties.is_editable = -1; /*is_editable:both*/
+            conds.limit = -1; /*No limitation*/
+            conds.offset = 0; /*offset*/
+            conds.order_offset = BP_BOOKMARK_O_DATE_CREATED;
+            conds.ordering = 0; /*ordering:ASC*/
+            conds.period_offset = BP_BOOKMARK_O_DATE_CREATED;
+            conds.period_type = BP_BOOKMARK_DATE_ALL;
+            if (bp_bookmark_adaptor_get_cond_ids_p(&ids, &count,
+                &properties, &conds,
+                BP_BOOKMARK_O_URL/*check_offset*/
+                , url.c_str()/*keyword*/, 0/*is_like:EQUAL*/) == 0) {
+                if (count > 0)
+                    throw InvalidValuesException("Already Exist");
+            }
+            if (bp_bookmark_adaptor_set_type(newId,0) < 0) {
+                ret = bp_bookmark_adaptor_get_errorcode();
+                LOGE("ret : %d", ret);
+                BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_set_type()");
+            }
+            if (bp_bookmark_adaptor_set_url(newId, url.c_str()) < 0) {
+                ret = bp_bookmark_adaptor_get_errorcode();
+                LOGE("ret : %d", ret);
+                BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_set_url()");
+            }
+        } else {
+            properties.parent = parent_id; /*parent id*/
+            properties.type = 1; /*type:folder*/
+            properties.is_operator = -1; /*is_operator:both*/
+            properties.is_editable = -1; /*is_editable:both*/
+            conds.limit = -1; /*No limitation*/
+            conds.offset = 0;
+            conds.order_offset = BP_BOOKMARK_O_DATE_CREATED;
+            conds.ordering = 0; /*ordering:ASC*/
+            conds.period_offset = BP_BOOKMARK_O_DATE_CREATED;
+            conds.period_type = BP_BOOKMARK_DATE_ALL;
+            if (bp_bookmark_adaptor_get_cond_ids_p(&ids, &count,
+                &properties, &conds,
+                BP_BOOKMARK_O_TITLE/*check_offset*/
+                , title.c_str()/*keyword*/, 0/*is_like:EQUAL*/) == 0) {
+                for (int i=0; i<count; i++) {
+                    int myParentId = 0;
+                    if (bp_bookmark_adaptor_get_parent_id(ids[i], &myParentId) == 0) {
+                        if (myParentId == parent_id)
+                            throw InvalidValuesException("Already Exist");
+                    }
+                }
+                if (bp_bookmark_adaptor_set_type(newId,1) < 0) {
+                    ret = bp_bookmark_adaptor_get_errorcode();
+                    LOGE("ret : %d", ret);
+                    BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_set_type()");
+                }
+            }
+        }
+
+        if (bp_bookmark_adaptor_set_title(newId, title.c_str()) < 0) {
+            ret = bp_bookmark_adaptor_get_errorcode();
+            LOGE("ret : %d", ret);
+            BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_set_type()");
+        }
+    } catch (const BasePlatformException& err) {
+        if (ids)
+            free(ids);
+        if (newId != UNDEFINED_ID)
+            bp_bookmark_adaptor_delete(newId);
+        throw err;
+    }
+    if (ids)
+        free(ids);
+    return newId;
+}
+
+void BookmarkManager::remove(BookmarkSearchDataPtr &searchData) {
+    LOGD("Entered");
+    if (!bInit) {
+        if (!_initialize())
+            throw UnknownException("Unknown Error");
+    }
+
+    int ret = BP_BOOKMARK_ERROR_NONE;
+    std::string errMessage;
+    if (searchData->m_bookmark == NULL) {
+        if (bp_bookmark_adaptor_reset() < 0) {
+            ret = bp_bookmark_adaptor_get_errorcode();
+            errMessage = BookmarkUtil::getBookmarkErrorMessage(ret);
+            LOGE("Failed to delete all bookmarks: %s", errMessage.c_str());
+            if (ret == BP_BOOKMARK_ERROR_NO_DATA) {
+                LOGD("No data to delete");
+            }
+            else if ((ret == BP_BOOKMARK_ERROR_IO_ERROR) || (ret == BP_BOOKMARK_ERROR_DISK_BUSY)) {
+                LOGE("ret : %d", ret);
+                BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_reset()");
+            }
+            else {
+                throw UnknownException("Unknown Error");
+            }
+        }
+    } else if (bp_bookmark_adaptor_delete((searchData->m_bookmark)->m_id) < 0) {
+        ret = bp_bookmark_adaptor_get_errorcode();
+        errMessage = BookmarkUtil::getBookmarkErrorMessage(ret);
+        LOGE("Failed to delete bookmark: %s", errMessage.c_str());
+        if (ret == BP_BOOKMARK_ERROR_NO_DATA) {
+            LOGD("No data to delete");
+        }
+        else if (ret == BP_BOOKMARK_ERROR_ID_NOT_FOUND) {
+            LOGD("Not found");
+        }
+        else if ((ret == BP_BOOKMARK_ERROR_IO_ERROR) || (ret == BP_BOOKMARK_ERROR_DISK_BUSY)) {
+            LOGE("ret : %d", ret);
+            BookmarkUtil::throwBookmarkException(ret, "bp_bookmark_adaptor_reset()");
+        }
+        else {
+            throw UnknownException("Unknown Error");
+        }
+    }
+}
+
+bool BookmarkManager::findParent(BookmarkParentSearchDataPtr &parentSearchData) {
+    LOGD("Enter");
+    if (!bInit) {
+        if (!_initialize())
+            throw UnknownException("Unknown Error");
+    }
+    int parentId = 0;
+    if (bp_bookmark_adaptor_get_parent_id(parentSearchData->m_id, &parentId) < 0) {
+        LOGE("Can't get bookmark parentId: %s", BookmarkUtil::getBookmarkErrorMessage(bp_bookmark_adaptor_get_errorcode()).c_str());
+        return false;
+    }
+
+    try {
+        parentSearchData->m_parent = _makeBookmarkData(parentId);
+        LOGD("find parent");
+        return true;
+    } catch (int errCode) {
+        LOGE("Error occurs during making parent BookmarkData: %s", BookmarkUtil::getBookmarkErrorMessage(errCode).c_str());
+        return false;
+    }
+}
+
+int BookmarkManager::getRootFolderId() {
+    return rootFolderId;
+
+}
+
+BookmarkManager* BookmarkManager::getInstance(){
+    static BookmarkManager instance;
+    return &instance;
+}
+
+bool BookmarkManager::_initialize() {
+    if (bp_bookmark_adaptor_initialize() < 0) {
+        LOGE("fail to initialize: %s", BookmarkUtil::getBookmarkErrorMessage(bp_bookmark_adaptor_get_errorcode()).c_str());
+        bInit = false;
+    } else {
+        bInit = true;
+    }
+    if (bp_bookmark_adaptor_get_root(&rootFolderId) < 0) {
+        LOGE("Can't get root id: %s", BookmarkUtil::getBookmarkErrorMessage(bp_bookmark_adaptor_get_errorcode()).c_str());
+        rootFolderId = 0;
+    }
+    return bInit;
+}
+BookmarkManager::BookmarkManager(){
+    rootFolderId = 0;
+    bInit = false;
+    if (!_initialize())
+        LOGE("initialize fail");
+}
+BookmarkManager::~BookmarkManager(){
+    if (bp_bookmark_adaptor_deinitialize() < 0)
+        LOGE("fail to deinitialize: %s", BookmarkUtil::getBookmarkErrorMessage(bp_bookmark_adaptor_get_errorcode()).c_str());
+}
+
+}
+}
+
diff --git a/src/Bookmark/BookmarkManager.h b/src/Bookmark/BookmarkManager.h
new file mode 100755 (executable)
index 0000000..4bf637e
--- /dev/null
@@ -0,0 +1,80 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _BOOKMARKMANAGER_
+#define _BOOKMARKMANAGER_
+
+#include <map>
+#include <string>
+#include <vector>
+#include <boost/shared_ptr.hpp>
+#include <stdio.h>
+#include <CallbackUserData.h>
+#include "BookmarkData.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bookmark{
+
+class BookmarkSearchData {
+    public:
+        BookmarkSearchData(BookmarkData *bookmarkData, bool recursive = true)
+            : m_bookmark(bookmarkData), m_recursive(recursive) {}
+        BookmarkData *m_bookmark;
+        bool m_recursive;
+
+};
+typedef std::shared_ptr<BookmarkSearchData> BookmarkSearchDataPtr;
+
+class BookmarkParentSearchData {
+    public:
+        BookmarkParentSearchData(int id) : m_id(id) {}
+        int m_id;
+        BookmarkDataPtr m_parent;
+};
+typedef std::shared_ptr<BookmarkParentSearchData> BookmarkParentSearchDataPtr;
+
+class BookmarkManager{
+    public:
+        std::vector<BookmarkDataPtr> get(BookmarkSearchDataPtr &searchData);
+        int add(bookmarkType type, const int parent_id, const std::string& title, const std::string& url = "");
+        void remove(BookmarkSearchDataPtr &searchData);
+        bool findParent(BookmarkParentSearchDataPtr &parentSearchData);
+        int getRootFolderId();
+        static BookmarkManager* getInstance();
+
+    private:
+        bool bInit;
+        int rootFolderId;
+        BookmarkManager();
+        ~BookmarkManager();
+        std::string _getErrorMessage(int errorCode);
+        BookmarkDataPtr _makeBookmarkData(int id/*, int parentId*/);
+        bool _initialize();
+        int _get(int parentId, int** ids);
+
+};
+
+
+
+}
+}
+
+#endif //_BOOKMARKMANAGER_
+
diff --git a/src/Bookmark/BookmarkUtil.cpp b/src/Bookmark/BookmarkUtil.cpp
new file mode 100644 (file)
index 0000000..2862b65
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "BookmarkUtil.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include <sstream>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+std::string& BookmarkUtil::getBookmarkErrorMessage(const int errorCode){
+    switch(errorCode) {
+        case BP_BOOKMARK_ERROR_INVALID_PARAMETER:
+            return errInvalidParameter;
+        case BP_BOOKMARK_ERROR_OUT_OF_MEMORY:
+            return errOutOfMemory;
+        case BP_BOOKMARK_ERROR_IO_ERROR:
+            return errIOError;
+        case BP_BOOKMARK_ERROR_NO_DATA:
+            return errNoData;
+        case BP_BOOKMARK_ERROR_ID_NOT_FOUND:
+            return errIDNotFound;
+        case BP_BOOKMARK_ERROR_DUPLICATED_ID:
+            return errDuplicatedId;
+        case BP_BOOKMARK_ERROR_PERMISSION_DENY:
+            return errPermissionDenied;
+        case BP_BOOKMARK_ERROR_DISK_BUSY:
+            return errDiskBusy;
+        case BP_BOOKMARK_ERROR_DISK_FULL:
+            return errDiskFull;
+        case BP_BOOKMARK_ERROR_TOO_BIG_DATA:
+            return errTooBigData;
+        default:
+            return errUnknown;
+    }
+}
+
+std::string BookmarkUtil::getBookmarkLogMessage(const int errorCode, const std::string &hint){
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getBookmarkErrorMessage(errorCode) << ", " << errorCode;
+    return std::string(ss.str());
+}
+
+} // Bookmark
+} // DeviceAPI
diff --git a/src/Bookmark/BookmarkUtil.h b/src/Bookmark/BookmarkUtil.h
new file mode 100644 (file)
index 0000000..21fe7e0
--- /dev/null
@@ -0,0 +1,57 @@
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_BOOKMARK_UTIL_H__
+#define __TIZEN_BOOKMARK_UTIL_H__
+
+#include <string>
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <web_bookmark.h>
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+static std::string errInvalidParameter = "Invalid parameter";
+static std::string errOutOfMemory = "Out of memory";
+static std::string errIOError = "IO Error";
+static std::string errNoData = "No data";
+static std::string errIDNotFound = "ID not Found";
+static std::string errDuplicatedId = "Duplicated ID";
+static std::string errPermissionDenied = "Permission denied";
+static std::string errDiskBusy = "Disk Busy";
+static std::string errDiskFull= "Disk Full";
+static std::string errTooBigData = "Too Big Data";
+static std::string errUnknown = "Unknown error";
+
+class BookmarkUtil {
+public:
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwBookmarkException(const int errorCode, const std::string &hint)
+    {
+        std::string log = BookmarkUtil::getBookmarkLogMessage(errorCode, hint);
+        LOGE("%s", log.c_str());
+        throw T(log.c_str());
+    }
+    static std::string& getBookmarkErrorMessage(const int errorCode);
+    static std::string getBookmarkLogMessage(const int errorCode, const std::string &hint);
+};
+
+} // Bookmark
+} // DeviceAPI
+
+#endif // __TIZEN_BOOKMARK_UTIL_H__
diff --git a/src/Bookmark/CMakeLists.txt b/src/Bookmark/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..08fc6c7
--- /dev/null
@@ -0,0 +1,48 @@
+SET(TARGET_NAME ${bookmark_target})
+SET(DESTINATION_NAME ${bookmark_dest})
+SET(TARGET_IMPL_NAME ${bookmark_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_bookmark REQUIRED bookmark-adaptor)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_bookmark_INCLUDE_DIRS}
+)
+
+SET(SRCS_IMPL
+    JSBookmarkManager.cpp
+    BookmarkManager.cpp
+    JSBookmarkFolder.cpp
+    JSBookmarkItem.cpp
+    BookmarkUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${platform_pkgs_bookmark_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/bookmark
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Bookmark/JSBookmarkFolder.cpp b/src/Bookmark/JSBookmarkFolder.cpp
new file mode 100755 (executable)
index 0000000..f1443df
--- /dev/null
@@ -0,0 +1,172 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <CommonsJavaScript/Converter.h>
+#include <PlatformException.h>
+#include "JSBookmarkFolder.h"
+#include "BookmarkManager.h"
+#include "BookmarkData.h"
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+#define TIZEN_BOOKMARKFOLDER_PARENT "parent"
+#define TIZEN_BOOKMARKFOLDER_TITLE "title"
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+JSClassRef JSBookmarkFolder::m_jsClassRef = NULL;
+
+JSClassDefinition JSBookmarkFolder::m_jsClassInfo = {
+    0, // current (and only) version is 0
+    kJSClassAttributeNone, //attributes
+    "BookmarkFolder", //class name
+    NULL, // parent class
+    JSBookmarkFolder::m_property, //static values
+    NULL, // static functions
+    JSBookmarkFolder::initialize, // initialize
+    JSBookmarkFolder::finalize, //finalize
+    NULL, //hasProperty
+    NULL, //getProperty
+    NULL, //setProperty
+    NULL, //deleteProperty
+    NULL, //getPropertyNames
+    NULL, // callAsFunction
+    NULL, // constructor
+    NULL,
+    NULL // convertToType
+};
+
+
+JSStaticValue JSBookmarkFolder::m_property[] =
+{
+    {TIZEN_BOOKMARKFOLDER_PARENT,  getProperty, NULL, kJSPropertyAttributeReadOnly},
+    {TIZEN_BOOKMARKFOLDER_TITLE,  getProperty, NULL, kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef JSBookmarkFolder::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBookmarkFolder::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+void JSBookmarkFolder::initialize(JSContextRef ctx, JSObjectRef object)
+{
+    LOGD("JSBookmarkFolder::initialize()\n");
+}
+
+void JSBookmarkFolder::finalize(JSObjectRef object)
+{
+    LOGD("JSBookmarkFolder::finalize()\n");
+
+    BookmarkData * priv = static_cast<BookmarkData *>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSObjectRef JSBookmarkFolder::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    LOGD("Enter");
+    JSObjectRef bookmarkFolder = NULL;
+    try {
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+
+        std::string title = validator.toString(0);
+        bookmarkFolder = createJSObject(ctx, title);
+    } catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        bookmarkFolder = createJSObject(ctx, "");
+    }
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(ctx, bookmarkFolder, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+    return bookmarkFolder;
+}
+
+JSObjectRef JSBookmarkFolder::createJSObject(JSContextRef context, const std::string &title) {
+    return createJSObject(context, title, UNDEFINED_ID);
+}
+
+JSObjectRef JSBookmarkFolder::createJSObject(JSContextRef context, const std::string &title, const int id) {
+    LOGD("Enter");
+
+    BookmarkData *priv = new BookmarkData(BOOKMARKFOLDER_TYPE, title, "", id);
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), priv);
+    return obj;
+}
+
+JSValueRef JSBookmarkFolder::getParent(JSContextRef context, JSObjectRef object) {
+    LOGD("Enter");;
+    BookmarkData * priv = static_cast<BookmarkData *>(JSObjectGetPrivate(object));
+
+    if (!priv)
+        throw TypeMismatchException("Private data is null");
+
+    LOGD("bookmark id: %d", priv->m_id);
+    if (priv->m_id != UNDEFINED_ID) {
+        BookmarkParentSearchDataPtr parentSearchData(new BookmarkParentSearchData(priv->m_id));
+        bool isAlive = BookmarkManager::getInstance()->findParent(parentSearchData);
+        if (isAlive) {
+            LOGD("Alive");
+            if ((parentSearchData->m_parent)->m_id == BookmarkManager::getInstance()->getRootFolderId())
+                return JSValueMakeNull(context);
+            else
+                return createJSObject(context, (parentSearchData->m_parent)->m_title, (parentSearchData->m_parent)->m_id);
+        }
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSBookmarkFolder::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    LOGD("Enter");
+
+    try {
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_BOOKMARKFOLDER_PARENT)) {
+            return getParent(context, object);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_BOOKMARKFOLDER_TITLE)) {
+            Converter convert(context);
+            BookmarkData *priv = static_cast<BookmarkData *>(JSObjectGetPrivate(object));
+            if (!priv)
+                throw TypeMismatchException("Private data is null");
+            return convert.toJSValueRef(priv->m_title);
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (const WrtDeviceApis::Commons::ConversionException& err) {
+        LOGE("Converting fail");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // Bookmark
+} // TizenApis
+
diff --git a/src/Bookmark/JSBookmarkFolder.h b/src/Bookmark/JSBookmarkFolder.h
new file mode 100755 (executable)
index 0000000..62040f3
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _JS_BOOKMARKFOLDER_H_
+#define _JS_BOOKMARKFOLDER_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+class JSBookmarkFolder
+{
+  public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSObjectRef createJSObject(JSContextRef context, const std::string &title);
+    static JSObjectRef createJSObject(JSContextRef context, const std::string &title, const int id);
+    static JSValueRef getParent(JSContextRef context, JSObjectRef object);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+  private:
+
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+    static JSStaticValue m_property[];
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+};
+
+}
+}
+
+#endif /* _JS_BOOKMARKFOLDER_H_ */
+
+
+
diff --git a/src/Bookmark/JSBookmarkItem.cpp b/src/Bookmark/JSBookmarkItem.cpp
new file mode 100755 (executable)
index 0000000..5c4ee5b
--- /dev/null
@@ -0,0 +1,158 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSBookmarkItem.h"
+#include "JSBookmarkFolder.h"
+#include "BookmarkData.h"
+#include <JSWebAPIErrorFactory.h>
+#include <CommonsJavaScript/Converter.h>
+#include <ArgumentValidator.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+#define TIZEN_BOOKMARKITEM_PARENT "parent"
+#define TIZEN_BOOKMARKITEM_TITLE "title"
+#define TIZEN_BOOKMARKITEM_URL "url"
+
+JSClassRef JSBookmarkItem::m_jsClassRef = NULL;
+
+JSClassDefinition JSBookmarkItem::m_jsClassInfo = {
+    0, // current (and only) version is 0
+    kJSClassAttributeNone, //attributes
+    "BookmarkItem", //class name
+    NULL, // parent class
+    JSBookmarkItem::m_property, //static values
+    NULL, // static functions
+    JSBookmarkItem::initialize, // initialize
+    JSBookmarkItem::finalize, //finalize
+    NULL, //hasProperty
+    NULL, //getProperty
+    NULL, //setProperty
+    NULL, //deleteProperty
+    NULL, //getPropertyNames
+    NULL, // callAsFunction
+    NULL, // constructor
+    NULL,
+    NULL // convertToType
+};
+
+
+JSStaticValue JSBookmarkItem::m_property[] =
+{
+    {TIZEN_BOOKMARKITEM_PARENT,  getProperty, NULL, kJSPropertyAttributeReadOnly},
+    {TIZEN_BOOKMARKITEM_TITLE,  getProperty, NULL, kJSPropertyAttributeReadOnly},
+    {TIZEN_BOOKMARKITEM_URL,  getProperty, NULL, kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+
+const JSClassRef JSBookmarkItem::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+const JSClassDefinition* JSBookmarkItem::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+
+void JSBookmarkItem::initialize(JSContextRef ctx, JSObjectRef object)
+{
+    LOGD("JSBookmarkItem::initialize()");
+}
+
+void JSBookmarkItem::finalize(JSObjectRef object)
+{
+    LOGD("JSBookmarkItem::finalize()");
+    BookmarkData *priv = static_cast<BookmarkData *>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSObjectRef JSBookmarkItem::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception) {
+    LOGD("JSBookmarkItem::constructor()");
+    ArgumentValidator validator(ctx, argumentCount, arguments);
+    JSObjectRef bookmarkItem = NULL;
+    try {
+        std::string title = validator.toString(0);
+        std::string url = validator.toString(1);
+        bookmarkItem = createJSObject(ctx, title, url);
+    } catch(const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        bookmarkItem = createJSObject(ctx, "", "");
+    }
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(ctx, bookmarkItem, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+    return bookmarkItem;
+}
+
+JSObjectRef JSBookmarkItem::createJSObject(JSContextRef context, const std::string &title, const std::string &url) {
+    LOGD("Enter");
+    return createJSObject(context, title, url, UNDEFINED_ID);
+}
+JSObjectRef JSBookmarkItem::createJSObject(JSContextRef context, const std::string &title, const std::string &url, const int id) {
+    LOGD("Enter");
+
+    BookmarkData *priv = new BookmarkData(BOOKMARKITEM_TYPE, title, url, id);
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), priv);
+    return obj;
+}
+
+JSValueRef JSBookmarkItem::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    LOGD("Enter");
+    try {
+        Converter convert(context);
+        BookmarkData *priv = static_cast<BookmarkData *>(JSObjectGetPrivate(object));
+
+        if (!priv) {
+            LOGE("NULL private data");
+            throw TypeMismatchException("Private data is null");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_BOOKMARKITEM_PARENT)) {
+            return JSBookmarkFolder::getParent(context, object);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_BOOKMARKITEM_TITLE)) {
+            return convert.toJSValueRef(priv->m_title);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_BOOKMARKITEM_URL)) {
+            return convert.toJSValueRef(priv->m_url);
+        }
+    } catch(const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch(const WrtDeviceApis::Commons::ConversionException& err) {
+        LOGE("Converting fail");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+
+} // Bookmark
+} // TizenApis
+
diff --git a/src/Bookmark/JSBookmarkItem.h b/src/Bookmark/JSBookmarkItem.h
new file mode 100755 (executable)
index 0000000..8f7a9de
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _JS_BOOKMARKITEM_H_
+#define _JS_BOOKMARKITEM_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+class JSBookmarkItem
+{
+  public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSObjectRef createJSObject(JSContextRef context, const std::string &title, const std::string &url);
+    static JSObjectRef createJSObject(JSContextRef context, const std::string &title, const std::string &url, const int id);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+  private:
+
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+    static JSStaticValue m_property[];
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+};
+
+}
+}
+
+#endif /* _JS_BOOKMARKITEM_H_ */
+
+
+
diff --git a/src/Bookmark/JSBookmarkManager.cpp b/src/Bookmark/JSBookmarkManager.cpp
new file mode 100755 (executable)
index 0000000..7985ab4
--- /dev/null
@@ -0,0 +1,242 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <CommonsJavaScript/Converter.h>
+#include <GlobalContextManager.h>
+#include "JSBookmarkManager.h"
+#include "JSBookmarkFolder.h"
+#include "JSBookmarkItem.h"
+#include "BookmarkManager.h"
+#include "plugin_config.h"
+#include <ArgumentValidator.h>
+#include <PlatformException.h>
+#include <CommonsJavaScript/Converter.h>
+#include <TimeTracer.h>
+
+#include <string>
+#include <vector>
+#include <Logger.h>
+
+using namespace std;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+JSClassRef JSBookmarkManager::m_jsClassRef = NULL;
+
+JSClassDefinition JSBookmarkManager::m_jsClassInfo = {
+    0,                                       // current (and only) version is 0
+    kJSClassAttributeNone,        //attributes
+    "BookmarkManager",                        //class name
+    NULL,                                 // parent class
+    NULL,                                 //static values
+    JSBookmarkManager::m_function,     // static functions
+    JSBookmarkManager::initialize,         // initialize
+    JSBookmarkManager::finalize,          //finalize
+    NULL,                                //hasProperty
+    NULL,   //getProperty
+    NULL,                                //setProperty
+    NULL,                                //deleteProperty
+    NULL,                                //getPropertyNames
+    NULL,                               // callAsConstructor
+    NULL,                               // constructor
+    JSBookmarkManager::hasInstance,
+    NULL // convertToType
+};
+
+
+JSStaticFunction JSBookmarkManager::m_function[] = {
+    { "get", JSBookmarkManager::get, kJSPropertyAttributeNone },
+    { "add", JSBookmarkManager::add, kJSPropertyAttributeNone },
+    { "remove", JSBookmarkManager::remove, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSBookmarkManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSBookmarkManager::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+void JSBookmarkManager::initialize(JSContextRef ctx, JSObjectRef object)
+{
+}
+
+void JSBookmarkManager::finalize(JSObjectRef object)
+{
+}
+
+bool JSBookmarkManager::hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception) {
+    return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
+}
+
+JSValueRef JSBookmarkManager::get(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    AceSecurityStatus status = BOOKMARK_CHECK_ACCESS(BOOKMARK_FUNCTION_API_READ_FUNCS);
+    TIZEN_SYNC_ACCESS_HANDLER(status, ctx, exception);
+
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+
+        bool recursive = validator.toBool(1, true);
+
+        JSObjectRef parentobj = NULL;
+
+        parentobj = validator.toObject(0, JSBookmarkFolder::getClassRef(), true);
+
+        BookmarkData * parentFolder = NULL;
+        if (parentobj) {
+            parentFolder = static_cast<BookmarkData *>(JSObjectGetPrivate(parentobj));
+
+            if (!parentFolder)
+                throw TypeMismatchException("Private data is null");
+            if (parentFolder->m_id == UNDEFINED_ID)
+                throw Common::NotFoundException("Parent doesn't exist in db");
+        }
+
+        BookmarkSearchDataPtr searchData(new BookmarkSearchData(parentFolder,recursive));
+        std::vector<BookmarkDataPtr> bookmarkList = BookmarkManager::getInstance()->get(searchData);
+        unsigned short bookmarksCount = bookmarkList.size();
+        LOGD("count : %d", bookmarksCount);
+        std::vector<JSValueRef> bookmarksArray;
+        Converter converter(ctx);
+        for (int i = 0; i < bookmarksCount; i++) {
+            JSValueRef bookmark;
+            LOGD("bookmarkList[%d] :  %s", i, (bookmarkList[i]->m_title.c_str()));
+            if (bookmarkList[i]->m_type == BOOKMARKITEM_TYPE)
+                bookmark = static_cast<JSValueRef>(JSBookmarkItem::createJSObject(ctx, bookmarkList[i]->m_title, bookmarkList[i]->m_url, bookmarkList[i]->m_id));
+            else
+                bookmark = static_cast<JSValueRef>(JSBookmarkFolder::createJSObject(ctx, bookmarkList[i]->m_title, bookmarkList[i]->m_id));
+            bookmarksArray.push_back(bookmark);
+        }
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return converter.toJSValueRef(bookmarksArray);
+
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+}
+
+JSValueRef JSBookmarkManager::add(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    AceSecurityStatus status = BOOKMARK_CHECK_ACCESS(BOOKMARK_FUNCTION_API_WRITE_FUNCS);
+    TIZEN_SYNC_ACCESS_HANDLER(status, ctx, exception);
+
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        //convert bookmark
+        JSObjectRef bookmarkobj = NULL;
+        try {
+            bookmarkobj = validator.toObject(0, JSBookmarkItem::getClassRef());
+        } catch (const TypeMismatchException& err){
+            LOGD("Bookmark's type is not BookmarkItem");
+            bookmarkobj = validator.toObject(0, JSBookmarkFolder::getClassRef());
+        }
+        BookmarkData * bookmark = static_cast<BookmarkData *>(JSObjectGetPrivate(bookmarkobj));
+
+        if (!bookmark)
+            throw TypeMismatchException("Bookmark private data is null");
+
+        //convert parentFolder
+        JSObjectRef parentobj = NULL;
+
+        parentobj = validator.toObject(1, JSBookmarkFolder::getClassRef(), true);
+
+        BookmarkData * parentFolder = NULL;
+        if (parentobj) {
+            parentFolder = static_cast<BookmarkData *>(JSObjectGetPrivate(parentobj));
+            if (!parentFolder)
+                throw TypeMismatchException("Parent Folder private data is null");
+        }
+
+        int parentId = UNDEFINED_ID;
+        if (parentFolder)
+            parentId = parentFolder->m_id;
+        else
+            parentId = BookmarkManager::getInstance()->getRootFolderId();
+
+        if (parentId == UNDEFINED_ID)
+            throw Common::NotFoundException("Parent doesn't exist in db");
+
+        bookmark->m_id = BookmarkManager::getInstance()->add(bookmark->m_type, parentId, bookmark->m_title, bookmark->m_url);
+        LOGD("bookmark id: %d", bookmark->m_id);
+
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(ctx);
+
+}
+
+JSValueRef JSBookmarkManager::remove(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    AceSecurityStatus status = BOOKMARK_CHECK_ACCESS(BOOKMARK_FUNCTION_API_WRITE_FUNCS);
+    TIZEN_SYNC_ACCESS_HANDLER(status, ctx, exception);
+
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+
+        JSObjectRef bookmarkobj = NULL;
+        try {
+            bookmarkobj = validator.toObject(0, JSBookmarkItem::getClassRef(), true);
+        } catch (const TypeMismatchException& err){
+            LOGD("Bookmark's type is not BookmarkItem");
+            bookmarkobj = validator.toObject(0, JSBookmarkFolder::getClassRef(), true);
+        }
+
+        BookmarkData *bookmark = NULL;
+        if (bookmarkobj) {
+            bookmark = static_cast<BookmarkData *>(JSObjectGetPrivate(bookmarkobj));
+            if (!bookmark)
+                throw TypeMismatchException("Bookmark private data is null");
+            if (bookmark->m_id == UNDEFINED_ID)
+                throw Common::NotFoundException("Bookmark doesn't exist in db");
+        }
+
+        BookmarkSearchDataPtr searchData(new BookmarkSearchData(bookmark));
+
+        BookmarkManager::getInstance()->remove(searchData);
+    }catch( const Common::NotFoundException& err){
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(ctx);
+
+}
+} // Bookmark
+} // TizenApis
+
+
diff --git a/src/Bookmark/JSBookmarkManager.h b/src/Bookmark/JSBookmarkManager.h
new file mode 100755 (executable)
index 0000000..92ea1f6
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#ifndef _JS_BOOKMARK_MANAGER_H_
+#define _JS_BOOKMARK_MANAGER_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+class JSBookmarkManager
+{
+  public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+  private:
+
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+
+    static JSStaticFunction m_function[];
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static bool hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception);
+
+    static JSValueRef get(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef add(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef remove(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+
+
+};
+
+}
+}
+
+#endif /* _JS_BOOKMARK_MANAGER_H_ */
+
+
diff --git a/src/Bookmark/config.xml b/src/Bookmark/config.xml
new file mode 100755 (executable)
index 0000000..e29d62f
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-bookmark.so</library-name>
+    <feature-install-uri>bookmark.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bookmark.read</name>
+        <device-capability>bookmark.read</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/bookmark.write</name>
+        <device-capability>bookmark.write</device-capability>
+    </api-feature>
+</plugin-properties>
diff --git a/src/Bookmark/plugin_config.cpp b/src/Bookmark/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..d9e662b
--- /dev/null
@@ -0,0 +1,113 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#include <map>
+#include <utility>
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include "plugin_config.h"
+
+#define BOOKMARK_FEATURE_API_READ "http://tizen.org/privilege/bookmark.read"
+#define BOOKMARK_FEATURE_API_WRITE "http://tizen.org/privilege/bookmark.write"
+
+#define BOOKMARK_DEVICE_CAP_READ "bookmark.read"
+#define BOOKMARK_DEVICE_CAP_WRITE "bookmark.write"
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+static WrtDeviceApis::Commons::FunctionMapping createBookmarkFunctions();
+
+static WrtDeviceApis::Commons::FunctionMapping bookmarkFunctions =
+    createBookmarkFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(Bookmark, bookmarkFunctions);
+
+#pragma GCC visibility pop
+
+static WrtDeviceApis::Commons::FunctionMapping createBookmarkFunctions()
+{
+    using namespace WrtDeviceApis::Commons;
+
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BOOKMARK_READ, BOOKMARK_DEVICE_CAP_READ);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_BOOKMARK_WRITE, BOOKMARK_DEVICE_CAP_WRITE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BOOKMARK_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BOOKMARK_READ, DEVICE_CAP_BOOKMARK_READ);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_BOOKMARK_WRITE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_BOOKMARK_WRITE, DEVICE_CAP_BOOKMARK_WRITE);
+
+    /**
+     * API features
+     */
+    ACE_CREATE_FEATURE(FEATURE_READ, BOOKMARK_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_WRITE, BOOKMARK_FEATURE_API_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(BOOKMARK_FEATURES_READ);
+    ACE_ADD_API_FEATURE(BOOKMARK_FEATURES_READ, FEATURE_READ);
+
+    ACE_CREATE_FEATURE_LIST(BOOKMARK_FEATURES_WRITE);
+    ACE_ADD_API_FEATURE(BOOKMARK_FEATURES_WRITE, FEATURE_WRITE);
+
+   /**
+     * Functions
+     */
+    FunctionMapping bookmarkFunctions;
+
+    AceFunction bookmarkReadFuncs = ACE_CREATE_FUNCTION(
+            FUNCTION_BOOKMARK_READ_FUNCTIONS,
+            BOOKMARK_FUNCTION_API_READ_FUNCS,
+            BOOKMARK_FEATURES_READ,
+            DEVICE_LIST_BOOKMARK_READ);
+
+    bookmarkFunctions.insert(std::make_pair(
+                               BOOKMARK_FUNCTION_API_READ_FUNCS,
+                               bookmarkReadFuncs));
+
+    AceFunction bookmarkWriteFuncs = ACE_CREATE_FUNCTION(
+            FUNCTION_BOOKMARK_WRITE_FUNCTIONS,
+            BOOKMARK_FUNCTION_API_WRITE_FUNCS,
+            BOOKMARK_FEATURES_WRITE,
+            DEVICE_LIST_BOOKMARK_WRITE);
+
+    bookmarkFunctions.insert(std::make_pair(
+                               BOOKMARK_FUNCTION_API_WRITE_FUNCS,
+                               bookmarkWriteFuncs));
+
+
+    return bookmarkFunctions;
+}
+
+} // namespace Bookmark
+} // namespace DeviceAPI
+
+#undef BOOKMARK_DEVICE_CAP_WRITE
+#undef BOOKMARK_DEVICE_CAP_READ
+#undef BOOKMARK_FEATURE_API_WRITE
+#undef BOOKMARK_FEATURE_API_READ
+
diff --git a/src/Bookmark/plugin_config.h b/src/Bookmark/plugin_config.h
new file mode 100755 (executable)
index 0000000..5b14bc0
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _BOOKMARK_PLUGIN_CONFIG_H_
+#define _BOOKMARK_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+#define BOOKMARK_FUNCTION_API_READ_FUNCS "BookmarkReadFunction"
+#define BOOKMARK_FUNCTION_API_WRITE_FUNCS "BookmarkWriteFunction"
+
+DECLARE_FUNCTION_GETTER(Bookmark);
+
+#define BOOKMARK_CHECK_ACCESS(functionName)                       \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(                \
+        getBookmarkFunctionData,             \
+        functionName)
+}
+}
+
+#endif //  _BOOKMARK_PLUGIN_CONFIG_H_
diff --git a/src/Bookmark/plugin_initializer.cpp b/src/Bookmark/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..3552163
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+#include "JSBookmarkManager.h"
+#include "JSBookmarkFolder.h"
+#include "JSBookmarkItem.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Bookmark {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Bookmark] on_widget_start_callback ( %d )", widgetId);
+    TIME_TRACER_INIT();
+
+    Try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } Catch (Exception) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Bookmark] on_widget_stop_callback ( %d )", widgetId);
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"Bookmark");
+    TIME_TRACER_RELEASE();
+
+    Try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } Catch (Exception) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Bookmark] on_frame_load_callback ( %p )", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Bookmark] on_frame_unload_callback ( %p )", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+class_definition_options_t BookmarkOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL,
+    NULL,
+    NULL
+};
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "bookmark",
+        (js_class_template_getter)JSBookmarkManager::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+                                "BookmarkItem",
+                                (js_class_template_getter)JSBookmarkItem::getClassRef,
+                                reinterpret_cast<js_class_constructor_cb_t>(JSBookmarkItem::constructor),
+                                &BookmarkOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+                                "BookmarkFolder",
+                                (js_class_template_getter)JSBookmarkFolder::getClassRef,
+                                reinterpret_cast<js_class_constructor_cb_t>(JSBookmarkFolder::constructor),
+                                &BookmarkOptions)
+PLUGIN_CLASS_MAP_END
+
+}
+}
+
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..963e8db
--- /dev/null
@@ -0,0 +1,246 @@
+# -----------------------------------------------------------------------------
+# Common Module
+# -----------------------------------------------------------------------------
+SET(COMMON_TARGET_NAME       "wrt-plugins-tizen-common")
+SET(COMMON_DESTINATION_NAME  "tizen-tizen")
+
+SET(CMAKE_INSTALL_RPATH
+  ${CMAKE_INSTALL_RPATH}
+  ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${COMMON_DESTINATION_NAME}
+)
+
+configure_and_install_pkg(wrt-plugins-tizen-common.pc)
+add_subdir(Common)
+
+SET(LIBS_COMMON
+  ${LIBS_COMMON}
+  ${COMMON_TARGET_NAME}
+)
+
+add_subdir(Common/StandaloneConsole)
+
+IF(ENABLE_TIME_TRACER)
+add_subdir(Common/TimeTracer)
+
+SET(LIBS_COMMON
+  ${LIBS_COMMON}
+  "timetracer"
+)
+
+ENDIF(ENABLE_TIME_TRACER)
+
+SET(LIBS_TEST
+  ${LIBS_COMMON}
+  "standaloneconsole"
+)
+
+
+MESSAGE(Status, "LIBS_COMMON is: ${LIBS_COMMON}")
+MESSAGE(Status, "INCLUDE_COMMON is: ${INCLUDE_COMMON}")
+
+# -----------------------------------------------------------------------------
+# Plugin Modules
+# -----------------------------------------------------------------------------
+
+SET(MANDATORY_PLUGINS
+    Tizen
+    TimeUtil
+    Filesystem
+    Content
+    Application
+    Systeminfo
+    Alarm
+    MessagePort
+    Package
+)
+
+IF(ENABLE_OPTIONAL_ACCOUNT)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Account
+)
+ENDIF(ENABLE_OPTIONAL_ACCOUNT)
+
+IF(ENABLE_OPTIONAL_ARCHIVE)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Archive
+)
+ENDIF(ENABLE_OPTIONAL_ARCHIVE)
+
+IF(ENABLE_OPTIONAL_BADGE)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Badge
+)
+ENDIF(ENABLE_OPTIONAL_BADGE)
+
+IF(ENABLE_OPTIONAL_BT)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Bluetooth
+)
+ENDIF(ENABLE_OPTIONAL_BT)
+
+
+IF(ENABLE_OPTIONAL_BOOKMARK)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Bookmark
+)
+ENDIF(ENABLE_OPTIONAL_BOOKMARK)
+
+
+IF(ENABLE_OPTIONAL_CALENDAR)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Calendar
+)
+ENDIF(ENABLE_OPTIONAL_CALENDAR)
+
+
+IF(ENABLE_OPTIONAL_CALL_HISTORY)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Callhistory
+)
+ENDIF(ENABLE_OPTIONAL_CALL_HISTORY)
+
+
+IF(ENABLE_OPTIONAL_CONTACT)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Contact
+)
+ENDIF(ENABLE_OPTIONAL_CONTACT)
+
+IF(ENABLE_OPTIONAL_DATA_CONTROL)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  DataControl
+)
+ENDIF(ENABLE_OPTIONAL_DATA_CONTROL)
+
+IF(ENABLE_OPTIONAL_DATA_SYNC)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  DataSync
+)
+ENDIF(ENABLE_OPTIONAL_DATA_SYNC)
+
+IF(ENABLE_OPTIONAL_DOWNLOAD)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Download
+)
+ENDIF(ENABLE_OPTIONAL_DOWNLOAD)
+
+IF(ENABLE_OPTIONAL_EXIF)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Exif
+)
+ENDIF(ENABLE_OPTIONAL_EXIF)
+
+IF(ENABLE_OPTIONAL_FM_RADIO)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  FMRadio
+)
+ENDIF(ENABLE_OPTIONAL_FM_RADIO)
+
+IF(ENABLE_OPTIONAL_HAM)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  HumanActivityMonitor
+)
+ENDIF(ENABLE_OPTIONAL_HAM)
+
+IF(ENABLE_OPTIONAL_MEDIAKEY)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Mediakey
+)
+ENDIF(ENABLE_OPTIONAL_MEDIAKEY)
+
+IF(ENABLE_OPTIONAL_MESSAGING)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Messaging
+)
+ENDIF(ENABLE_OPTIONAL_MESSAGING)
+
+IF(ENABLE_OPTIONAL_NBS)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  NetworkBearerSelection
+)
+ENDIF(ENABLE_OPTIONAL_NBS)
+
+IF(ENABLE_OPTIONAL_NFC)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  NFC
+)
+ENDIF(ENABLE_OPTIONAL_NFC)
+
+IF(ENABLE_OPTIONAL_NOTIFICATION)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Notification
+)
+ENDIF(ENABLE_OPTIONAL_NOTIFICATION)
+
+IF(ENABLE_OPTIONAL_POWER)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Power
+)
+ENDIF(ENABLE_OPTIONAL_POWER)
+
+IF(ENABLE_OPTIONAL_PUSH)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Push
+)
+ENDIF(ENABLE_OPTIONAL_PUSH)
+
+IF(ENABLE_OPTIONAL_SE)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  SecureElement
+)
+ENDIF(ENABLE_OPTIONAL_SE)
+
+IF(ENABLE_OPTIONAL_SENSOR)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Sensor
+)
+ENDIF(ENABLE_OPTIONAL_SENSOR)
+
+IF(ENABLE_OPTIONAL_SOUND)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  Sound
+)
+ENDIF(ENABLE_OPTIONAL_SOUND)
+
+IF(ENABLE_OPTIONAL_SYSTEM_SETTING)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  SystemSetting
+)
+ENDIF(ENABLE_OPTIONAL_SYSTEM_SETTING)
+
+IF(ENABLE_OPTIONAL_WEB_SETTING)
+SET(OPTIONAL_PLUGINS
+  ${OPTIONAL_PLUGINS}
+  WebSetting
+)
+ENDIF(ENABLE_OPTIONAL_WEB_SETTING)
+
+add_plugin(
+  ${MANDATORY_PLUGINS}
+  ${OPTIONAL_PLUGINS}
+)
diff --git a/src/Calendar/CMakeLists.txt b/src/Calendar/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..9834ad7
--- /dev/null
@@ -0,0 +1,83 @@
+SET(TARGET_NAME ${calendar_target})
+SET(DESTINATION_NAME ${calendar_dest})
+SET(TARGET_IMPL_NAME ${calendar_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_calendar REQUIRED accounts-svc calendar-service2 icu-i18n)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+SET(INCLUDE_DIRS
+    ${contact_include}
+    ${timeutil_include}
+    ${tizen_include}
+    ${platform_pkgs_calendar_INCLUDE_DIRS}
+)
+
+INCLUDE_DIRECTORIES(${INCLUDE_COMMON} ${INCLUDE_DIRS})
+MESSAGE(STATUS "${TARGET_NAME} module includes: INCLUDE_COMMON ${INCLUDE_DIRS}")
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${contact_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${timeutil_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    ChangeListenerContainer.cpp
+    JSCalendarEventId.cpp
+    CalendarEventId.cpp
+    JSCalendarAlarm.cpp
+    CalendarAlarm.cpp
+    JSCalendarAttendee.cpp
+    CalendarAttendee.cpp
+    JSCalendarItem.cpp
+    CalendarItem.cpp
+    JSCalendarEvent.cpp
+    CalendarEvent.cpp
+    JSCalendarTask.cpp
+    CalendarTask.cpp
+    CalendarChangeCallback.cpp
+    Calendar.cpp
+    CalendarCallbackUserData.cpp
+    JSCalendar.cpp
+    CalendarManager.cpp
+    JSCalendarManager.cpp
+    JSCalendarRecurrenceRule.cpp
+    CalendarRecurrenceRule.cpp
+    CalendarUtility.cpp
+    CalendarItemSearchEngine.cpp
+    CalendarFindCallbackData.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+SET(LINK_LIBS
+    ${tizen_impl}
+    ${timeutil_impl}
+    ${contact_impl}
+    ${platform_pkgs_calendar_LIBRARIES}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME} ${LIBS_COMMON} ${LINK_LIBS})
+MESSAGE(STATUS "${TARGET_NAME} module links: LIBS_COMMON ${LINK_LIBS}")
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+    "-Wl,--no-as-needed" ${contact_config}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/calendar
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Calendar/Calendar.cpp b/src/Calendar/Calendar.cpp
new file mode 100755 (executable)
index 0000000..57402d5
--- /dev/null
@@ -0,0 +1,1822 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include "Calendar.h"
+#include "TimeUtil.h"
+#include "ChangeListenerContainer.h"
+#include "JSCalendarEvent.h"
+#include "JSCalendarTask.h"
+#include "JSCalendarItem.h"
+#include "CalendarManager.h"
+#include "CalendarFindCallbackData.h"
+#include "CalendarItemSearchEngine.h"
+#include <account.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+using namespace Time;
+
+std::mutex Calendar::s_mutex;
+ChangeListenerContainer Calendar::s_listener;
+long Calendar::s_last_verison = 0;
+
+Calendar::Calendar():
+        SecurityAccessor(),
+        m_id(0),
+        m_name(""),
+        m_type(CalendarUtility::CalendarType::UNDEFINED),
+        f_rec_h(NULL),
+        m_account_id(0)
+{
+    LOGD("Entered");
+}
+
+Calendar::~Calendar()
+{
+    LOGD("Entered");
+    s_listener.removeAllChangeListener(m_id);
+    if (s_listener.isEmpty()) {
+        removePlatformChangeListener();
+        s_last_verison = 0;
+    }
+}
+
+Calendar & Calendar::operator =(const Calendar& calendar)
+{
+    return *this;
+}
+
+CalendarId Calendar::getId()
+{
+    return m_id;
+}
+
+std::string Calendar::getName()
+{
+    return m_name;
+}
+
+CalendarUtility::CalendarType Calendar::getType()
+{
+    return m_type;
+}
+
+long Calendar::getAccountId()
+{
+    return m_account_id;
+}
+
+void Calendar::setId(long id)
+{
+    m_id = id;
+}
+
+void Calendar::setName(std::string name)
+{
+    m_name = name;
+}
+
+void Calendar::setType(CalendarUtility::CalendarType type)
+{
+    m_type = type;
+}
+
+void Calendar::setAccountId(long accountId)
+{
+    m_account_id = accountId;
+}
+
+bool Calendar::isCalendarIdSet()
+{
+    if (0 == m_id) {
+        return false;
+    } else
+        return true;
+}
+
+CalendarUtility::CalendarType Calendar::stringToCalendarType(std::string type)
+{
+    if ("EVENT" == type) {
+        return CalendarUtility::CalendarType::EVENT;
+    }
+    if ("TASK" == type) {
+        return CalendarUtility::CalendarType::TASK;
+    }
+
+    LOGE("Invalid CalendarType");
+    throw TypeMismatchException("Invalid CalendarType");
+}
+
+void Calendar::calendar_db_changed_cb(const char* view_uri, void* user_data)
+{
+    LOGD("ENTERED");
+    if (!user_data) {
+        LOGE("Callback is null");
+        return;
+    }
+
+    Calendar *cbdata = static_cast<Calendar*>(user_data);
+    int ret, id, type, updatedVersion, calendarId, count = 0;
+    calendar_list_h list = NULL;
+    calendar_record_h currentRecord = NULL;
+    calendar_record_h record = NULL;
+    EventCalendarVector event_add;
+    EventCalendarVector event_update;
+    EventCalendarIdVector event_remove;
+    try {
+        if (-1 == cbdata->getId()) {
+            calendarId = CALENDAR_BOOK_FILTER_ALL;
+        } else {
+            calendarId = cbdata->getId();
+        }
+
+        if (CalendarUtility::CalendarType::EVENT == cbdata->getType()) {
+            ret = calendar_db_get_changes_by_version(_calendar_event._uri,
+                calendarId, s_last_verison, &list, &updatedVersion);
+        } else {
+            ret = calendar_db_get_changes_by_version(_calendar_todo._uri,
+                calendarId, s_last_verison, &list, &updatedVersion);
+        }
+
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't get the updated item list");
+        }
+
+        ret = calendar_list_get_count(list, &count);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't get the item count");
+        } else {
+            LOGD("Item count: %d",count);
+        }
+
+        calendar_list_first(list);
+
+        while(count-- > 0)
+        {
+            currentRecord = NULL;
+            record = NULL;
+            ret = calendar_list_get_current_record_p(list, &currentRecord);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Can't get current record");
+            }
+
+            ret = calendar_record_get_int(currentRecord,
+                    _calendar_updated_info.id, &id);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Can't get updated info id");
+            }
+
+            ret = calendar_record_get_int(currentRecord,
+                    _calendar_updated_info.modified_status ,&type);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Can't get updated info modified status");
+            }
+
+            if (CALENDAR_RECORD_MODIFIED_STATUS_DELETED != type) {
+                if (CalendarUtility::CalendarType::EVENT == cbdata->getType()) {
+                    ret = calendar_db_get_record(_calendar_event._uri, id, &record);
+                } else {
+                    ret = calendar_db_get_record(_calendar_todo._uri, id, &record);
+                }
+            }
+
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Can't get record");
+            }
+
+            if (CALENDAR_RECORD_MODIFIED_STATUS_INSERTED==type) {
+                EventCalendar event;
+                event.calendar_id = cbdata->getId();
+                event.type = cbdata->getType();
+                if (CalendarUtility::CalendarType::EVENT == cbdata->getType()) {
+                    std::shared_ptr<CalendarEvent> eventItem(new CalendarEvent());
+                    eventItem->convertPlatFormEventToAbstractCalendarEvent(record);
+                    event.events.push_back(eventItem);
+                } else {
+                    std::shared_ptr<CalendarTask> eventItem(new CalendarTask());
+                    eventItem->convertPlatformTaskToAbstractCalendarTask(record);
+                    event.tasks.push_back(eventItem);
+                }
+                event_add.push_back(event);
+            } else if (CALENDAR_RECORD_MODIFIED_STATUS_UPDATED==type) {
+                EventCalendar event;
+                event.calendar_id = cbdata->getId();
+                event.type = cbdata->getType();
+                if (CalendarUtility::CalendarType::EVENT == cbdata->getType()) {
+                    std::shared_ptr<CalendarEvent> eventItem(new CalendarEvent());
+                    eventItem->convertPlatFormEventToAbstractCalendarEvent(record);
+                    event.events.push_back(eventItem);
+                } else {
+                    std::shared_ptr<CalendarTask> eventItem(new CalendarTask());
+                    eventItem->convertPlatformTaskToAbstractCalendarTask(record);
+                    event.tasks.push_back(eventItem);
+                }
+                event_update.push_back(event);
+            } else if (CALENDAR_RECORD_MODIFIED_STATUS_DELETED==type) {
+                EventCalendarId event;
+                event.calendar_id = cbdata->getId();
+                event.type = cbdata->getType();
+                if (CalendarUtility::CalendarType::EVENT == event.type) {
+                    CalendarEventIdPtr id_ptr(new CalendarEventId());
+                    id_ptr->setUid(id);
+                    event.event_id.push_back(id_ptr);
+                } else {
+                    event.task_id.push_back(id);
+                }
+                event_remove.push_back(event);
+
+            } else {
+                LOGW("Wrong change type.");
+                calendar_list_next(list);
+                continue;
+            }
+            calendar_list_next(list);
+            if (record) {
+                calendar_record_destroy(record, true);
+            }
+        }
+        ret = calendar_db_get_current_version(&updatedVersion);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't get new version");
+        }
+        s_last_verison = updatedVersion;
+
+        if (!event_add.empty()) {
+            EventCalendar tmp_event;
+
+            for (std::vector<EventCalendar>::iterator it_e = event_add.begin();
+                it_e != event_add.end(); ++it_e) {
+                tmp_event.type = it_e->type;
+                if (CalendarUtility::CalendarType::EVENT == it_e->type) {
+                    for (std::vector<CalendarEventPtr>::iterator it_i = it_e->events.begin();
+                            it_i != it_e->events.end(); ++it_i) {
+                        tmp_event.events.push_back(*it_i);
+                    }
+                } else {
+                    for (std::vector<CalendarTaskPtr>::iterator it_i = it_e->tasks.begin();
+                            it_i != it_e->tasks.end(); ++it_i) {
+                        tmp_event.tasks.push_back(*it_i);
+                    }
+                }
+            }
+            s_listener.callCalendarAdded(tmp_event);
+        }
+
+        if (!event_update.empty()) {
+            EventCalendar tmp_event;
+
+            for (std::vector<EventCalendar>::iterator it_e = event_update.begin();
+                    it_e != event_update.end(); ++it_e) {
+                tmp_event.type = it_e->type;
+                if (CalendarUtility::CalendarType::EVENT == it_e->type) {
+                    for (std::vector<CalendarEventPtr>::iterator it_i = it_e->events.begin();
+                            it_i != it_e->events.end(); ++it_i) {
+                        tmp_event.events.push_back(*it_i);
+                    }
+                } else {
+                    for (std::vector<CalendarTaskPtr>::iterator it_i = it_e->tasks.begin();
+                            it_i != it_e->tasks.end(); ++it_i) {
+                        tmp_event.tasks.push_back(*it_i);
+                    }
+                }
+            }
+            s_listener.callCalendarUpdated(tmp_event);
+        }
+
+        if (!event_remove.empty()) {
+            EventCalendarId tmp_event;
+
+            for (std::vector<EventCalendarId>::iterator it_e = event_remove.begin();
+                it_e != event_remove.end(); ++it_e) {
+                tmp_event.type = it_e->type;
+                if (CalendarUtility::CalendarType::EVENT == it_e->type) {
+                    for (std::vector<CalendarEventIdPtr>::iterator it_i = it_e->event_id.begin();
+                        it_i != it_e->event_id.end(); ++it_i) {
+                        tmp_event.event_id.push_back(*it_i);
+                    }
+                } else {
+                    for (std::vector<int>::iterator it_i = it_e->task_id.begin();
+                        it_i != it_e->task_id.end(); ++it_i) {
+                        tmp_event.task_id.push_back(*it_i);
+                    }
+                }
+            }
+            s_listener.callCalendarRemoved(tmp_event);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("get changes fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("get changes fails");
+    }
+
+    if (list) {
+        calendar_list_destroy(list, true);
+    }
+}
+
+void Calendar::addBatchEvents(CalendarCallbackUserData* eventsCallBack)
+{
+    LOGD("Entered");
+    int ret;
+    if (!eventsCallBack) {
+        LOGE("eventsCallBack is null");
+        throw UnknownException("eventsCallBack is null");
+    }
+
+    calendar_list_h list_h = NULL;
+    int *idsOfInsertedEvents;
+    int numberOfInsertedEvents;
+
+    ret = calendar_list_create(&list_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Could not create list for event batch operation");
+    }
+
+    std::size_t eventsSize = eventsCallBack->m_events.size();
+    for (std::size_t i = 0; i < eventsSize; ++i) {
+        eventsCallBack->m_events[i]->setCalendarId(eventsCallBack->m_calendar_ptr->getId());
+        calendar_record_h record_h =
+            (*(eventsCallBack->m_events[i])).convertAbstractCalendarEventToPlatformCalendarEvent();
+        ret = calendar_record_clone(record_h, &f_rec_h);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Could not convert");
+        }
+        ret = calendar_list_add(list_h, f_rec_h);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Could not add event record to list of events");
+        }
+    }
+
+    ret = calendar_db_insert_records(list_h, &idsOfInsertedEvents, &numberOfInsertedEvents);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("calendar_db_insert_records failed.");
+        if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "InvalidValuesError");
+        }
+        else{
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "CALENDAR_ERROR_DB_FAILED occurred");
+        }
+    }
+    else{
+        for (int i = 0; i < numberOfInsertedEvents; i++) {
+            CalendarEventIdPtr eventIdPtr = CalendarEventIdPtr(new CalendarEventId());
+            if (!eventIdPtr) {
+                LOGE("eventIdPtr is NULL");
+                throw UnknownException("eventIdPtr is NULL");
+            }
+            eventIdPtr->setUid(idsOfInsertedEvents[i]);
+            eventsCallBack->m_events[i]->setId(eventIdPtr);
+        }
+    }
+    if (list_h) {
+        calendar_list_destroy(list_h, true);
+    }
+    free (idsOfInsertedEvents);
+    idsOfInsertedEvents = NULL;
+    return;
+}
+
+void Calendar::addBatchTasks(CalendarCallbackUserData* tasksCallBack)
+{
+    LOGD("Entered");
+    int ret;
+    if (!tasksCallBack) {
+        LOGE("tasksCallBack is null");
+        throw UnknownException("tasksCallBack is null");
+    }
+    int *idsOfInsertedTasks;
+    int numberOfInsertedTasks;
+    calendar_list_h list_h = NULL;
+
+    ret = calendar_list_create(&list_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Could not create list for event batch operation");
+    }
+
+    std::size_t taskSize = tasksCallBack->m_tasks.size();
+    for (std::size_t i = 0; i < taskSize; ++i) {
+        tasksCallBack->m_tasks[i]->setCalendarId(tasksCallBack->m_calendar_ptr->getId());
+        calendar_record_h record_h =
+                (*(tasksCallBack->m_tasks[i])).convertAbstractCalendarTaskToPlatformCalendarTask();
+        ret = calendar_record_clone(record_h, &f_rec_h);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Could not convert");
+        }
+        ret = calendar_list_add(list_h, f_rec_h);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("Could not add task record to list of tasks because of"
+                    " CALENDAR_ERROR_INVALID_PARAMETER");
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException<InvalidValuesException>(ret, "Could not add task record to list of tasks");
+        }
+
+    }
+
+    ret = calendar_db_insert_records(list_h, &idsOfInsertedTasks, &numberOfInsertedTasks);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("calendar_db_insert_records failed.");
+            if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException<InvalidValuesException>(ret, "Could not add task record to list of tasks");
+            }
+            else{
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "CALENDAR_ERROR_DB_FAILED occurred");
+            }
+    }
+    else{
+        for (int i = 0; i < numberOfInsertedTasks; i++) {
+            tasksCallBack->m_tasks[i]->setId(idsOfInsertedTasks[i]);
+        }
+    }
+    if (list_h) {
+        calendar_list_destroy(list_h, true);
+    }
+    free(idsOfInsertedTasks);
+    idsOfInsertedTasks = NULL;
+    return;
+}
+
+gboolean Calendar::addBatchCompleted(void *data)
+{
+    LOGD("Entered");
+    auto callback = static_cast<CalendarCallbackUserData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try{
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            callback->callSuccessCallback(callback->getJsResult());
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("InvalidValuesError");
+    }
+    catch (...) {
+        LOGE("UnknownError");
+    }
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+void* Calendar::addBatchThread(void *data)
+{
+    LOGD("Entered");
+    std::lock_guard<std::mutex> lock(s_mutex);
+    JSObjectRef js_result;
+    CalendarCallbackUserData* callback;
+    try {
+        callback = static_cast<CalendarCallbackUserData*>(data);
+        if (!callback) {
+            LOGE("Callback is null");
+            return NULL;
+        }
+        JSContextRef context = callback->getContext();
+        std::vector<JSObjectRef> items_vector;
+
+        if (0<callback->m_events.size()) {
+            callback->m_calendar_ptr->addBatchEvents(callback);
+            int count = callback->m_events.size();
+            for (int i = 0; i < count; i++) {
+                items_vector.push_back(JSCalendarEvent::makeJSObject(context,
+                        callback->m_events[i]));
+            }
+        }
+        else if (callback->m_tasks.size()>0) {
+            callback->m_calendar_ptr->addBatchTasks(callback);
+            int count = callback->m_tasks.size();
+            for (int i = 0; i < count; i++) {
+                items_vector.push_back(JSCalendarTask::makeJSObject(context,
+                        callback->m_tasks[i]));
+            }
+        }
+        int size = items_vector.size();
+        JSValueRef exception = NULL;
+        js_result = JSObjectMakeArray(context, size,
+                size > 0 ? &items_vector[0] : NULL, &exception);
+        if (NULL == js_result || NULL != exception) {
+            LOGE("Could not create a result array.");
+            throw UnknownException(context, exception);
+        }
+        callback->setJsResult(js_result);
+
+    } catch (const BasePlatformException &err) {
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, err.getMessage().c_str());
+    }
+    catch (...) {
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "UnknownError.");
+    }
+
+    if (0 == g_idle_add(addBatchCompleted, data)) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+    return NULL;
+}
+
+void Calendar::addBatch(CalendarCallbackUserData* callback)
+{
+    LOGD("Entered");
+    if (NULL == callback) {
+        throw UnknownException("NULL cbdata error.");
+    }
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, addBatchThread, static_cast<void*>(callback))) {
+        LOGE("Failed to create pthread for addBatch()");
+        throw UnknownException("pthread_create error.");
+    }
+    if (pthread_detach(thread)) {
+        LOGW("Failed to detach the pthread for addBatch()");
+    }
+}
+
+void Calendar::addEvent(CalendarEventPtr event)
+{
+    LOGD("Entered");
+    int ret;
+    calendar_record_h record_h = event->convertAbstractCalendarEventToPlatformCalendarEvent();
+
+    ret = calendar_record_clone(record_h, &f_rec_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Could not convert");
+    }
+    int rec_id = 0;
+
+    ret = calendar_db_insert_record(f_rec_h, &rec_id);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Could not insert event record to Calendar DB");
+    }
+    CalendarEventIdPtr eventIdPtr = CalendarEventIdPtr(new CalendarEventId());
+    if (!eventIdPtr) {
+        LOGE("eventIdPtr is NULL");
+        throw UnknownException("eventIdPtr is NULL");
+    }
+    eventIdPtr->setUid(rec_id);
+    event->setCalendarId(getId());
+    event->setId(eventIdPtr);
+
+    ret = calendar_record_destroy(f_rec_h, true);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar DB event record destroy error");
+    }
+}
+
+void Calendar::addTask(CalendarTaskPtr task)
+{
+    LOGD("Entered");
+    int ret;
+
+    calendar_record_h record_h = task->convertAbstractCalendarTaskToPlatformCalendarTask();
+
+    ret = calendar_record_clone(record_h, &f_rec_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Could not convert");
+    }
+    int rec_id = 0;
+
+    ret = calendar_db_insert_record(f_rec_h, &rec_id);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Could not insert todo record to Calendar DB");
+    }
+    task->setCalendarId(getId());
+    task->setId(rec_id);
+
+    ret = calendar_record_destroy(f_rec_h, true);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar DB todo record destroy error");
+     }
+ }
+
+CalendarEventPtr Calendar::getEvent(CalendarEventIdPtr id) {
+    calendar_record_h rec;
+    int ret;
+
+    ret = calendar_db_get_record(_calendar_event._uri,
+            id->getUid(), &rec);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException<NotFoundException>(ret, "calendar_db_get_record  error");
+    }
+    ret = calendar_record_clone(rec, &f_rec_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Record cloning error.");
+    }
+
+    CalendarEventPtr event(new CalendarEvent());
+    event->convertPlatFormEventToAbstractCalendarEvent(f_rec_h);
+    return event;
+}
+
+CalendarTaskPtr Calendar::getTask(int id) {
+    LOGD("Entered");
+
+    int ret;
+    calendar_record_h rec;
+    ret = calendar_db_get_record(_calendar_todo._uri,id, &rec);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException<NotFoundException>(ret, "Task not found in database");
+    }
+    ret = calendar_record_clone(rec, &f_rec_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Record cloning error.");
+    }
+
+    CalendarTaskPtr task(new CalendarTask());
+    task->convertPlatformTaskToAbstractCalendarTask(f_rec_h);
+    return task;
+}
+
+void Calendar::removeBatchEvents(CalendarCallbackUserData* callback)
+{
+    LOGD("Entered");
+    int ret;
+    calendar_record_h record_h = NULL;
+    calendar_list_h list_h = NULL;
+
+    std::vector<int> ids_no_recurr_vect;
+    int rec_count = 0;
+
+    char *recurrence_id = NULL;
+    query_s q;
+
+    q.property_id_array.clear();
+    ids_no_recurr_vect.clear();
+    q.uri = _calendar_event._uri;
+    int size = callback->m_events_ids.size();
+
+    for (int i = 0; i < size; i++) {
+        int idToRemove = callback->m_events_ids[i]->getUid();
+
+        int ret = 0;
+        ret = calendar_db_get_record(_calendar_event._uri,
+                idToRemove, &record_h);
+        if (ret != CALENDAR_ERROR_NONE) {
+            if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException<NotFoundException>(ret, "Event not found in database.");
+            }
+            else {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Database error.");
+            }
+        }
+        ret = calendar_record_get_str(record_h,
+                        _calendar_event.recurrence_id, &recurrence_id);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Could not get record recurrenceId from db.");
+        }
+        if (NULL != recurrence_id) {
+            q.property_id_array.push_back((property_id_value_s)
+            {   _calendar_event.recurrence_id, RECORD_VT_STR, 0, recurrence_id});
+        }
+        else {LOGD("recurrenceId %d", idToRemove);
+            q.property_id_array.push_back((property_id_value_s)
+            {   _calendar_event.original_event_id, RECORD_VT_INT, idToRemove, ""});
+
+            ids_no_recurr_vect.push_back(idToRemove);
+        }
+    }
+
+    if (0 < ids_no_recurr_vect.size()) {
+        int ret = calendar_db_delete_records(_calendar_event._uri, &ids_no_recurr_vect[0],
+                ids_no_recurr_vect.size());
+
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("calendar_db_delete_records failed.");
+                if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+                    LOGE("ret : %d", ret);
+                    CalendarUtility::throwCalendarException(ret, "calendar_db_delete_records()");
+                }
+                else{
+                    LOGE("ret : %d", ret);
+                    CalendarUtility::throwCalendarException(ret, "calendar_db_delete_records()");
+                }
+        }
+    }
+
+    if (0 < q.property_id_array.size()) {
+
+        queryRecords(&q, &list_h);
+        if (list_h) {
+            ret = calendar_list_get_count(list_h, &rec_count);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Calendar events list get records count error");
+            }
+            ret = calendar_list_first(list_h);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Calendar events list records, move to first error");
+            }
+            int rec_ids[rec_count];
+            for (int i = 0; i < rec_count; i++) {
+                calendar_record_h rec_h;
+
+                ret = calendar_list_get_current_record_p(list_h, &rec_h);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    CalendarUtility::throwCalendarException(ret, "Calendar events list, get record error");
+                }
+                ret = calendar_record_get_int(rec_h, _calendar_event.id,
+                        &rec_ids[i]);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    CalendarUtility::throwCalendarException(ret, "Calendar event record get id error");
+                }
+                LOGD("id of event - %d",rec_ids[i]);
+                if (i == rec_count - 1) {
+                    break;
+                }
+                ret = calendar_list_next(list_h);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    CalendarUtility::throwCalendarException(ret, "Calendar events list, goto next error");
+                }
+            }
+            int ret;
+            if (0 < rec_count) {
+                ret = calendar_db_delete_records(_calendar_event._uri, rec_ids, rec_count);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGE("calendar_db_delete_records failed.");
+                    if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+                        LOGE("CALENDAR_ERROR_INVALID_PARAMETER");
+                        throw UnknownException("InvalidValuesError");
+                    }
+                    else{
+                        LOGE("CALENDAR_ERROR_DB_FAILED");
+                        throw UnknownException("UnknownError");
+                    }
+                }
+            }
+            calendar_list_destroy(list_h, true);
+        }
+        queryDestroy(&q);
+    }
+    if (recurrence_id) {
+        free(recurrence_id);
+        recurrence_id = NULL;
+    }
+}
+
+void Calendar::removeBatchTasks(CalendarCallbackUserData* callback)
+{
+    LOGD("Entered");
+    int ret;
+    calendar_list_h list_h = NULL;
+    int rec_count = 0;
+    query_s q;
+
+    LOGD("Entered");
+    if (!callback) {
+        LOGE("cbdata is null");
+        throw UnknownException("cbdata is null");
+    }
+
+    int *rec_ids = NULL;
+    //int idInt = callback->m_tasks_ids[i];
+    int size = callback->m_tasks_ids.size();
+    q.uri = _calendar_todo._uri;
+
+    for (int i = 0; i < size; i++) {
+        q.property_id_array.push_back((property_id_value_s)
+                {_calendar_todo.id, RECORD_VT_INT, callback->m_tasks_ids[i], NULL});
+    }
+    queryRecords(&q, &list_h);
+
+    ret = calendar_list_get_count(list_h, &rec_count);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar events list get records count error");
+    }
+    ret = calendar_list_first(list_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar tasks list records, move to first error");
+    }
+    rec_ids = static_cast<int*>(calloc(rec_count, sizeof(int)));
+
+    for (int i = 0; i < rec_count; i++) {
+        calendar_record_h rec_h;
+
+        ret = calendar_list_get_current_record_p(list_h, &rec_h);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Calendar todos list, get record error");
+        }
+        ret = calendar_record_get_int(rec_h, _calendar_todo.id, &rec_ids[i]);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Calendar task record get id error");
+        }
+        if (i == rec_count - 1) {
+            break;
+        }
+        ret = calendar_list_next(list_h);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "calendar_list_next()");
+        }
+    }
+
+    ret = calendar_db_delete_records(_calendar_todo._uri, rec_ids,rec_count);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("calendar_db_delete_records failed.");
+            if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException<InvalidValuesException>(ret, "calendar_db_delete_records()");
+            }
+            else {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "calendar_db_delete_records");
+            }
+    }
+    if (list_h) {
+        calendar_list_destroy(list_h, true);
+    }
+    queryDestroy(&q);
+    free(rec_ids);
+    rec_ids = NULL;
+}
+
+gboolean Calendar::removeBatchCompleted(void *data)
+{
+    LOGD("Entered");
+    auto callback = static_cast<CalendarCallbackUserData*>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try{
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),callback->getErrorMessage());
+
+                callback->callErrorCallback(errobj);
+        }
+        else {
+                callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("InvalidValuesError");
+    }
+    catch (...) {
+        LOGE("UnknownError");
+    }
+    delete callback;
+    callback = NULL;
+    return false;
+
+}
+
+void* Calendar::removeBatchThread(void *data)
+{
+    LOGD("Entered");
+    std::lock_guard<std::mutex> lock(s_mutex);
+    CalendarCallbackUserData* callback;
+    try {
+        callback = static_cast<CalendarCallbackUserData*>(data);
+        if (!callback) {
+            LOGE("Callback is null");
+            return NULL;
+        }
+
+        if (0<callback->m_events_ids.size()) {
+            callback->m_calendar_ptr->removeBatchEvents(callback);
+        }
+        else if (0<callback->m_tasks_ids.size()) {
+            callback->m_calendar_ptr->removeBatchTasks(callback);
+        }
+    } catch (const BasePlatformException &err) {
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,err.getMessage().c_str());
+    }
+    catch (...) {
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,"UnknownError.");
+    }
+    if (0 == g_idle_add(removeBatchCompleted, data)) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+    return NULL;
+}
+
+void Calendar::removeBatch(CalendarCallbackUserData* callback)
+{
+    LOGD("Entered");
+    if (NULL == callback) {
+        LOGE("NULL cbdata error.");
+        throw UnknownException("NULL cbdata error.");
+    }
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, removeBatchThread, static_cast<void*>(callback))) {
+        LOGD("Failed to create pthread for removeBatch()");
+        throw UnknownException("pthread_create error.");
+    }
+    if (pthread_detach(thread)) {
+        LOGW("Failed to detach the pthread for removeBatch()");
+    }
+}
+
+void Calendar::removeEvent(const CalendarEventIdPtr id)
+{
+    LOGD("Entered");
+    calendar_record_h record_h = NULL;
+    calendar_list_h list_h = NULL;
+    int rec_count = 0;
+    char *recurrence_id = NULL;
+    query_s q;
+    q.uri = _calendar_event._uri;
+    int idToRemove = id->getUid();
+
+    int ret = 0;
+    ret = calendar_db_get_record(_calendar_event._uri, idToRemove, &record_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException<NotFoundException>(ret, "Event not found in database.");
+        }
+        else {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Database error.");
+        }
+    }
+    ret = calendar_record_get_str(record_h, _calendar_event.recurrence_id,
+                    &recurrence_id);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Could not get record recurrenceId from db.");
+    }
+    if (NULL != recurrence_id && EMPTY_STRING != recurrence_id) {
+        q.property_id_array.push_back((property_id_value_s)
+                {_calendar_event.recurrence_id, RECORD_VT_STR, 0, recurrence_id});
+    }
+    else {
+        ret = calendar_db_delete_record(_calendar_event._uri, idToRemove);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Calendar event record delete error");
+        }
+        ret = calendar_record_destroy(record_h, true);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Record deletion error");
+        }
+        return;
+    }
+
+    queryRecords(&q, &list_h);
+
+    ret = calendar_list_get_count(list_h, &rec_count);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar events list get records count error");
+    }
+    if (rec_count > 0) {
+        ret = calendar_list_first(list_h);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Calendar events list records,"
+                    "move to first error");
+        }
+        for (int i = 0; i < rec_count; i++) {
+            calendar_record_h current_record_h;
+            ret = calendar_list_get_current_record_p(list_h, &current_record_h);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Calendar events list, get record error");
+            }
+            int rec_id;
+
+            ret = calendar_record_get_int(current_record_h, _calendar_event.id, &rec_id);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Calendar event record get id error");
+            }
+            ret = calendar_db_delete_record(_calendar_event._uri, rec_id);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Calendar event record delete error");
+            }
+            if (i == rec_count - 1) {
+                break;
+            }
+            ret = calendar_list_next(list_h);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "calendar_list_next error");
+            }
+        }
+    }
+    if (list_h) {
+        calendar_list_destroy(list_h, true);
+    }
+    queryDestroy(&q);
+}
+
+void Calendar::removeTask(const int id)
+{
+    LOGD("Entered");
+    int ret;
+    calendar_record_h rec = NULL;
+    int eventId = id;
+    ret = calendar_db_get_record(_calendar_todo._uri, eventId, &rec);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException<NotFoundException>(ret, "Task not found in database");
+    }
+    ret = calendar_db_delete_record(_calendar_todo._uri, eventId);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Task deletion error");
+    }
+}
+
+void Calendar::updateBatchEvents(CalendarCallbackUserData* callback)
+{
+    LOGD("Entered");
+    calendar_list_h listForUpdate = NULL;
+    calendar_list_h listForAdd = NULL;
+    int ret, count;
+    calendar_record_h record = NULL;
+
+    ret = calendar_list_create(&listForUpdate);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Can't create a list for update");
+    }
+
+    ret = calendar_list_create(&listForAdd);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Can't create a list for add");
+    }
+
+    std::size_t size = callback->m_events.size();
+    for (std::size_t i=0; i<size; i++) {
+        CalendarEventPtr this_event = callback->m_events[i];
+        if (!this_event->isSet(CALENDAR_EVENT_ATTRIBUTE_ID)) {
+            LOGE("Item id is not set.");
+            throw TypeMismatchException("Item id is not set.");
+        }
+
+        this_event->convertAbstractCalendarEventToPlatformCalendarEvent(true);
+
+        if (this_event->getIsDetached() || callback->getIsAllInstances() ||
+                CalendarRecurrenceRule::NO_FREQUENCY ==
+                        this_event->getRecurrenceRule()->getFrequency()
+                || this_event->getId()->isSet(CALENDAR_EVENT_ID_ATTRIBUTE_RID)) {
+            // Platform detects the detached events and uptates all instances.
+            record = NULL;
+            ret = calendar_record_clone(this_event->getPlatformCalendarItem(), &record);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Clonning failed");
+            }
+
+            ret = calendar_list_add(listForUpdate, record);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Can't add the item to the list");
+            } else {
+                LOGD("Added the detached event to the update list");
+            }
+        } else {
+            LOGD("Update the exdate for a recurring parent event and add a new child event");
+            ret = calendar_record_clone(this_event->getPlatformCalendarItem(), &record);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Clonning failed");
+            }
+
+            std::stringstream ss;
+            ss<<this_event->getId()->getRid();
+            ret = calendar_record_set_str(record,
+                    _calendar_event.recurrence_id, ss.str().c_str());
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Cannot set event recurrence id");
+            } else {
+                LOGD("Saved the rid for the child.");
+            }
+
+            ret = calendar_record_set_int(record,
+                    _calendar_event.original_event_id, this_event->getId()->getUid());
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Cannot set the parent id");
+            }
+
+            ret = calendar_record_set_int(record,
+                    _calendar_event.freq, CALENDAR_RECURRENCE_NONE);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Cannot set the frequency");
+            }
+
+            ret = calendar_list_add(listForAdd, record);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Can't add the item to the add list");
+            }
+
+            this_event->setIsDetached(true);
+
+            std::string exdate = "";
+            auto exceptions = this_event->getRecurrenceRule()->getExceptions();
+            std::size_t exceptions_size = exceptions.size();
+            for (std::size_t j=0; j<exceptions_size; j++) {
+                long long int utc_time = CalendarUtility::localTimeToUTCTime(exceptions.at(j));
+                std::stringstream strs;
+                strs<<utc_time;
+                exdate.append(strs.str());
+                exdate.append(",");
+            }
+            exdate.append(this_event->getId()->getRid());
+
+            ret = calendar_record_set_str(this_event->getPlatformCalendarItem(),
+                    _calendar_event.exdate, exdate.c_str());
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Can't update the exdate");
+            } else {
+                LOGD("Set the exdate for the parent event");
+            }
+
+            ret = calendar_list_add(listForUpdate, record);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Can't add the item to the update list");
+            }
+            else {
+                LOGD("The item added to the update list");
+            }
+        }
+    }
+
+    // Perform the platform operations.
+    count = -1;
+    ret = calendar_list_get_count(listForAdd, &count);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Getting list count failed");
+    } else {
+        LOGD("Final list count for add");
+    }
+    if (count>0) {
+        ret = calendar_db_insert_records(listForAdd, NULL, NULL);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't insert the item list");
+        } else {
+            LOGD("Add records requst done for update batch operation.");
+        }
+    }
+
+    count = -1;
+    ret = calendar_list_get_count(listForUpdate, &count);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Getting list count failed");
+    } else {
+        LOGD("Final list count for update");
+    }
+    if (count>0) {
+        ret = calendar_db_update_records(listForUpdate);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't update the item list");
+        } else {
+            LOGD("Events updated successfully");
+        }
+    }
+
+    if (listForAdd) {
+        calendar_list_destroy(listForAdd, true);
+    }
+    if (listForUpdate) {
+        calendar_list_destroy(listForUpdate, true);
+    }
+}
+
+
+void Calendar::updateBatchTasks(CalendarCallbackUserData* callback)
+{
+    LOGD("Entered");
+    calendar_list_h listForUpdate;
+    calendar_record_h record = NULL;
+    int ret;
+
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        throw UnknownException("Callback is null");
+    }
+
+    std::size_t task_size = callback->m_tasks.size();
+
+    ret = calendar_list_create(&listForUpdate);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Can't create a list for update");
+    }
+
+    for (std::size_t i = 0; i < task_size; ++i) {
+        CalendarTaskPtr this_task = callback->m_tasks[i];
+
+        this_task->convertAbstractCalendarTaskToPlatformCalendarTask(true);
+        record = NULL;
+        ret = calendar_record_clone(this_task->getPlatformCalendarItem(), &record);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Clonning failed");
+        }
+
+        ret = calendar_list_add(listForUpdate, record);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't add the item to the list");
+        }
+    }
+
+    ret = calendar_db_update_records(listForUpdate);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("calendar_db_update_records failed.");
+        if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException<InvalidValuesException>(ret, "Invalid values error occurred");
+        }
+        else{
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "CALENDAR_ERROR_DB_FAILED occurred");
+        }
+    }
+    if (listForUpdate) {
+        calendar_list_destroy(listForUpdate, true);
+    }
+}
+
+gboolean Calendar::updateBatchCompleted(void *data)
+{
+    LOGD("Entered");
+    auto callback = static_cast<CalendarCallbackUserData*>(data);
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try{
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+
+                callback->callErrorCallback(errobj);
+        }
+        else {
+            callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("InvalidValuesError");
+    }
+    catch (...) {
+        LOGE("UnknownError");
+    }
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+void* Calendar::updateBatchThread(void *data)
+{
+    LOGD("Entered");
+    std::lock_guard<std::mutex> lock(s_mutex);
+    CalendarCallbackUserData* callback;
+    try {
+        callback = static_cast<CalendarCallbackUserData*>(data);
+        if (NULL == callback) {
+            LOGE("Callback is null");
+            return NULL;
+        }
+
+        if (0<callback->m_events.size()) {
+            callback->m_calendar_ptr->updateBatchEvents(callback);
+        }
+        else if (0<callback->m_tasks.size()) {
+            callback->m_calendar_ptr->updateBatchTasks(callback);
+        }
+
+    } catch (const BasePlatformException &err) {
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,"UnknownError.");
+    }
+    if (0 == g_idle_add(updateBatchCompleted, data)) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+    return NULL;
+}
+
+
+void Calendar::updateBatch(CalendarCallbackUserData* callback)
+{
+    LOGD("Entered");
+    if (NULL == callback) {
+        LOGE("NULL cbdata error.");
+        throw UnknownException("NULL cbdata error.");
+    }
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, updateBatchThread, static_cast<void*>(callback))) {
+        LOGE("Failed to create pthread for updateBatch()");
+        throw UnknownException("pthread_create error.");
+    }
+    if (pthread_detach(thread)) {
+        LOGW("Failed to detach the pthread for updateBatch()");
+    }
+}
+
+void Calendar::updateEvent(CalendarEventPtr event, bool updateAllInstances)
+{
+    LOGD("Entered");
+    int ret = 0;
+
+    if (!event->isSet(CALENDAR_EVENT_ATTRIBUTE_ID)) {
+        LOGE("Event id is not set");
+        throw UnknownException("Event id is not set");
+    }
+
+    calendar_record_h record_h =
+            event->convertAbstractCalendarEventToPlatformCalendarEvent(true);
+
+    if (updateAllInstances ||
+            CalendarRecurrenceRule::NO_FREQUENCY == event->getRecurrenceRule()->getFrequency()
+            || event->getId()->isSet(CALENDAR_EVENT_ID_ATTRIBUTE_RID)) {
+                ret = calendar_db_update_record(record_h);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    CalendarUtility::throwCalendarException(ret, "Can't update new item");
+                }
+                LOGD("Calendar item updated.");
+    } else {
+        LOGD("Update the exdate for a recurring parent event and add a new child event.");
+        // First update the parent event.
+        std::string exdate = "";
+        const TZDatePtrVector& exceptions = event->getRecurrenceRule()->getExceptions();
+        const std::size_t exceptions_size = exceptions.size();
+        for (std::size_t i=0; i<exceptions_size; i++) {
+            long long int utc_time = CalendarUtility::localTimeToUTCTime(exceptions.at(i));
+            std::stringstream ss;
+            ss<<utc_time;
+            exdate.append(ss.str());
+            exdate.append(",");
+        }
+        exdate.append(event->getId()->getRid());
+
+        ret = calendar_record_set_str(record_h, _calendar_event.exdate, exdate.c_str());
+        if (ret != CALENDAR_ERROR_NONE) {
+           LOGE("ret : %d", ret);
+           CalendarUtility::throwCalendarException(ret, "Can't update the exdate");
+        } else {
+           LOGD("Set the exdate for the parent event: ");
+        }
+
+        // Don't set the recurrence id for the parent event.
+        ret = calendar_record_set_str(record_h, _calendar_event.recurrence_id, NULL);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't update the exdate");
+        }
+
+        ret = calendar_db_update_record(record_h);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't update new event");
+        }
+        // Now add the detached child event.
+        CalendarRecurrenceRulePtr empty_rrule( new CalendarRecurrenceRule());
+        // Detached event should not have rrule set.
+        event->setRecurrenceRule(empty_rrule);
+
+        // Reset id for record insertion.
+        event->getId()->setUid(0);
+        event->getId()->setRid("");
+        event->getId()->setIsSet(CALENDAR_EVENT_ID_ATTRIBUTE_UID, false);
+        event->getId()->setIsSet(CALENDAR_EVENT_ID_ATTRIBUTE_RID, false);
+
+        addEvent(event);
+
+        event->setIsDetached(true);
+     }
+}
+
+void Calendar::updateTask(CalendarTaskPtr task)
+{
+    LOGD("Entered");
+    int ret;
+    calendar_record_h record_h;
+
+    if (!task->isSet(CALENDAR_TASK_ATTRIBUTE_ID)) {
+        LOGE("Task id is not set");
+        throw UnknownException("Task id is not set");
+    }
+
+    record_h = task->convertAbstractCalendarTaskToPlatformCalendarTask(true);
+
+    ret = calendar_db_update_record(record_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Can't update new item");
+    }
+    LOGD("Calendar item updated.");
+
+}
+
+gboolean Calendar::findCompleted(void *data)
+{
+    LOGD("Entered");
+    CalendarFindCallbackData* callback = static_cast<CalendarFindCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            auto items = callback->getItems();
+            if (!items) {
+                LOGE("items is null");
+                return false;
+            }
+            if (CalendarUtility::CalendarType::EVENT == callback->getType()) {
+                JSObjectRef arr = CalendarUtility::vectorToJSObjectArray<CalendarItemPtr, CalendarEvent,
+                        JSCalendarEvent>(context, *items);
+                callback->callSuccessCallback(arr);
+            } else {
+                JSObjectRef arr = CalendarUtility::vectorToJSObjectArray<CalendarItemPtr, CalendarTask,
+                        JSCalendarTask>(context, *items);
+                callback->callSuccessCallback(arr);
+            }
+        }
+    }
+
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Find callback failed");
+    }
+
+    delete callback;
+    callback = NULL;
+    return false;
+
+}
+
+void* Calendar::findThread(void *data)
+{
+    LOGD("Entered");
+    CalendarFindCallbackData* callback = static_cast<CalendarFindCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+    try{
+        CalendarUtility::CalendarType type =callback->getType();
+        if (CalendarUtility::CalendarType::UNDEFINED == type) {
+            LOGE("Wrong Calendar type");
+            throw TypeMismatchException("Wrong Calendar type");
+        }
+
+        CalendarItemSearchEngine search_engine(type);
+        int calendar_id = callback->getCalendarId();
+        bool is_filter_set = callback->getFilterIsSet();
+        if (is_filter_set) {
+            search_engine.applyFilter(callback->getFilter());
+        }
+        search_engine.setCalendarId(calendar_id, is_filter_set);
+        if (callback->getSortModeIsSet()) {
+            search_engine.applySortMode(callback->getSortMode());
+        }
+
+        callback->setItems(search_engine.find());
+    }
+    catch (const BasePlatformException &error)
+    {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+            error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+    }
+    catch (...) {
+        LOGE("UnknownError");
+        callback->setError("UnknownError", "Find method failed");
+    }
+    guint id = g_idle_add(findCompleted, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+        callback = NULL;
+    }
+    return NULL;
+}
+
+void Calendar::find(CalendarFindCallbackData *callback)
+{
+    LOGD("Entered");
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, findThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void Calendar::queryDestroy(query_s *q)
+{
+    LOGD("Entered");
+    int ret;
+    q->property_id_array.clear();
+    ret = calendar_filter_destroy(q->filter_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Calendar event filter destroy error : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+    ret = calendar_query_destroy(q->query_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Calendar event query destroy error : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+}
+
+void Calendar::queryRecords(query_s *q, calendar_list_h *list_h)
+{
+    LOGD("Entered");
+    int ret;
+    ret = calendar_query_create(q->uri, &q->query_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar event query create error");
+    }
+    ret = calendar_query_set_distinct(q->query_h, true);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar event query distinct set error");
+    }
+    ret = calendar_filter_create(q->uri, &q->filter_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar event filter create error");
+    }
+    size_t size = q->property_id_array.size();
+    for (unsigned int i = 0; i < size; i++) {
+        property_id_value_s *prop = &q->property_id_array[i];
+
+        switch (prop->value_type) {
+        case RECORD_VT_INT:
+            ret = calendar_filter_add_int(q->filter_h, prop->id,
+                    CALENDAR_MATCH_EQUAL, prop->int_value);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Calendar filter integer add error");
+            }
+            break;
+        case RECORD_VT_STR:
+            ret = calendar_filter_add_str(q->filter_h, prop->id,
+                    CALENDAR_MATCH_EXACTLY, prop->str_value);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Calendar filter string add error");
+            }
+            break;
+        default:
+            LOGE("Calendar filter unknown add error");
+            throw UnknownException("Calendar filter unknown add error");
+            break;
+        }
+        if (size > 1 && i < size - 1) {
+            ret = calendar_filter_add_operator(q->filter_h, CALENDAR_FILTER_OPERATOR_OR);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Calendar filter unknown add operator error");
+            }
+        }
+    }
+    ret = calendar_query_set_filter(q->query_h, q->filter_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar event query filter set error");
+    }
+
+    ret = calendar_db_get_records_with_query(q->query_h, 0, 0, list_h);
+    if (ret != CALENDAR_ERROR_NONE) {
+        if (CALENDAR_ERROR_OUT_OF_MEMORY == ret) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Calendar event query records error");
+        }
+        else if (CALENDAR_ERROR_INVALID_PARAMETER == ret) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Calendar event query records error");
+        }
+        else if (CALENDAR_ERROR_DB_FAILED == ret) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Calendar event query records error");
+        }
+    }
+}
+
+long Calendar::addChangeListener(
+    std::shared_ptr<CalendarChangeCallback> callback)
+{
+    LOGD("Entered");
+    int ret;
+    if (s_listener.isEmpty()) {
+
+        const char *view_uri = NULL;
+        switch (m_type) {
+            case CalendarUtility::CalendarType::EVENT:
+                view_uri = _calendar_event._uri;
+                break;
+            case CalendarUtility::CalendarType::TASK:
+                view_uri = _calendar_todo._uri;
+                break;
+            case CalendarUtility::CalendarType::UNDEFINED:
+                LOGE("Unknown calendar type");
+                throw UnknownException("Unknown calendar type");
+        }
+
+        ret = calendar_db_add_changed_cb(view_uri,
+                calendar_db_changed_cb, this);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Calendar DB add event change callback error");
+        }
+    }
+
+    int version = 0;
+    ret = calendar_db_get_current_version(&version);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Can't get version");
+    } else {
+        s_last_verison = version;
+    }
+
+    long callback_id = s_listener.addChangeListener(callback);
+    return callback_id;
+}
+
+void Calendar::removePlatformChangeListener()
+{
+    LOGD("Entered");
+    int ret;
+
+    const char *view_uri = NULL;
+
+    switch (m_type) {
+        case CalendarUtility::CalendarType::EVENT:
+            view_uri = _calendar_event._uri;
+            break;
+        case CalendarUtility::CalendarType::TASK:
+            view_uri = _calendar_todo._uri;
+            break;
+        case CalendarUtility::UNDEFINED:
+            LOGE("Unknown calendar type");
+            break;
+    }
+
+    ret = calendar_db_remove_changed_cb(view_uri, calendar_db_changed_cb, this);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Calendar DB remove event change callback error");
+    }
+
+}
+
+void Calendar::removeChangeListener(const JSContextRef context, long watchId)
+{
+    LOGD("Entered");
+
+    s_listener.removeChangeListener(context, watchId);
+    if (s_listener.isEmpty()) {
+        removePlatformChangeListener();
+        s_last_verison = 0;
+    }
+}
+
+bool Calendar::isValidAccount(long account_id)
+{
+    account_h handle;
+    int ret = account_create(&handle);
+    bool result = false;
+    if (ret != ACCOUNT_ERROR_NONE) {
+        LOGE("Failed to create account handle: %x", ret);
+        throw UnknownException("Failed to create account handle");
+    }
+
+    ret = account_query_account_by_account_id(static_cast<int>(account_id), &handle);
+    if (ret != ACCOUNT_ERROR_NONE) {
+        result = false;
+    } else {
+        result = true;
+    }
+
+    ret = account_destroy(handle);
+    if (ret != ACCOUNT_ERROR_NONE) {
+        LOGE("Failed to destroy account handle: %x", ret);
+        throw UnknownException("Failed to destroy account handle");
+    }
+
+    return result;
+}
+
+} //Calendar
+} //DeviceAPI
+
diff --git a/src/Calendar/Calendar.h b/src/Calendar/Calendar.h
new file mode 100755 (executable)
index 0000000..d3048ca
--- /dev/null
@@ -0,0 +1,143 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CALENDAR_H_
+#define _TIZEN_CALENDAR_H_
+
+#include <calendar_service.h>
+#include <CallbackUserData.h>
+
+#include "CalendarEvent.h"
+#include "CalendarTask.h"
+#include "CalendarChangeCallback.h"
+#include "ChangeListenerContainer.h"
+#include "CalendarFindCallbackData.h"
+#include "CalendarCallbackUserData.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+typedef long CalendarId;
+
+class Calendar;
+typedef std::shared_ptr<Calendar> CalendarPtr;
+
+class Calendar : public Common::SecurityAccessor {
+public:
+    Calendar();
+    virtual ~Calendar();
+
+    void addEvent(CalendarEventPtr event);
+    void addTask(CalendarTaskPtr task);
+
+    CalendarEventPtr getEvent(CalendarEventIdPtr id);
+    CalendarTaskPtr getTask(int id);
+
+    void removeEvent(const CalendarEventIdPtr id);
+    void removeTask(const int id);
+
+    void updateEvent(CalendarEventPtr event, bool updateAllInstances);
+    void updateTask(CalendarTaskPtr task);
+
+    void addBatch(CalendarCallbackUserData* callback);
+    void updateBatch(CalendarCallbackUserData* callback);
+    void removeBatch(CalendarCallbackUserData* callback);
+
+    CalendarId getId();
+    std::string getName();
+    CalendarUtility::CalendarType getType();
+    long getAccountId();
+
+    void setId(long id);
+    void setName(std::string name);
+    void setType(CalendarUtility::CalendarType type);
+    void setAccountId(long accountId);
+    bool isCalendarIdSet();
+
+    static CalendarUtility::CalendarType stringToCalendarType(std::string type);
+
+    long addChangeListener(
+            std::shared_ptr<CalendarChangeCallback> callback);
+    void removeChangeListener(const JSContextRef context, long watchId);
+
+    void find(CalendarFindCallbackData *callback);
+
+    static bool isValidAccount(long m_account_id);
+
+private:
+    Calendar(const Calendar& calendar) {};
+    Calendar & operator =(const Calendar& calendar);
+
+    void addBatchEvents(CalendarCallbackUserData* cbdata);
+    void addBatchTasks(CalendarCallbackUserData* cbdata);
+
+    static std::mutex s_mutex;
+
+    static ChangeListenerContainer s_listener;
+    static long s_last_verison;
+
+    CalendarId m_id;
+    std::string m_name;
+    CalendarUtility::CalendarType m_type;
+    long m_account_id;
+
+    enum  property_value_type_e {RECORD_VT_INT, RECORD_VT_STR};
+
+    typedef struct {
+        int id;
+        property_value_type_e value_type;
+        int int_value;
+        const char *str_value;
+    } property_id_value_s;
+
+    typedef struct {
+        const char *uri;
+        std::vector<property_id_value_s> property_id_array;
+        calendar_query_h query_h;
+        calendar_filter_h filter_h;
+    } query_s;
+
+    calendar_record_h f_rec_h;
+
+    void queryDestroy(query_s *q);
+    void queryRecords(query_s *q, calendar_list_h *list_h);
+
+    static  gboolean addBatchCompleted(void *data);
+    static void* addBatchThread(void *data);
+
+    static  gboolean updateBatchCompleted(void *data);
+    static void* updateBatchThread(void *data);
+    void updateBatchEvents(CalendarCallbackUserData* eventsCallBack);
+    void updateBatchTasks(CalendarCallbackUserData* eventsCallBack);
+
+    static  gboolean removeBatchCompleted(void *data);
+    static void* removeBatchThread(void *data);
+    void removeBatchEvents(CalendarCallbackUserData* cbdata);
+    void removeBatchTasks(CalendarCallbackUserData* cbdata);
+
+    static void calendar_db_changed_cb(const char* view_uri, void* user_data);
+
+    void removePlatformChangeListener();
+
+    static gboolean findCompleted(void *data);
+    static void *findThread(void *data);
+};
+
+}
+}
+
+#endif /* _TIZEN_CALENDAR_H_ */
diff --git a/src/Calendar/CalendarAlarm.cpp b/src/Calendar/CalendarAlarm.cpp
new file mode 100755 (executable)
index 0000000..45e568c
--- /dev/null
@@ -0,0 +1,130 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CalendarAlarm.h"
+#include <PlatformException.h>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+CalendarAlarm::CalendarAlarm()
+{
+    m_alarm_method = CALENDAR_ALARM_METHOD_UNDEFINED;
+    for (std::size_t i = 0; i< CALENDAR_ALARM_NUMBER_OF_ATTRIBUTES; ++i) {
+        m_is_set[i] = false;
+    }
+    setDescription("");
+}
+CalendarAlarm::~CalendarAlarm()
+{
+}
+
+const std::string& CalendarAlarm::getTimeZone()
+{
+    return m_time_zone;
+}
+void CalendarAlarm::setTimeZone(const std::string& time_zone)
+{
+    m_time_zone = time_zone;
+}
+
+long long int CalendarAlarm::getAbsoluteDate() const
+{
+    return m_absolute_date;
+}
+
+void CalendarAlarm::setAbsoluteDateResetBefore(long long int absolute_date)
+{
+    m_is_set[CALENDAR_ALARM_ATTRIBUTE_ABSOLUTE_DATE] = true;
+    m_absolute_date = absolute_date;
+
+    m_is_set[CALENDAR_ALARM_ATTRIBUTE_BEFORE] = false;
+    m_before.reset();
+}
+
+TimeDurationPtr CalendarAlarm::getBefore() const
+{
+    return m_before;
+}
+
+void CalendarAlarm::setBeforeResetAbsoluteDate(TimeDurationPtr before) {
+    m_is_set[CALENDAR_ALARM_ATTRIBUTE_BEFORE] = true;
+    m_before = before;
+
+    m_is_set[CALENDAR_ALARM_ATTRIBUTE_ABSOLUTE_DATE] = false;
+    m_absolute_date = UNDEFINED_TIME;
+}
+
+CalendarAlarmMethod CalendarAlarm::getAlarmMethod() const
+{
+    return m_alarm_method;
+}
+
+void CalendarAlarm::setAlarmMethod(CalendarAlarmMethod method)
+{
+    m_is_set[CALENDAR_ALARM_ATTRIBUTE_ALARM_METHOD] = true;
+    m_alarm_method = method;
+}
+
+const std::string& CalendarAlarm::getDescription() const
+{
+    return m_description;
+}
+
+void CalendarAlarm::setDescription(const std::string& description)
+{
+    m_is_set[CALENDAR_ALARM_ATTRIBUTE_DESCRIPTION] = true;
+    m_description = description;
+}
+
+CalendarAlarmMethod CalendarAlarm::stringToAlarmMethod(const std::string& string_type) {
+    if (TYPE_SOUND == string_type) {
+        return CALENDAR_ALARM_METHOD_SOUND;
+    }
+    if (TYPE_DISPLAY == string_type) {
+        return CALENDAR_ALARM_METHOD_DISPLAY;
+    }
+    LOGE("Invalid CalendarAlarmMethod");
+    throw TypeMismatchException("Invalid CalendarAlarmMethod");
+}
+
+const std::string& CalendarAlarm::alarmMethodToString(CalendarAlarmMethod alarm_method) {
+    if (CALENDAR_ALARM_METHOD_SOUND == alarm_method) {
+        return TYPE_SOUND;
+    }
+    if (CALENDAR_ALARM_METHOD_DISPLAY == alarm_method) {
+        return TYPE_DISPLAY;
+    }
+    LOGE("Invalid CalendarAlarmMethod");
+    throw TypeMismatchException("Invalid CalendarAlarmMethod");
+}
+
+bool CalendarAlarm::isSet(CalendarAlarmAttribute attribute) const
+{
+    return m_is_set[attribute];
+}
+
+void CalendarAlarm::setIsSet(CalendarAlarmAttribute attribute, bool is_set)
+{
+    m_is_set[attribute] = is_set;
+}
+
+} //Calendar
+} //DeviceAPI
diff --git a/src/Calendar/CalendarAlarm.h b/src/Calendar/CalendarAlarm.h
new file mode 100644 (file)
index 0000000..b06b2eb
--- /dev/null
@@ -0,0 +1,93 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CALENDAR_ALARM_H_
+#define _TIZEN_CALENDAR_ALARM_H_
+
+#include <calendar_types.h>
+#include <string>
+#include <memory>
+#include <TimeDuration.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+#define UNDEFINED_TIME -1
+
+class CalendarAlarm;
+typedef std::shared_ptr<CalendarAlarm> CalendarAlarmPtr;
+
+namespace {
+const std::string TYPE_SOUND = "SOUND";
+const std::string TYPE_DISPLAY = "DISPLAY";
+}
+
+enum CalendarAlarmMethod{
+    CALENDAR_ALARM_METHOD_SOUND = CALENDAR_ALARM_ACTION_AUDIO,
+    CALENDAR_ALARM_METHOD_DISPLAY = CALENDAR_ALARM_ACTION_DISPLAY,
+    CALENDAR_ALARM_METHOD_UNDEFINED = CALENDAR_ALARM_ACTION_MAX
+};
+
+enum CalendarAlarmAttribute{
+    CALENDAR_ALARM_ATTRIBUTE_ABSOLUTE_DATE,
+    CALENDAR_ALARM_ATTRIBUTE_BEFORE,
+    CALENDAR_ALARM_ATTRIBUTE_ALARM_METHOD,
+    CALENDAR_ALARM_ATTRIBUTE_DESCRIPTION,
+    CALENDAR_ALARM_NUMBER_OF_ATTRIBUTES
+};
+
+class CalendarAlarm{
+public:
+
+    CalendarAlarm();
+    ~CalendarAlarm();
+
+    const std::string& getTimeZone();
+    void setTimeZone(const std::string& time_zone);
+
+    long long int getAbsoluteDate() const;
+    void setAbsoluteDateResetBefore(long long int absolute_date);
+
+    DeviceAPI::Time::TimeDurationPtr getBefore() const;
+    void setBeforeResetAbsoluteDate(DeviceAPI::Time::TimeDurationPtr before);
+
+    CalendarAlarmMethod getAlarmMethod() const;
+    void setAlarmMethod(CalendarAlarmMethod value);
+
+    const std::string& getDescription() const;
+    void setDescription(const std::string& description);
+
+    static CalendarAlarmMethod stringToAlarmMethod(const std::string& string_type);
+    static const std::string& alarmMethodToString(CalendarAlarmMethod alarm_method);
+
+    bool isSet(CalendarAlarmAttribute attribute) const;
+    void setIsSet(CalendarAlarmAttribute attribute, bool is_set);
+
+private:
+    std::string m_time_zone;
+    long long int m_absolute_date;             //this attribute is used in all date attributes
+    DeviceAPI::Time::TimeDurationPtr m_before;
+    CalendarAlarmMethod m_alarm_method;
+    std::string m_description;
+
+    bool m_is_set[CalendarAlarmAttribute::CALENDAR_ALARM_NUMBER_OF_ATTRIBUTES];
+};
+
+} //Calendar
+} //DeviceAPI
+
+#endif
diff --git a/src/Calendar/CalendarAttendee.cpp b/src/Calendar/CalendarAttendee.cpp
new file mode 100755 (executable)
index 0000000..4adde30
--- /dev/null
@@ -0,0 +1,360 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CalendarAttendee.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+namespace {
+const std::string ROLE_REQ_PARTICIPANT_STRING = "REQ_PARTICIPANT";
+const std::string ROLE_OPT_PARTICIPANT_STRING = "OPT_PARTICIPANT";
+const std::string ROLE_NON_PARTICIPANT_STRING = "NON_PARTICIPANT";
+const std::string ROLE_CHAIR_STRING = "CHAIR";
+
+const std::string STATUS_PENDING_STRING = "PENDING";
+const std::string STATUS_ACCEPTED_STRING = "ACCEPTED";
+const std::string STATUS_DECLINED_STRING = "DECLINED";
+const std::string STATUS_TENTATIVE_STRING = "TENTATIVE";
+const std::string STATUS_DELEGATED_STRING = "DELEGATED";
+const std::string STATUS_COMPLETED_STRING = "COMPLETED";
+const std::string STATUS_PROCESS_STRING = "PROCESS";
+
+const std::string TYPE_INDIVIDUAL_STRING = "INDIVIDUAL";
+const std::string TYPE_GROUP_STRING = "GROUP";
+const std::string TYPE_RESOURCE_STRING = "RESOURCE";
+const std::string TYPE_ROOM_STRING = "ROOM";
+const std::string TYPE_UNKNOWN_STRING = "UNKNOWN";
+}
+
+
+CalendarAttendee::CalendarAttendee() :
+    m_is_name_set(false),
+    m_is_group_set(false),
+    m_is_delegator_uri_set(false),
+    m_is_delegate_uri_set(false),
+    m_is_contact_ref_set(false),
+
+    m_role(REQ_PARTICIPANT_ROLE),
+    m_status(PENDING_AT_STATUS),
+    m_RSVP(false),
+    m_type(INDIVIDUAL_TYPE),
+    m_contact_ref(new Contact::ContactRef())
+{
+    LOGE("ENTERED");
+}
+
+CalendarAttendee::~CalendarAttendee()
+{
+}
+
+bool CalendarAttendee::isNameSet() const
+{
+    return m_is_name_set;
+}
+
+bool CalendarAttendee::isGroupSet() const
+{
+    return m_is_group_set;
+}
+
+bool CalendarAttendee::isDelegatorURISet() const
+{
+    return m_is_delegator_uri_set;
+}
+
+bool CalendarAttendee::isDelegateURISet() const
+{
+    return m_is_delegate_uri_set;
+}
+
+bool CalendarAttendee::isContactRefSet() const
+{
+    return m_is_contact_ref_set;
+}
+
+const std::string& CalendarAttendee::getName() const
+{
+    return m_name;
+}
+
+void CalendarAttendee::setName(const std::string &value)
+{
+    m_name = value;
+    m_is_name_set = true;
+}
+
+void CalendarAttendee::unsetName()
+{
+    m_name = "";
+    m_is_name_set = false;
+}
+
+const std::string& CalendarAttendee::getURI() const
+{
+    return m_uri;
+}
+
+void CalendarAttendee::setURI(const std::string &value)
+{
+    m_uri = value;
+}
+
+CalendarAttendee::CalendarAttendeeRole CalendarAttendee::getRole() const
+{
+    return m_role;
+}
+
+void CalendarAttendee::setRole(CalendarAttendeeRole value)
+{
+    m_role = value;
+}
+
+CalendarAttendee::CalendarAttendeeStatus CalendarAttendee::getStatus() const
+{
+    return m_status;
+}
+
+void CalendarAttendee::setStatus(CalendarAttendeeStatus value)
+{
+    m_status = value;
+}
+
+bool CalendarAttendee::getRSVP() const
+{
+    return m_RSVP;
+}
+
+void CalendarAttendee::setRSVP(bool value)
+{
+    m_RSVP = value;
+}
+
+CalendarAttendee::CalendarAttendeeType CalendarAttendee::getType() const
+{
+    return m_type;
+}
+
+void CalendarAttendee::setType(CalendarAttendeeType value)
+{
+    m_type = value;
+}
+
+const std::string& CalendarAttendee::getGroup() const
+{
+    return m_group;
+}
+
+void CalendarAttendee::setGroup(const std::string &value)
+{
+    m_group = value;
+    m_is_group_set = true;
+}
+
+void CalendarAttendee::unsetGroup()
+{
+    m_group = "";
+    m_is_group_set = false;
+}
+
+const std::string& CalendarAttendee::getDelegatorURI() const
+{
+    return m_delegator_uri;
+}
+
+void CalendarAttendee::setDelegatorURI(const std::string &value)
+{
+    m_delegator_uri = value;
+    m_is_delegator_uri_set = true;
+}
+
+void CalendarAttendee::unsetDelegatorURI()
+{
+    m_delegator_uri = "";
+    m_is_delegator_uri_set = false;
+}
+
+const std::string& CalendarAttendee::getDelegateURI() const
+{
+    return m_delegate_uri;
+}
+
+void CalendarAttendee::setDelegateURI(const std::string &value)
+{
+    m_delegate_uri = value;
+    m_is_delegate_uri_set = true;
+}
+
+void CalendarAttendee::unsetDelegateURI()
+{
+    m_delegate_uri = "";
+    m_is_delegate_uri_set = false;
+}
+
+Contact::ContactRefPtr CalendarAttendee::getContactRef()
+{
+    return m_contact_ref;
+}
+
+void CalendarAttendee::setContactRef(Contact::ContactRefPtr contact_ref)
+{
+    m_contact_ref = contact_ref;
+    m_is_contact_ref_set = true;
+}
+
+void CalendarAttendee::unsetContactRef()
+{
+    m_contact_ref.reset();
+    m_is_contact_ref_set = false;
+}
+
+CalendarAttendee::CalendarAttendeeRole CalendarAttendee::stringToAttendeeRole(const std::string& role)
+{
+    if (ROLE_REQ_PARTICIPANT_STRING == role) {
+        return CalendarAttendee::CalendarAttendeeRole::REQ_PARTICIPANT_ROLE;
+    }
+    if (ROLE_OPT_PARTICIPANT_STRING == role) {
+        return CalendarAttendee::CalendarAttendeeRole::OPT_PARTICIPANT_ROLE;
+    }
+    if (ROLE_NON_PARTICIPANT_STRING == role) {
+        return CalendarAttendee::CalendarAttendeeRole::NON_PARTICIPANT_ROLE;
+    }
+    if (ROLE_CHAIR_STRING == role) {
+        return CalendarAttendee::CalendarAttendeeRole::CHAIR_ROLE;
+    }
+
+    LOGW("Invalid attendee role");
+    throw TypeMismatchException("Invalid attendee role");
+}
+
+const std::string& CalendarAttendee::attendeeRoleToString(CalendarAttendeeRole role)
+{
+    switch (role) {
+        case CalendarAttendee::CalendarAttendeeRole::REQ_PARTICIPANT_ROLE:
+            return ROLE_REQ_PARTICIPANT_STRING;
+        case CalendarAttendee::CalendarAttendeeRole::OPT_PARTICIPANT_ROLE:
+            return ROLE_OPT_PARTICIPANT_STRING;
+        case CalendarAttendee::CalendarAttendeeRole::NON_PARTICIPANT_ROLE:
+            return ROLE_NON_PARTICIPANT_STRING;
+        case CalendarAttendee::CalendarAttendeeRole::CHAIR_ROLE:
+            return ROLE_CHAIR_STRING;
+        default:
+            LOGW("Invalid attendee role");
+            throw TypeMismatchException("Invalid attendee role");
+    }
+}
+
+CalendarAttendee::CalendarAttendeeStatus CalendarAttendee::stringToAttendeeStatus(const std::string& status)
+{
+    if (STATUS_PENDING_STRING == status) {
+        return CalendarAttendee::CalendarAttendeeStatus::PENDING_AT_STATUS;
+    }
+    if (STATUS_ACCEPTED_STRING == status) {
+        return CalendarAttendee::CalendarAttendeeStatus::ACCEPTED_AT_STATUS;
+    }
+    if (STATUS_DECLINED_STRING == status) {
+        return CalendarAttendee::CalendarAttendeeStatus::DECLINED_AT_STATUS;
+    }
+    if (STATUS_TENTATIVE_STRING == status) {
+        return CalendarAttendee::CalendarAttendeeStatus::TENTATIVE_AT_STATUS;
+    }
+    if (STATUS_DELEGATED_STRING == status) {
+        return CalendarAttendee::CalendarAttendeeStatus::DELEGATED_AT_STATUS;
+    }
+    if (STATUS_COMPLETED_STRING == status) {
+        return CalendarAttendee::CalendarAttendeeStatus::COMPLETED_AT_STATUS;
+    }
+    if (STATUS_PROCESS_STRING == status) {
+        return CalendarAttendee::CalendarAttendeeStatus::IN_PROCESS_AT_STATUS;
+    }
+
+    LOGW("Invalid attendee status");
+    throw TypeMismatchException("Invalid attendee status");
+}
+
+const std::string& CalendarAttendee::attendeeStatusToString(CalendarAttendeeStatus status)
+{
+    switch (status) {
+        case CalendarAttendee::CalendarAttendeeStatus::PENDING_AT_STATUS:
+            return STATUS_PENDING_STRING;
+        case CalendarAttendee::CalendarAttendeeStatus::ACCEPTED_AT_STATUS:
+            return STATUS_ACCEPTED_STRING;
+        case CalendarAttendee::CalendarAttendeeStatus::DECLINED_AT_STATUS:
+            return STATUS_DECLINED_STRING;
+        case CalendarAttendee::CalendarAttendeeStatus::TENTATIVE_AT_STATUS:
+            return STATUS_TENTATIVE_STRING;
+        case CalendarAttendee::CalendarAttendeeStatus::DELEGATED_AT_STATUS:
+            return STATUS_DELEGATED_STRING;
+        case CalendarAttendee::CalendarAttendeeStatus::COMPLETED_AT_STATUS:
+            return STATUS_COMPLETED_STRING;
+        case CalendarAttendee::CalendarAttendeeStatus::IN_PROCESS_AT_STATUS:
+            return STATUS_PROCESS_STRING;
+        default:
+            LOGW("Invalid attendee status");
+            throw TypeMismatchException("Invalid attendee status");
+    }
+}
+
+CalendarAttendee::CalendarAttendeeType CalendarAttendee::stringToAttendeeType(const std::string& type)
+{
+    if (TYPE_INDIVIDUAL_STRING == type) {
+        return CalendarAttendee::CalendarAttendeeType::INDIVIDUAL_TYPE;
+    }
+    if (TYPE_GROUP_STRING == type) {
+        return CalendarAttendee::CalendarAttendeeType::GROUP_TYPE;
+    }
+    if (TYPE_RESOURCE_STRING == type) {
+        return CalendarAttendee::CalendarAttendeeType::RESOURCE_TYPE;
+    }
+    if (TYPE_ROOM_STRING == type) {
+        return CalendarAttendee::CalendarAttendeeType::ROOM_TYPE;
+    }
+    if (TYPE_UNKNOWN_STRING == type) {
+        return CalendarAttendee::CalendarAttendeeType::UNKNOWN_TYPE;
+    }
+
+    LOGW("Invalid attendee type");
+    throw TypeMismatchException("Invalid attendee type");
+}
+
+const std::string& CalendarAttendee::attendeeTypeToString(CalendarAttendeeType type)
+{
+    switch (type) {
+        case CalendarAttendee::CalendarAttendeeType::INDIVIDUAL_TYPE:
+            return TYPE_INDIVIDUAL_STRING;
+        case CalendarAttendee::CalendarAttendeeType::GROUP_TYPE:
+            return TYPE_GROUP_STRING;
+        case CalendarAttendee::CalendarAttendeeType::RESOURCE_TYPE:
+            return TYPE_RESOURCE_STRING;
+        case CalendarAttendee::CalendarAttendeeType::ROOM_TYPE:
+            return TYPE_ROOM_STRING;
+        case CalendarAttendee::CalendarAttendeeType::UNKNOWN_TYPE:
+            return TYPE_UNKNOWN_STRING;
+        default:
+            LOGW("Invalid attendee type");
+            throw TypeMismatchException("Invalid attendee type");
+    }
+}
+
+}
+}
+
diff --git a/src/Calendar/CalendarAttendee.h b/src/Calendar/CalendarAttendee.h
new file mode 100755 (executable)
index 0000000..f86135c
--- /dev/null
@@ -0,0 +1,137 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CALENDAR_ATTENDEE_H_
+#define _TIZEN_CALENDAR_ATTENDEE_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <ContactRef.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class CalendarAttendee;
+typedef std::shared_ptr<CalendarAttendee> CalendarAttendeePtr;
+
+class CalendarAttendee {
+public:
+
+    typedef enum {
+        REQ_PARTICIPANT_ROLE,
+        OPT_PARTICIPANT_ROLE,
+        NON_PARTICIPANT_ROLE,
+        CHAIR_ROLE
+    } CalendarAttendeeRole;
+
+    typedef enum {
+        PENDING_AT_STATUS,
+        ACCEPTED_AT_STATUS,
+        DECLINED_AT_STATUS,
+        TENTATIVE_AT_STATUS,
+        DELEGATED_AT_STATUS,
+        COMPLETED_AT_STATUS,
+        IN_PROCESS_AT_STATUS
+    } CalendarAttendeeStatus;
+
+    typedef enum {
+        INDIVIDUAL_TYPE,
+        GROUP_TYPE,
+        RESOURCE_TYPE,
+        ROOM_TYPE,
+        UNKNOWN_TYPE
+    } CalendarAttendeeType;
+
+
+    CalendarAttendee();
+    virtual ~CalendarAttendee();
+
+    bool isNameSet() const;
+    bool isGroupSet() const;
+    bool isDelegatorURISet() const;
+    bool isDelegateURISet() const;
+    bool isContactRefSet() const;
+
+    const std::string& getName() const;
+    void setName(const std::string& value);
+    void unsetName();
+
+    const std::string& getURI() const;
+    void setURI(const std::string &value);
+
+    CalendarAttendeeRole getRole() const;
+    void setRole(CalendarAttendeeRole value);
+
+    CalendarAttendeeStatus getStatus() const;
+    void setStatus(CalendarAttendeeStatus value);
+
+    bool getRSVP() const;
+    void setRSVP(bool value);
+
+    CalendarAttendeeType getType() const;
+    void setType(CalendarAttendeeType value);
+
+    const std::string& getGroup() const;
+    void setGroup(const std::string &value);
+    void unsetGroup();
+
+    const std::string& getDelegatorURI() const;
+    void setDelegatorURI(const std::string &value);
+    void unsetDelegatorURI();
+
+    const std::string& getDelegateURI() const;
+    void setDelegateURI(const std::string &value);
+    void unsetDelegateURI();
+
+    Contact::ContactRefPtr getContactRef();
+    void setContactRef(Contact::ContactRefPtr contact_ref);
+    void unsetContactRef();
+
+    static CalendarAttendeeRole stringToAttendeeRole(const std::string& role);
+    static const std::string& attendeeRoleToString(CalendarAttendeeRole role);
+
+    static CalendarAttendeeStatus stringToAttendeeStatus(const std::string& status);
+    static const std::string& attendeeStatusToString(CalendarAttendeeStatus status);
+
+    static CalendarAttendeeType stringToAttendeeType(const std::string& type);
+    static const std::string& attendeeTypeToString(CalendarAttendeeType type);
+
+
+protected:
+    bool m_is_name_set;
+    bool m_is_group_set;
+    bool m_is_delegator_uri_set;
+    bool m_is_delegate_uri_set;
+    bool m_is_contact_ref_set;
+
+    std::string m_name;
+    std::string m_uri;
+    CalendarAttendeeRole m_role;
+    CalendarAttendeeStatus m_status;
+    bool m_RSVP;
+    CalendarAttendeeType m_type;
+    std::string m_group;
+    std::string m_delegator_uri;
+    std::string m_delegate_uri;
+    Contact::ContactRefPtr m_contact_ref;
+};
+
+}
+}
+
+#endif /* _TIZEN_CALENDAR_ATTENDEE_H_ */
diff --git a/src/Calendar/CalendarCallbackUserData.cpp b/src/Calendar/CalendarCallbackUserData.cpp
new file mode 100755 (executable)
index 0000000..20e3359
--- /dev/null
@@ -0,0 +1,145 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+#include "CalendarCallbackUserData.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+CalendarCallbackUserData::CalendarCallbackUserData(JSContextRef globalCtx,
+        const std::vector<CalendarEventPtr>& events,
+        const std::vector<CalendarTaskPtr>& tasks,
+        CalendarPtr calPtr) :
+        Common::CallbackUserData(globalCtx)
+{
+    LOGD("Entered");
+    m_is_error = false;
+
+    const std::size_t eventsSize = events.size();
+    m_events.reserve(eventsSize);
+    for (std::size_t i = 0; i < eventsSize; ++i) {
+        m_events.push_back(events[i]);
+    }
+
+    const std::size_t tasksSize = tasks.size();
+    m_tasks.reserve(tasksSize);
+    for (std::size_t i = 0; i < tasksSize; ++i) {
+        m_tasks.push_back(tasks[i]);
+    }
+    m_calendar_ptr = calPtr;
+    m_js_result = NULL;
+}
+
+CalendarCallbackUserData::CalendarCallbackUserData(JSContextRef globalCtx,
+        const std::vector<CalendarEventIdPtr>& eventsIds,
+        const std::vector<int>& tasksIds,
+        CalendarPtr calPtr) :
+        Common::CallbackUserData(globalCtx)
+{
+    LOGD("Entered");
+    m_is_error = false;
+    m_events_ids.clear();
+    std::size_t eventsIdsSize = eventsIds.size();
+    m_events_ids.reserve(eventsIdsSize);
+    for (std::size_t i = 0; i < eventsIdsSize; ++i) {
+        m_events_ids.push_back(eventsIds[i]);
+    }
+    m_tasks_ids.clear();
+    std::size_t tasksIdsSize = tasksIds.size();
+    m_tasks_ids.reserve(tasksIdsSize);
+    for (std::size_t i = 0; i < tasksIdsSize; ++i) {
+        m_tasks_ids.push_back(tasksIds[i]);
+    }
+    m_calendar_ptr = calPtr;
+    m_js_result = NULL;
+}
+
+CalendarCallbackUserData::~CalendarCallbackUserData()
+{
+    LOGD("Entered");
+    if (m_js_result) {
+        JSValueUnprotect(getContext(), m_js_result);
+    }
+}
+
+void CalendarCallbackUserData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    LOGD("Entered");
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+void CalendarCallbackUserData::setJsResult(JSObjectRef result)
+{
+    LOGD("Entered");
+    if (m_js_result) {
+        JSValueUnprotect(getContext(), m_js_result);
+    }
+    m_js_result = result;
+    JSValueProtect(getContext(), m_js_result);
+
+}
+
+void CalendarCallbackUserData::setAllInstances(bool all)
+{
+    LOGD("Entered");
+    m_all_instance = all;
+}
+
+bool CalendarCallbackUserData::isError() const
+{
+    LOGD("Entered");
+    return m_is_error;
+}
+
+const std::string& CalendarCallbackUserData::getErrorName() const
+{
+    LOGD("Entered");
+    return m_err_name;
+}
+
+const std::string& CalendarCallbackUserData::getErrorMessage() const
+{
+    LOGD("Entered");
+    return m_err_message;
+}
+JSObjectRef CalendarCallbackUserData::getJsResult()
+{
+    LOGD("Entered");
+    return m_js_result;
+}
+
+bool CalendarCallbackUserData::getIsAllInstances()
+{
+    LOGD("Entered");
+    return m_all_instance;
+}
+
+} // DeviceAPI
+} // Calendar
+
diff --git a/src/Calendar/CalendarCallbackUserData.h b/src/Calendar/CalendarCallbackUserData.h
new file mode 100644 (file)
index 0000000..fde3035
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CALENDAR_CALLBACK_H_
+#define _TIZEN_CALENDAR_CALLBACK_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <string>
+#include <vector>
+#include <memory>
+
+#include "CalendarEvent.h"
+#include "CalendarEventId.h"
+#include "CalendarTask.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class Calendar;
+typedef std::shared_ptr<Calendar> CalendarPtr;
+
+class CalendarCallbackUserData: public Common::CallbackUserData {
+
+public:
+    CalendarCallbackUserData(JSContextRef globalCtx,
+            const std::vector<CalendarEventPtr>& events,
+            const std::vector<CalendarTaskPtr>& tasks, CalendarPtr calPtr);
+
+    CalendarCallbackUserData(JSContextRef globalCtx,
+            const std::vector<CalendarEventIdPtr>& eventsIds,
+            const std::vector<int>& tasksIds,
+            CalendarPtr calPtr);
+
+    ~CalendarCallbackUserData();
+
+    void setError(const std::string& err_name, const std::string& err_message);
+    void setJsResult(JSObjectRef result);
+    void setAllInstances(bool all);
+    bool isError() const;
+    const std::string& getErrorName() const;
+    const std::string& getErrorMessage() const;
+    JSObjectRef getJsResult();
+    bool getIsAllInstances();
+
+    std::vector<CalendarEventPtr> m_events;
+    std::vector<CalendarTaskPtr> m_tasks;
+    std::vector<CalendarEventIdPtr> m_events_ids;
+    std::vector<int> m_tasks_ids;
+    bool m_all_instance;
+    CalendarPtr m_calendar_ptr;
+
+private:
+    std::string m_err_name;
+    std::string m_err_message;
+    bool m_is_error;
+    JSObjectRef m_js_result;
+};
+
+} // DeviceAPI
+} // Calendar
+
+#endif /* CALENDARCALLBACK_H_ */
diff --git a/src/Calendar/CalendarChangeCallback.cpp b/src/Calendar/CalendarChangeCallback.cpp
new file mode 100755 (executable)
index 0000000..fa32fe2
--- /dev/null
@@ -0,0 +1,189 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+#include "CalendarChangeCallback.h"
+#include "CalendarUtility.h"
+#include "JSCalendarItem.h"
+#include "JSCalendarEventId.h"
+#include "JSCalendarTask.h"
+#include "JSCalendarEvent.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+const char* CALENDARADDED = "onitemsadded";
+const char* CALENDARUPDATED = "onitemsupdated";
+const char* CALENDARREMOVED = "onitemsremoved";
+
+CalendarChangeCallback::CalendarChangeCallback(JSContextRef globalCtx,
+        JSObjectRef on_added_obj,
+        JSObjectRef on_updated_obj,
+        JSObjectRef on_removed_obj,
+        int calendar_id):
+        m_callback_data(globalCtx),
+        m_id(calendar_id),
+        m_is_active(true)
+{
+    LOGD("Entered");
+
+    m_callback_data.setCallback(CALENDARADDED, on_added_obj);
+
+    m_callback_data.setCallback(CALENDARUPDATED, on_updated_obj);
+
+    m_callback_data.setCallback(CALENDARREMOVED, on_removed_obj);
+}
+
+CalendarChangeCallback::~CalendarChangeCallback()
+{
+    LOGD("Entered");
+}
+
+void CalendarChangeCallback::addedEvents(const CalendarEventPtrVector& calendar_item)
+{
+    LOGD("Entered");
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef ctx = m_callback_data.getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(ctx)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    JSObjectRef js_obj =
+                CalendarUtility::vectorToJSObjectArray<CalendarEventPtr,
+                JSCalendarEvent>(ctx, calendar_item);
+    m_callback_data.invokeCallback(CALENDARADDED, js_obj);
+}
+
+void CalendarChangeCallback::addedTasks(const CalendarTaskPtrVector& calendar_item)
+{
+    LOGD("Entered");
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef ctx = m_callback_data.getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(ctx)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    JSObjectRef js_obj =
+                CalendarUtility::vectorToJSObjectArray<CalendarTaskPtr,
+                JSCalendarTask>(ctx, calendar_item);
+    m_callback_data.invokeCallback(CALENDARADDED, js_obj);
+}
+
+void CalendarChangeCallback::updatedEvents(const CalendarEventPtrVector& calendar_item)
+{
+    LOGD("Entered");
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef ctx = m_callback_data.getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(ctx)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    JSObjectRef js_obj =
+            CalendarUtility::vectorToJSObjectArray<CalendarEventPtr,
+            JSCalendarEvent>(ctx, calendar_item);
+
+    m_callback_data.invokeCallback(CALENDARUPDATED, js_obj);
+}
+
+void CalendarChangeCallback::updatedTasks(const CalendarTaskPtrVector& calendar_item)
+{
+    LOGD("Entered");
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef ctx = m_callback_data.getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(ctx)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    JSObjectRef js_obj =
+            CalendarUtility::vectorToJSObjectArray<CalendarTaskPtr,
+            JSCalendarTask>(ctx, calendar_item);
+
+    m_callback_data.invokeCallback(CALENDARUPDATED, js_obj);
+}
+
+void CalendarChangeCallback::removedEvent(const CalendarEventIdPtrVector& calendar_item)
+{
+    LOGD("Entered");
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef ctx = m_callback_data.getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(ctx)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    JSObjectRef js_obj =
+            CalendarUtility::vectorToJSObjectArray<CalendarEventIdPtr,
+            JSCalendarEventId>(ctx, calendar_item);
+
+    m_callback_data.invokeCallback(CALENDARREMOVED, js_obj);
+}
+
+void CalendarChangeCallback::removedTask(const std::vector<int>& calendar_item)
+{
+    LOGD("Entered");
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef ctx = m_callback_data.getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(ctx)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    JSObjectRef js_obj =
+            CalendarUtility::vectorToJSObjectArray<int,
+            JSCalendarEventId>(ctx, calendar_item);
+
+    m_callback_data.invokeCallback(CALENDARREMOVED, js_obj);
+}
+
+int CalendarChangeCallback::getCalendarId() const
+{
+    return m_id;
+}
+
+JSContextRef CalendarChangeCallback::getContext() const
+{
+    return m_callback_data.getContext();
+}
+
+void CalendarChangeCallback::setActive(bool act)
+{
+    m_is_active = act;
+}
+
+} // DeviceAPI
+} // Calendar
diff --git a/src/Calendar/CalendarChangeCallback.h b/src/Calendar/CalendarChangeCallback.h
new file mode 100644 (file)
index 0000000..3a77c9d
--- /dev/null
@@ -0,0 +1,62 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CALENDAR_CHANGE_CALLBACK_H__
+#define __TIZEN_CALENDAR_CHANGE_CALLBACK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include <MultiCallbackUserData.h>
+#include "CalendarEvent.h"
+#include "CalendarTask.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+extern const char* CALENDARADDED;
+extern const char* CALENDARUPDATED;
+extern const char* CALENDARREMOVED;
+
+class CalendarChangeCallback {
+public:
+    CalendarChangeCallback(JSContextRef globalCtx,
+            JSObjectRef on_added_obj,
+            JSObjectRef on_updated_obj,
+            JSObjectRef on_removed_obj,
+            int calendar_id);
+    virtual ~CalendarChangeCallback();
+
+    void addedEvents(const CalendarEventPtrVector& calendar_item);
+    void addedTasks(const CalendarTaskPtrVector& calendar_item);
+    void updatedEvents(const CalendarEventPtrVector& calendar_item);
+    void updatedTasks(const CalendarTaskPtrVector& calendar_item);
+    void removedEvent(const CalendarEventIdPtrVector& calendar_ids);
+    void removedTask(const std::vector<int>& calendar_ids);
+
+    int getCalendarId() const;
+    JSContextRef getContext() const;
+    void setActive(bool act);
+private:
+    Common::MultiCallbackUserData m_callback_data;
+    int m_id;
+    bool m_is_active;
+};
+
+} // DeviceAPI
+} // Calendar
+
+#endif /* CALENDARCHANGECALLBACK_H_ */
diff --git a/src/Calendar/CalendarEvent.cpp b/src/Calendar/CalendarEvent.cpp
new file mode 100755 (executable)
index 0000000..16dbd94
--- /dev/null
@@ -0,0 +1,2412 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        CalendarEvent.cpp
+*/
+
+#include "CalendarEvent.h"
+#include "CalendarAlarm.h"
+#include "CalendarAttendee.h"
+#include "CalendarUtility.h"
+#include "JSCalendarEvent.h"
+#include "CalendarManager.h"
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+#include <string>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+const std::string AVAILABILITY_BUSY = "BUSY";
+const std::string AVAILABILITY_FREE = "FREE";
+const std::string EMPTY_STRING = "";
+
+struct CalendarEventHolder {
+    CalendarEventPtr ptr;
+};
+
+CalendarEventCallbackUserData::CalendarEventCallbackUserData(JSContextRef globalCtx) :
+        Common::CallbackUserData(globalCtx),
+        m_is_error(false),
+        m_err_name(""),
+        m_err_message(""),
+        m_js_array_events(NULL)
+{
+    LOGD("Entered");
+}
+
+CalendarEventCallbackUserData::~CalendarEventCallbackUserData()
+{
+    LOGD("Entered");
+    if (m_js_array_events) {
+        JSValueUnprotect(Common::CallbackUserData::getContext(), m_js_array_events);
+    }
+}
+
+void CalendarEventCallbackUserData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool CalendarEventCallbackUserData::isError() const
+{
+    return m_is_error;
+}
+
+const std::string& CalendarEventCallbackUserData::getErrorName() const
+{
+    return m_err_name;
+}
+
+long long int CalendarEventCallbackUserData::getStartDate() const
+{
+    return m_start_date;
+}
+
+void CalendarEventCallbackUserData::setStartDate(long long int start_date, const std::string& time_zone)
+{
+    m_start_date = start_date;
+    m_time_zone = time_zone;
+}
+
+long long int CalendarEventCallbackUserData::getEndDate() const
+{
+    return m_end_date;
+
+}
+void CalendarEventCallbackUserData::setEndDate(long long int end_date, const std::string& time_zone)
+{
+    m_end_date = end_date;
+    m_time_zone = time_zone;
+}
+
+JSObjectRef CalendarEventCallbackUserData::getJSArrayEvents() const
+{
+    return m_js_array_events;
+}
+
+void CalendarEventCallbackUserData::setJSArrayEvents(JSObjectRef js_array_events)
+{
+    if (m_js_array_events) {
+        JSValueUnprotect(Common::CallbackUserData::getContext(), m_js_array_events);
+    }
+    m_js_array_events = js_array_events;
+    JSValueProtect(Common::CallbackUserData::getContext(), m_js_array_events);
+}
+
+CalendarEventPtr CalendarEventCallbackUserData::getEvent() const
+{
+    return m_event;
+}
+void CalendarEventCallbackUserData::setEvent(CalendarEventPtr event)
+{
+    m_event = event;
+}
+const std::string& CalendarEventCallbackUserData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+
+
+CalendarEvent::CalendarEvent():
+        CalendarItem(),
+        m_id(new CalendarEventId()),
+        m_recurrence_rule(new CalendarRecurrenceRule())
+{
+    LOGD("Entered");
+    try{
+        m_is_set.resize(CALENDAR_EVENT_NUMBER_OF_ATTRIBUTES, false);
+    }
+    catch (...) {
+        LOGE("Resize vector failed");
+        throw UnknownException("Can't create the CalendarEvent object");
+    }
+    m_type = CALENDAR_EVENT;
+    setStatus(EVENT_STATUS_CONFIRMED);
+    setIsDetached(false);
+    setAvailability(CALENDAR_EVENT_AVAILABILITY_BUSY);
+    m_platform_item = NULL;
+
+}
+
+CalendarEvent::CalendarEvent(const CalendarEvent& calendar_event):
+        CalendarItem(calendar_event),
+        m_id(new CalendarEventId(*calendar_event.getId())),
+        m_is_detached(calendar_event.getIsDetached()),
+        m_availability(calendar_event.getAvailability())
+{
+    LOGD("Entered");
+    m_type = CALENDAR_EVENT;
+    m_is_set = calendar_event.getIsSet();
+
+    if (m_is_set[CALENDAR_EVENT_ATTRIBUTE_RECURRENCE_RULE]) {
+        m_recurrence_rule = CalendarRecurrenceRulePtr(
+                new CalendarRecurrenceRule(*(calendar_event.m_recurrence_rule)));
+    }
+    else{
+        m_recurrence_rule = CalendarRecurrenceRulePtr(new CalendarRecurrenceRule());
+    }
+}
+
+CalendarEvent::~CalendarEvent()
+{
+    LOGD("Entered");
+}
+
+CalendarEventIdPtr CalendarEvent::getId() const
+{
+    LOGD("Entered");
+    return m_id;
+}
+
+void CalendarEvent::setId(CalendarEventIdPtr id)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_EVENT_ATTRIBUTE_ID] = true;
+    m_id = id;
+}
+
+CalendarEventAvailability CalendarEvent::getAvailability() const
+{
+    LOGD("Entered");
+    return m_availability;
+}
+
+void CalendarEvent::setAvailability(CalendarEventAvailability availability)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_EVENT_ATTRIBUTE_AVAILABILITY] = true;
+    m_availability = availability;
+}
+
+bool CalendarEvent::getIsDetached() const
+{
+    LOGD("Entered");
+    return m_is_detached;
+}
+
+void CalendarEvent::setIsDetached(bool is_detached)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_EVENT_ATTRIBUTE_IS_DETACHED] = true;
+    m_is_detached = is_detached;
+}
+
+CalendarRecurrenceRulePtr CalendarEvent::getRecurrenceRule() const
+{
+    return m_recurrence_rule;
+}
+void CalendarEvent::setRecurrenceRule(CalendarRecurrenceRulePtr recurrence_rule)
+{
+    m_is_set[CALENDAR_EVENT_ATTRIBUTE_RECURRENCE_RULE] = true;
+    m_recurrence_rule = recurrence_rule;
+}
+
+void CalendarEvent::unsetRecurrenceRule()
+{
+    m_is_set[CALENDAR_EVENT_ATTRIBUTE_RECURRENCE_RULE] = false;
+    m_recurrence_rule.reset(new CalendarRecurrenceRule());
+}
+
+CalendarEventAvailability CalendarEvent::stringToCalendarEventAvailability(
+        const std::string& string_event_attribute)
+{
+    LOGD("Entered");
+    if (AVAILABILITY_BUSY == string_event_attribute) {
+        return CALENDAR_EVENT_AVAILABILITY_BUSY;
+    }
+    if (AVAILABILITY_FREE == string_event_attribute) {
+        return CALENDAR_EVENT_AVAILABILITY_FREE;
+    }
+    LOGE("Invalid CalendarEventAvailability");
+    throw TypeMismatchException("Invalid CalendarEventAvailability");
+}
+
+std::string CalendarEvent::calendarEventAvailabilityToString(
+        CalendarEventAvailability event_attribute)
+{
+    LOGD("Entered");
+    if (CALENDAR_EVENT_AVAILABILITY_BUSY == event_attribute) {
+        return AVAILABILITY_BUSY;
+    }
+    if (CALENDAR_EVENT_AVAILABILITY_FREE == event_attribute) {
+        return AVAILABILITY_FREE;
+    }
+    LOGE("Invalid CalendarEventAvailability");
+    throw TypeMismatchException("Invalid CalendarEventAvailability");
+}
+
+bool CalendarEvent::isSet(CalendarEventAttribute attribute) const
+{
+    LOGD("Entered");
+    return m_is_set[attribute];
+}
+
+void CalendarEvent::setIsSet(CalendarEventAttribute attribute, bool is_set)
+{
+    LOGD("Entered");
+    m_is_set[attribute] = is_set;
+}
+
+calendar_record_h CalendarEvent::convertAbstractCalendarEventToPlatformCalendarEvent(
+        bool loadBeforeConvert)
+{
+    LOGD("Entered");
+    int ret;
+    freePlatformCalendarItem();
+    if (loadBeforeConvert) {
+        // Load the item for update operation to include the id.
+        ret = calendar_db_get_record(
+                _calendar_event._uri, getId()->getUid(), &m_platform_item);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Can't load the item: %d", ret);
+            throw UnknownException("Can't load the item");
+        }
+    }
+    else{
+        ret = calendar_record_create(_calendar_event._uri, &m_platform_item);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't create platform record %d", ret);
+            throw UnknownException("Can't create platform record");
+        } else {
+            LOGD("Platform item created with dataType: %s", _calendar_event._uri);
+        }
+    }
+
+    setCalendarIdToPlatformCalendarItem();
+    setDescriptionToPlatformCalendarItem();
+    setSummaryToPlatformCalendarItem();
+    setIsAllDayAndStartDateToPlatformCalendarItem();
+    setLocationToPlatformCalendarItem();
+    setGeolocationToPlatformCalendarItem();
+    setOrganizerToPlatformCalendarItem();
+    setVisibilityToPlatformCalendarItem();
+    setStatusToPlatformCalendarItem();
+    setPriorityToPlatformCalendarItem();
+    setAlarmsToPlatformCalendarItem();
+    setCategoriesToPlatformCalendarItem();
+    setAttendeesToPlatformCalendarItem();
+    setEndDateToPlatformCalendarItem();
+
+    setAvailabilityToPlatformCalendarEvent();
+    setRecurrenceRuleToPlatformCalendarEvent();
+    setRecurrenceIdToPlatformCalendarEvent();
+
+    return getPlatformCalendarItem();
+}
+
+void CalendarEvent::setAvailabilityToPlatformCalendarEvent()
+{
+    LOGD("Entered");
+    calendar_event_busy_status_e availability = CALENDAR_EVENT_BUSY_STATUS_BUSY;
+    if (m_is_set[CALENDAR_EVENT_ATTRIBUTE_AVAILABILITY]) {
+        if (CalendarEventAvailability::CALENDAR_EVENT_AVAILABILITY_FREE == m_availability)
+            availability = CALENDAR_EVENT_BUSY_STATUS_FREE;
+        else{
+            LOGD("Use the default availability");
+        }
+    }
+    int ret = calendar_record_set_int(m_platform_item,
+            _calendar_event.busy_status, availability);
+    if (ret != CALENDAR_ERROR_NONE) {
+         LOGW("Can't set availability.");
+    }
+}
+
+
+void CalendarEvent::setCalendarIdToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_CALENDAR_ID])
+    {
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(m_platform_item,
+                    _calendar_event.calendar_book_id, m_calendar_id)) {
+            LOGW("Can't set calendarId.");
+        }
+    }
+}
+
+void CalendarEvent::setDescriptionToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_DESCRIPTION])
+    {
+        if (CALENDAR_ERROR_NONE != calendar_record_set_str(m_platform_item,
+                    _calendar_event.description, m_description.c_str())) {
+            LOGW("Can't set item description.");
+        }
+    }
+}
+
+void CalendarEvent::setSummaryToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_SUMMARY])
+    {
+        if (CALENDAR_ERROR_NONE != calendar_record_set_str(m_platform_item,
+                    _calendar_event.summary, m_summary.c_str())) {
+            LOGW("Can't set item subject.");
+        }
+    }
+}
+
+void CalendarEvent::setIsAllDayAndStartDateToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    long long int time = UNDEFINED_TIME;
+
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        time = m_start_date;
+        LOGD("use start date, time = %lld, Timezone = %s", time, m_time_zone.c_str());
+    }
+
+    if (UNDEFINED_TIME == time && m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE]) {
+        time = m_end_date;
+        LOGD("use end date, time = %lld, Timezone = %s", time, m_time_zone.c_str());
+    }
+
+    calendar_time_s cal;
+    if (getIsAllDay()) {
+        LOGD("all day item");
+        cal.type = CALENDAR_TIME_LOCALTIME;
+        cal.time.date = CalendarUtility::LLIToCalTime(m_time_zone.c_str(), time).time.date;
+    } else {
+        LOGD("not all day item");
+        cal.type = CALENDAR_TIME_UTIME;
+        cal.time.utime = time;
+    }
+
+    if (CALENDAR_ERROR_NONE != calendar_record_set_caltime(m_platform_item,
+            _calendar_event.start_time, cal)) {
+        LOGE("Can't set start time");
+        throw UnknownException("Can't set start date");
+    }
+
+    if (CALENDAR_ERROR_NONE !=calendar_record_set_str(m_platform_item,
+               _calendar_event.start_tzid, m_time_zone.c_str())) {
+        LOGE("Can't set start date Timezone");
+        throw UnknownException("Can't set start date Timezone");
+    }
+}
+
+void CalendarEvent::setLocationToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_LOCATION])
+    {
+        if (CALENDAR_ERROR_NONE != calendar_record_set_str(m_platform_item,
+                    _calendar_event.location, m_location.c_str())) {
+            LOGW("Can't set location.");
+        }
+    }
+}
+
+void CalendarEvent::setGeolocationToPlatformCalendarItem()
+{
+    LOGD("Entered");;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_GEOLOCATION])
+    {
+        if (CALENDAR_ERROR_NONE !=  calendar_record_set_double(m_platform_item,
+                    _calendar_event.latitude, m_geolocation->getLatitude())) {
+            LOGW("Can't set latitude");
+        }
+
+        if (CALENDAR_ERROR_NONE != calendar_record_set_double(m_platform_item,
+                    _calendar_event.longitude, m_geolocation->getLongitude())) {
+            LOGW("Can't set longitude");
+        }
+    }
+}
+
+void CalendarEvent::setOrganizerToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_ORGANIZER])
+    {
+        if (CALENDAR_ERROR_NONE != calendar_record_set_str(m_platform_item,
+                    _calendar_event.organizer_name, m_organizer.c_str())) {
+            LOGW("Can't set item organizer.");
+        }
+    }
+}
+
+void CalendarEvent::setVisibilityToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_VISIBILITY])
+    {
+        calendar_sensitivity_e visibility = CALENDAR_SENSITIVITY_PUBLIC;
+        switch (getVisibility()) {
+            case CALENDAR_ITEM_VISIBILITY_PRIVATE:
+                visibility = CALENDAR_SENSITIVITY_PRIVATE;
+                break;
+            case CALENDAR_ITEM_VISIBILITY_CONFIDENTIAL:
+                visibility = CALENDAR_SENSITIVITY_CONFIDENTIAL;
+                break;
+            default:
+                LOGD("Use the default visibility CALENDAR_SENSITIVITY_PUBLIC");
+                break;
+        }
+
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(m_platform_item,
+                    _calendar_event.sensitivity, visibility)) {
+            LOGW("Can't set visibility.");
+        }
+    }
+}
+
+void CalendarEvent::setStatusToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_STATUS])
+    {
+        calendar_event_status_e event_status = CALENDAR_EVENT_STATUS_NONE;
+        switch (getStatus()) {
+            case EVENT_STATUS_TENTATIVE:
+                event_status = CALENDAR_EVENT_STATUS_TENTATIVE;
+                break;
+            case EVENT_STATUS_CONFIRMED:
+                event_status = CALENDAR_EVENT_STATUS_CONFIRMED;
+                break;
+            case EVENT_STATUS_CANCELLED:
+                event_status = CALENDAR_EVENT_STATUS_CANCELLED;
+                break;
+            default:
+                LOGD("Use the default status CALENDAR_EVENT_STATUS_NONE");
+                break;
+        }
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(m_platform_item,
+                _calendar_event.event_status, event_status)) {
+            LOGW("Can't set item status ");
+        }
+    }
+}
+
+void CalendarEvent::setPriorityToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_PRIORITY])
+    {
+        calendar_event_priority_e event_priority = CALENDAR_EVENT_PRIORITY_NORMAL;
+        switch (getPriority()) {
+            case CALENDAR_ITEM_PRIORITY_HIGH:
+                event_priority = CALENDAR_EVENT_PRIORITY_HIGH;
+                break;
+            case CALENDAR_ITEM_PRIORITY_LOW:
+                event_priority = CALENDAR_EVENT_PRIORITY_LOW;
+                break;
+            default:
+                LOGD("Use the default priority CALENDAR_EVENT_PRIORITY_NORMAL");
+                break;
+        }
+        if (CALENDAR_ERROR_NONE !=  calendar_record_set_int(m_platform_item,
+                _calendar_event.priority, event_priority)) {
+            LOGW("Can't set event priority");
+        }
+    }
+}
+
+void CalendarEvent::setAlarmsToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    // Remove the preset child alarms before adding new ones.
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_ALARMS])
+    {
+        unsigned int count = 0;
+
+        if (CALENDAR_ERROR_NONE != calendar_record_get_child_record_count(m_platform_item,
+                    _calendar_event.calendar_alarm, &count)) {
+            LOGW("Can't get alarms count");
+        }
+
+        calendar_record_h alarm = NULL;
+        for (unsigned int i=0; i<count; ++i) {
+            alarm = NULL;
+            // Be careful about the index. We always insert 0 cause the child list is updated every time we remove one.
+            if (CALENDAR_ERROR_NONE !=  calendar_record_get_child_record_at_p(m_platform_item,
+                        _calendar_event.calendar_alarm, 0, &alarm)) {
+                LOGW("Can't get the alarm");
+                continue;
+            }
+
+            if (CALENDAR_ERROR_NONE !=  calendar_record_remove_child_record(m_platform_item,
+                        _calendar_event.calendar_alarm, alarm)) {
+                LOGW("Can't remove the alarm");
+            }
+        }
+        // Now add the new alarms.
+        std::size_t size = getAlarms().size();
+        if (size) {
+            for (unsigned int i=0; i < size; ++i)
+            {
+                LOGD("Set the alarms nr %d",i);
+                alarm = NULL;
+                if (CALENDAR_ERROR_NONE!= calendar_record_create(_calendar_alarm._uri, &alarm)) {
+                    LOGW("Alarm creation failed");
+                    continue;
+                }
+
+                CalendarAlarmPtr the_alarm= getAlarms().at(i);
+                calendar_alarm_time_unit_type_e tick_unit = CALENDAR_ALARM_NONE;
+                int tick = 0;
+                if (UNDEFINED_TIME != the_alarm->getAbsoluteDate()) {
+                    tick_unit = CALENDAR_ALARM_TIME_UNIT_SPECIFIC;
+                } else {
+                    if (MSECS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_MINUTE; // minimum calendar time unit.
+                        tick = the_alarm->getBefore()->getLength() / 60000;
+                    } else if (SECS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
+                        tick = the_alarm->getBefore()->getLength() / 60;
+                    } else if (MINS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
+                        tick = the_alarm->getBefore()->getLength();
+                    } else if (HOURS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_HOUR;
+                        tick = the_alarm->getBefore()->getLength();
+                    } else if (DAYS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_DAY;
+                        tick = the_alarm->getBefore()->getLength();
+                    } else {
+                        LOGW("Wrong alarm time unit: %s",
+                                the_alarm->getBefore()->getUnit().c_str());
+                    }
+                }
+
+                if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == tick_unit) {
+                    long long int time = the_alarm->getAbsoluteDate();
+
+                    calendar_time_s at;
+                    at.type = CALENDAR_TIME_UTIME;
+                    at.time.utime = time;
+
+                    LOGD("Save absolute date: %d", time);
+                    if (CALENDAR_ERROR_NONE != calendar_record_set_caltime(alarm,
+                            _calendar_alarm.alarm_time, at)) {
+                        LOGW("Can't set alarm time");
+                    }
+                } else {
+                    if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                            alarm, _calendar_alarm.tick, tick)) {
+                        LOGW("Can't set alarm tick");
+                    }
+                }
+
+                if (CALENDAR_ERROR_NONE !=  calendar_record_set_int(alarm,
+                        _calendar_alarm.tick_unit, tick_unit)) {
+                    LOGW("Can't set alarm tick unit");
+                }
+
+                // Set the alarm type.
+                if (CALENDAR_ERROR_NONE != calendar_record_set_int(alarm, _calendar_alarm.action,
+                        the_alarm->getAlarmMethod())) {
+                    LOGW("Can't set alarm type");
+                }
+
+                // Set the display text
+                if (CALENDAR_ERROR_NONE !=  calendar_record_set_str(alarm, _calendar_alarm.description,
+                        the_alarm->getDescription().c_str())) {
+                    LOGW("Can't set alarm description");
+                }
+
+                if (CALENDAR_ERROR_NONE!= calendar_record_add_child_record(m_platform_item,
+                            _calendar_event.calendar_alarm, alarm)) {
+                    LOGW("Cannot add alarm child record");
+                    if (alarm) {
+                        calendar_record_destroy(alarm, true);
+                    }
+                }
+            }
+        } else {
+            LOGD("No alarms to save.");
+        }
+    }
+}
+
+void CalendarEvent::setCategoriesToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    std::string categories = "";
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_CATEGORIES])
+    {
+        // Need to concatenate all categories into one string separated by a comma.
+        auto cat_vec = getCategories();
+        size_t cat_vec_size = cat_vec.size();
+        for (size_t i = 0; i < cat_vec_size; ++i) {
+            if (!i) {
+                categories.append(cat_vec.at(i));
+            } else {
+                categories.append("," + cat_vec.at(i));
+            }
+        }
+
+        LOGD("Saving categories: %s", categories.c_str());
+        if (CALENDAR_ERROR_NONE != calendar_record_set_str(m_platform_item,
+                    _calendar_event.categories, categories.c_str())) {
+            LOGW("Cannot save categories.");
+        }
+    }
+}
+
+void CalendarEvent::setAttendeesToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    // Remove the preset child attendees before adding new ones.
+    unsigned int count = 0, i;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_ATTENDEES])
+    {
+        if (CALENDAR_ERROR_NONE != calendar_record_get_child_record_count(m_platform_item,
+                    _calendar_event.calendar_attendee, &count)) {
+            LOGW("Can't get attendees count");
+        }
+
+        calendar_record_h attendee = NULL;
+        for ( i = 0; i < count; ++i) {
+            attendee = NULL;
+            // Be careful about the index. We always insert 0 cause the child
+            // list is updated every time we remove one=
+
+            if (CALENDAR_ERROR_NONE != calendar_record_get_child_record_at_p(m_platform_item,
+                        _calendar_event.calendar_attendee, 0, &attendee)) {
+                LOGW("Can't get the attendee");
+                continue;
+            }
+
+            if (CALENDAR_ERROR_NONE != calendar_record_remove_child_record(m_platform_item,
+                        _calendar_event.calendar_attendee, attendee)) {
+                LOGW("Can't remove the attendee");
+                continue;
+            }
+        }
+        // Now add the new attendees.
+        auto attendee_list = getAttendees();
+        const std::size_t size = attendee_list.size();
+        if (size) {
+            for (i = 0; i < size; ++i) {
+                attendee = NULL;
+                if (CALENDAR_ERROR_NONE != calendar_record_create(_calendar_attendee._uri, &attendee)) {
+                    LOGW("Attendee creation failed");
+                    continue;
+                }
+                CalendarAttendeePtr the_attendee = attendee_list.at(i);
+                // save name
+                if (CALENDAR_ERROR_NONE != calendar_record_set_str(attendee, _calendar_attendee.name,
+                        the_attendee->getName().c_str())) {
+                    LOGW("Cannot set attendee name");
+                }
+                // save uri
+                if (CALENDAR_ERROR_NONE != calendar_record_set_str(attendee, _calendar_attendee.email,
+                        the_attendee->getURI().c_str())) {
+                    LOGW("Cannot set attendee URI");
+                }
+                // save role
+                calendar_attendee_role_e role = CALENDAR_ATTENDEE_ROLE_CHAIR;
+                switch (the_attendee->getRole()) {
+                case CalendarAttendee::REQ_PARTICIPANT_ROLE:
+                    role = CALENDAR_ATTENDEE_ROLE_REQ_PARTICIPANT;
+                    break;
+                case CalendarAttendee::OPT_PARTICIPANT_ROLE:
+                    role = CALENDAR_ATTENDEE_ROLE_OPT_PARTICIPANT;
+                    break;
+                case CalendarAttendee::NON_PARTICIPANT_ROLE:
+                    role = CALENDAR_ATTENDEE_ROLE_NON_PARTICIPANT;
+                    break;
+                default:
+                    LOGD("Use the default role");
+                    break;
+                }
+                if (CALENDAR_ERROR_NONE != calendar_record_set_int(attendee,
+                        _calendar_attendee.role, role)) {
+                    LOGW("Cannot set attendee role");
+                }
+                // save status
+                calendar_attendee_status_e status = CALENDAR_ATTENDEE_STATUS_PENDING;
+                switch (the_attendee->getStatus()) {
+                case CalendarAttendee::ACCEPTED_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_ACCEPTED;
+                    break;
+                case CalendarAttendee::DECLINED_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_DECLINED;
+                    break;
+                case CalendarAttendee::TENTATIVE_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_TENTATIVE;
+                    break;
+                case CalendarAttendee::DELEGATED_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_DELEGATED;
+                    break;
+                case CalendarAttendee::COMPLETED_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_COMPLETED;
+                    break;
+                case CalendarAttendee::IN_PROCESS_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_IN_PROCESS;
+                    break;
+                default:
+                    LOGD("Use the default status");
+                    break;
+                }
+                if (CALENDAR_ERROR_NONE != calendar_record_set_int(attendee, _calendar_attendee.status, status)) {
+                    LOGW("Cannot set attendee status");
+                }
+                // save RSVP
+                if (CALENDAR_ERROR_NONE !=  calendar_record_set_int(attendee, _calendar_attendee.rsvp,
+                        the_attendee->getRSVP())) {
+                    LOGW("Cannot set attendee RSVP");
+                }
+                // save type
+                if (CALENDAR_ERROR_NONE !=  calendar_record_set_int(attendee, _calendar_attendee.cutype,
+                        the_attendee->getType())) {
+                    LOGW("Cannot set attendee type");
+                }
+                // save group
+                if (CALENDAR_ERROR_NONE !=  calendar_record_set_str(attendee, _calendar_attendee.group,
+                        the_attendee->getGroup().c_str())) {
+                    LOGW("Cannot set attendee group");
+                }
+                // save delegatorURI
+                if (CALENDAR_ERROR_NONE !=  calendar_record_set_str(attendee, _calendar_attendee.delegator_uri,
+                        the_attendee->getDelegatorURI().c_str())) {
+                    LOGW("Cannot set attendee delegator uri");
+                }
+                // save delegateURI
+                if (CALENDAR_ERROR_NONE !=  calendar_record_set_str(attendee, _calendar_attendee.delegatee_uri,
+                        the_attendee->getDelegateURI().c_str())) {
+                    LOGW("Cannot set attendee delegate uri");
+                }
+                if (the_attendee->isContactRefSet()) {
+                    // save contactId
+                    if (CALENDAR_ERROR_NONE != calendar_record_set_str(attendee, _calendar_attendee.uid,
+                            the_attendee->getContactRef()->getContactIdString().c_str())) {
+                        LOGW("Cannot set attendee uid");
+                    }
+
+                    // save addressBookId
+                    std::stringstream ss(attendee_list.at(i)->getContactRef()->getAddressBookIdString());
+                    int addressBookId;
+                    ss >> addressBookId;
+                    LOGD("addressBookId: %d", addressBookId);
+                    if (CALENDAR_ERROR_NONE !=  calendar_record_set_int(attendee, _calendar_attendee.person_id, addressBookId)) {
+                        LOGW("Cannot set attendee address book id");
+                    }
+                }
+                else {
+                    LOGD("ContactRef not set");
+                }
+
+                if (CALENDAR_ERROR_NONE!= calendar_record_add_child_record(m_platform_item,
+                            _calendar_event.calendar_attendee, attendee)) {
+                    LOGW("Cannot add attendee child record");
+                    if (attendee) {
+                        calendar_record_destroy(attendee, true);
+                    }
+                }
+            }
+        } else {
+           LOGD("No attendee to save.");
+       }
+    }
+}
+
+void CalendarEvent::setEndDateToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    long long int time = UNDEFINED_TIME;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE]) {
+        time = m_end_date;
+        LOGD("Use end/due date");
+    }
+    else if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_DURATION] &&
+            m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        if (0 < getDuration()->getLength()) {
+            LOGD("Set the end/due date from the duration: %d", time);
+            long long length = getDuration()->getLength();
+            std::string unit = getDuration()->getUnit();
+
+            bool correct_unit = true;
+
+            if ( MINS == unit ) {
+                length = length*60;
+            } else if (HOURS == unit) {
+                length = length*60*60;
+            } else if (DAYS == unit) {
+                length = length*24*60*60;
+            } else if (MSECS == unit) {
+                length = length/1000;
+            } else if(SECS != unit ){
+                LOGD("Wrong duration unit: %s", unit.c_str());
+                correct_unit = false;
+            }
+
+            if(getIsAllDay() && correct_unit) {
+                if(length > 24*60*60){
+                    length = length - length%(24*60*60);
+                    length = length - 24*60*60;
+                } else {
+                    length = 0;
+                }
+            }
+            if(correct_unit){
+                time = m_start_date + length;
+            }
+        }
+    }
+
+    if (UNDEFINED_TIME == time && m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        time = m_start_date;
+        LOGD("Set the end/due date from the start time: %d", time);
+    }
+
+    calendar_time_s cal;
+    if (getIsAllDay()) {
+        LOGD("all day case");
+        cal.type = CALENDAR_TIME_LOCALTIME;
+        cal.time.date = CalendarUtility::LLIToCalTime(m_time_zone.c_str(), time).time.date;
+    } else {
+        LOGD("not all day case");
+        cal.type = CALENDAR_TIME_UTIME;
+        cal.time.utime = time;
+    }
+
+    if (CALENDAR_ERROR_NONE != calendar_record_set_caltime(m_platform_item, _calendar_event.end_time, cal)) {
+        LOGE("Can't set end/due date");
+        throw UnknownException("Can't set end date");
+    }
+
+    if (CALENDAR_ERROR_NONE != calendar_record_set_str(m_platform_item,
+                _calendar_event.end_tzid, m_time_zone.c_str())) {
+        LOGE("Can't set end time");
+        throw UnknownException("Can't set end date");
+    }
+}
+
+void CalendarEvent::setRecurrenceRuleToPlatformCalendarEvent()
+{
+    LOGD("Entered");
+    if (!isSet(CALENDAR_EVENT_ATTRIBUTE_RECURRENCE_RULE)) {
+        // Reset platform recurrence properties
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.freq, CALENDAR_RECURRENCE_NONE)) {
+            LOGW("Can't set frequency.");
+        }
+        if (CALENDAR_ERROR_NONE != calendar_record_set_str(
+                m_platform_item, _calendar_event.byday, NULL)) {
+            LOGW("Can't set byday.");
+        }
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.range_type, CALENDAR_RANGE_NONE)) {
+            LOGW("Can't set m_recurrence_rule range type.");
+        }
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.count, CALENDAR_RECURRENCE_NONE)) {
+            LOGW("Can't set occurrence count.");
+        }
+        if (CALENDAR_ERROR_NONE != calendar_record_set_str(
+                m_platform_item, _calendar_event.exdate, NULL)) {
+            LOGW("Can't set exceptions.");
+        }
+        if (CALENDAR_ERROR_NONE != calendar_record_set_str(
+                m_platform_item, _calendar_event.bysetpos, NULL)) {
+            LOGW("Can't set setPositions.");
+        }
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.interval,CALENDAR_RECURRENCE_NONE)) {
+            LOGW("Can't set interval.");
+        }
+
+        calendar_time_s cal;
+        long long int until_time_none = 0;
+        cal.type = CALENDAR_TIME_UTIME;
+        cal.time.utime = until_time_none;
+
+        if (CALENDAR_ERROR_NONE != calendar_record_set_caltime(m_platform_item,
+                _calendar_event.until_time, cal)) {
+            LOGW("Can't set m_recurrence_rule until time");
+        }
+        return;
+    }
+    // set frequency
+    switch (m_recurrence_rule->getFrequency()) {
+    case CalendarRecurrenceRule::NO_FREQUENCY:
+    case CalendarRecurrenceRule::UNDEFINED_FREQUENCY:
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.freq, CALENDAR_RECURRENCE_NONE)) {
+            LOGW("Failed setting frequency.");
+        }
+        return;
+    case CalendarRecurrenceRule::DAILY_FREQUENCY:
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.freq, CALENDAR_RECURRENCE_DAILY)) {
+            LOGW("Failed setting frequency.");
+        }
+        break;
+    case CalendarRecurrenceRule::WEEKLY_FREQUENCY:
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.freq, CALENDAR_RECURRENCE_WEEKLY)) {
+            LOGW("Failed setting frequency.");
+        }
+        break;
+    case CalendarRecurrenceRule::MONTHLY_FREQUENCY:
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.freq, CALENDAR_RECURRENCE_MONTHLY)) {
+            LOGW("Failed setting frequency.");
+        }
+        break;
+    case CalendarRecurrenceRule::YEARLY_FREQUENCY:
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.freq, CALENDAR_RECURRENCE_YEARLY)) {
+            LOGW("Failed setting frequency.");
+        }
+        break;
+    default:
+        LOGW("Invalid reccurence rule frequency");
+        break;
+    }
+
+    // set byday
+    auto daysOfTheWeek = m_recurrence_rule->getDaysOfTheWeek();
+    std::string byday = "";
+    size_t size = daysOfTheWeek.size();
+    for (size_t i = 0; i < size; i++) {
+        byday.append(CalendarRecurrenceRule::recurrenceRuleByDayValueToString(
+            daysOfTheWeek.at(i)));
+        if (i != size - 1) {
+            byday.append(",");
+        }
+    }
+    if (CALENDAR_ERROR_NONE != calendar_record_set_str(
+            m_platform_item, _calendar_event.byday,
+            byday.empty() ? NULL : byday.c_str())) {
+        LOGW("Can't set byday.");
+    }
+    // set the occurrence count
+    if (-1 != m_recurrence_rule->getOccurrenceCount()) {
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.range_type, CALENDAR_RANGE_COUNT)) {
+            LOGW("Can't set m_recurrence_rule range type.");
+        }
+
+        if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                m_platform_item, _calendar_event.count, m_recurrence_rule->getOccurrenceCount())) {
+            LOGW("Can't set occurrence count.");
+        }
+    }
+
+    // set the exceptions
+    std::string exdate = "";
+    size = m_recurrence_rule->getExceptions().size();
+    for (size_t i = 0; i < size; i++) {
+        std::stringstream ss;
+        ss << CalendarUtility::localTimeToUTCTime(m_recurrence_rule->getExceptions().at(i));
+        exdate.append(ss.str());
+        if (i != size - 1) {
+            exdate.append(",");
+        }
+    }
+    if (CALENDAR_ERROR_NONE != calendar_record_set_str(
+            m_platform_item, _calendar_event.exdate, exdate.c_str())) {
+        LOGW("Can't save exceptions.");
+    }
+
+    // set the setPositions
+    std::string bysetpos = "";
+    auto setPositions = m_recurrence_rule->getSetPositions();
+    size = setPositions.size();
+    for (size_t i = 0; i < size; i++) {
+        std::stringstream ss;
+        ss << setPositions.at(i);
+        bysetpos.append(ss.str());
+        if (i != size - 1) {
+            bysetpos.append(",");
+        }
+    }
+
+    if (CALENDAR_ERROR_NONE != calendar_record_set_str(
+            m_platform_item, _calendar_event.bysetpos,
+            bysetpos.empty() ? NULL : bysetpos.c_str())) {
+        LOGW("Can't save setPositions.");
+    }
+
+    // set the recurrence interval
+    if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+            m_platform_item, _calendar_event.interval,
+            m_recurrence_rule->getInterval())) {
+        LOGW("Can't set interval.");
+    }
+    // set the recurrence end date
+    // this is automatically calculated by platform if empty
+    if (m_recurrence_rule->isUntilDateSet()) {
+        long long int date_lli = m_recurrence_rule->getUntilDate();
+        if (UNDEFINED_TIME != date_lli) {
+            if (CALENDAR_ERROR_NONE != calendar_record_set_int(
+                    m_platform_item, _calendar_event.range_type, CALENDAR_RANGE_UNTIL)) {
+                LOGW("Can't set m_recurrence_rule range type");
+            }
+            int ret;
+            calendar_time_s cal = {CALENDAR_TIME_UTIME, {0}};
+            cal.type = CALENDAR_TIME_UTIME;
+            cal.time.utime = date_lli;
+            ret = calendar_record_set_caltime(m_platform_item,
+                    _calendar_event.until_time, cal);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Can't set m_recurrence_rule until time");
+            }
+        }
+    }
+}
+
+void CalendarEvent::setRecurrenceIdToPlatformCalendarEvent()
+{
+    LOGD("Entered");
+    if (!isSet(CALENDAR_EVENT_ATTRIBUTE_RECURRENCE_RULE)) {
+        int ret;
+        ret = calendar_record_set_str(m_platform_item,
+            _calendar_event.recurrence_id, NULL);
+
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set recurrence id");
+        }
+        return;
+    }
+    std::string rid_str = getId()->getRid();
+    std::stringstream ss(rid_str);
+    long long int rid;
+    ss >> rid;
+    if (UNDEFINED_TIME != rid && !rid_str.empty()) {
+        int ret = calendar_record_set_str(m_platform_item,
+            _calendar_event.recurrence_id, ss.str().c_str());
+
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set recurrence id");
+        }
+    }
+}
+
+void CalendarEvent::convertPlatFormEventToAbstractCalendarEvent(calendar_record_h platform_event_tmp)
+{
+    LOGD("Entered");
+    if (NULL == platform_event_tmp) {
+        platform_event_tmp = m_platform_item;
+    }
+    else{
+        freePlatformCalendarItem();
+        int ret = calendar_record_clone(platform_event_tmp, &m_platform_item);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot clone the records: %d", ret);
+        }
+    }
+    setCalendarIdFromPlatformCalendarItem();
+    setDescriptionFromPlatformCalendarItem();
+    setSummaryFromPlatformCalendarItem();
+    setIsAllDayAndStartDateFromPlatformCalendarItem();
+    setLastModifiedDateFromPlatformCalendarItem();
+    setLocationFromPlatformCalendarItem();
+    setGeolocationFromPlatformCalendarItem();
+    setOrganizerFromPlatformCalendarItem();
+    setVisibilityFromPlatformCalendarItem();
+    setStatusFromPlatformCalendarItem();
+    setPriorityFromPlatformCalendarItem();
+    setAlarmsFromPlatformCalendarItem();
+    setCategoriesFromPlatformCalendarItem();
+    setAttendeesFromPlatformCalendarItem();
+    setEndDateFromPlatformCalendarItem();
+
+    setIdFromPlatformCalendarEvent();
+    setIsDetachedFromPlatformCalendarEvent();
+    setAvailabilityFromPlatformCalendarEvent();
+    setRecurrenceRuleFromPlatformCalendarEvent();
+    setRecurrenceIdFromPlatformCalendarEvent();
+
+    copyAceCheckAccessFunction(CalendarManager::getInstance());
+
+    return;
+}
+
+void CalendarEvent::setCalendarIdFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int calendar_id = 0;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_int(m_platform_item,
+                _calendar_event.calendar_book_id, &calendar_id)) {
+        LOGW("Can't get calenadrId");
+    }
+    setCalendarId(calendar_id);
+}
+
+void CalendarEvent::setLastModifiedDateFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    long long int last_modified_date = 0;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_lli(m_platform_item,
+               _calendar_event.last_modified_time, &last_modified_date)) {
+        LOGW("Can't get last modification time");
+        return;
+    }
+    setLastModificationDate(last_modified_date);
+
+    if (UNDEFINED_TIME == last_modified_date) {
+        m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE] = false;
+    }
+
+}
+
+void CalendarEvent::setDescriptionFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    char *description = NULL;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(m_platform_item,
+                _calendar_event.description, &description)) {\
+        LOGW("Can't get description");
+    }
+    if (description) {
+        setDescription(std::string(description));
+    }
+}
+
+void CalendarEvent::setSummaryFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    char *summary = NULL;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(m_platform_item,
+                _calendar_event.summary, &summary)) {
+        LOGW("Can't get summary");
+    }
+    if (summary) {
+        setSummary(std::string(summary));
+    }
+}
+
+void CalendarEvent::setIsAllDayAndStartDateFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    calendar_time_s cal;
+    char *time_zone = NULL;
+
+    if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(m_platform_item,
+                _calendar_event.start_tzid, &time_zone)) {
+        LOGW("Can't get Timezone");
+    }
+
+    m_time_zone = std::string(time_zone);
+
+    if (CALENDAR_ERROR_NONE != calendar_record_get_caltime(m_platform_item,
+                _calendar_event.start_time, &cal)) {
+        LOGW("Can't get start time");
+    }
+
+    // Set the isAllDay flag also.
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE] = true;
+    if (CALENDAR_TIME_LOCALTIME == cal.type) {
+        m_start_date = CalendarUtility::calTimeToLLI(time_zone, cal);
+        setIsAllDay(true);
+    } else {
+        LOGD("cal.time.utime = %lld", cal.time.utime);
+        if (UNDEFINED_TIME == cal.time.utime) {
+            m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE] = false;
+        }
+        m_start_date = cal.time.utime;
+        setIsAllDay(false);
+    }
+}
+
+void CalendarEvent::setLocationFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    char *location = NULL;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(m_platform_item,
+                _calendar_event.location, &location)) {
+        LOGW("Can't get location");
+    }
+    if (location) {
+        setLocation(std::string(location));
+    }
+}
+
+void CalendarEvent::setGeolocationFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    double latitude = UNDEFINED_GEO;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_double(m_platform_item,
+                _calendar_event.latitude, &latitude)) {
+        LOGW("Can't get item latitude");
+        return;
+    }
+    //getGeolocation()->setLatitude(latitude);
+
+    double longitude = UNDEFINED_GEO;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_double(m_platform_item,
+                _calendar_event.longitude, &longitude)) {
+        LOGW("Can't get item longitude.");
+        return;
+    }
+    //getGeolocation()->setLongitude(longitude);
+    m_geolocation = Tizen::SimpleCoordinatesPtr(new Tizen::SimpleCoordinates(latitude, longitude));
+
+    if (UNDEFINED_GEO != latitude && UNDEFINED_GEO != longitude) {
+        m_is_set[CALENDAR_ITEM_ATTRIBUTE_GEOLOCATION] = true;
+    } else {
+        m_is_set[CALENDAR_ITEM_ATTRIBUTE_GEOLOCATION] = false;
+    }
+}
+
+void CalendarEvent::setOrganizerFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    char* organizer = NULL;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(m_platform_item,
+                _calendar_event.organizer_name, &organizer)) {
+        LOGW("Can't get organizer");
+    }
+    if (organizer) {
+        setOrganizer(std::string(organizer));
+    }
+}
+
+void CalendarEvent::setVisibilityFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int visibility;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_int(m_platform_item,
+                _calendar_event.sensitivity, &visibility)) {
+        LOGW("Can't get visibility");
+        return;
+    }
+    switch (visibility) {
+        case CALENDAR_SENSITIVITY_PRIVATE:
+            setVisibility(CALENDAR_ITEM_VISIBILITY_PRIVATE);
+            break;
+        case CALENDAR_SENSITIVITY_CONFIDENTIAL:
+            setVisibility(CALENDAR_ITEM_VISIBILITY_CONFIDENTIAL);
+            break;
+        default:
+            LOGD("Use the default visibility CALENDAR_ITEM_VISIBILITY_PUBLIC");
+            setVisibility(CALENDAR_ITEM_VISIBILITY_PUBLIC);
+            break;
+    }
+}
+
+void CalendarEvent::setStatusFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int status;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_int(m_platform_item,
+                _calendar_event.event_status, &status)) {
+        LOGW("Can't get status");
+        return;
+    }
+
+    switch (status) {
+        case CALENDAR_EVENT_STATUS_TENTATIVE:
+            setStatus(EVENT_STATUS_TENTATIVE);
+            break;
+        case CALENDAR_EVENT_STATUS_CONFIRMED:
+            setStatus(EVENT_STATUS_CONFIRMED);
+            break;
+        case CALENDAR_EVENT_STATUS_CANCELLED:
+            setStatus(EVENT_STATUS_CANCELLED);
+            break;
+        case CALENDAR_TODO_STATUS_CANCELED:
+            setStatus(TASK_STATUS_CANCELLED);
+            break;
+        case CALENDAR_TODO_STATUS_NEEDS_ACTION:
+            setStatus(TASK_STATUS_NEEDS_ACTION);
+            break;
+        case CALENDAR_TODO_STATUS_COMPLETED:
+            setStatus(TASK_STATUS_COMPLETED);
+            break;
+        case CALENDAR_TODO_STATUS_IN_PROCESS:
+            setStatus(TASK_STATUS_IN_PROCESS);
+            break;
+        default:
+            setStatus(EVENT_STATUS_UNDEFINED);
+            break;
+    }
+}
+
+void CalendarEvent::setPriorityFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int priority;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_int(m_platform_item,
+                _calendar_event.priority, &priority)) {
+        LOGW("Can't get event priority");
+        return;
+    }
+    //CALENDAR_TODO_PRIORITY_.... is equal CALENDAR_ITEM_PRIORITY_....
+    switch (priority) {
+        case CALENDAR_EVENT_PRIORITY_LOW:
+            setPriority(CALENDAR_ITEM_PRIORITY_LOW);
+            break;
+        case CALENDAR_EVENT_PRIORITY_HIGH:
+            setPriority(CALENDAR_ITEM_PRIORITY_HIGH);
+            break;
+        default:
+            LOGD("Use the default priority CALENDAR_ITEM_PRIORITY_MEDIUM");
+            setPriority(CALENDAR_ITEM_PRIORITY_MEDIUM);
+            break;
+    }
+}
+
+void CalendarEvent::setIdFromPlatformCalendarEvent()
+{
+    LOGD("Entered");
+    int id;
+    int ret = calendar_record_get_int(m_platform_item, _calendar_event.id, &id);
+    if (CALENDAR_ERROR_NONE!=ret) {
+        LOGE("Can't get calenadrId: %d", ret);
+        throw UnknownException("Can't get id");
+    }
+    m_id = CalendarEventIdPtr(new CalendarEventId());
+    m_id->setUid(id);
+    if (-1 != id) m_is_set[CALENDAR_EVENT_ATTRIBUTE_ID] = true;
+}
+
+void CalendarEvent::setIsDetachedFromPlatformCalendarEvent()
+{
+    LOGD("Entered");
+    int is_detached;
+    int ret = calendar_record_get_int(m_platform_item,
+            _calendar_event.original_event_id, &is_detached);
+
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get is_detached: %d", ret);
+        return;
+    }
+    if (is_detached>0) {
+        setIsDetached(true);
+        LOGD("This is a detached event.");
+    } else {
+        setIsDetached(false);
+    }
+}
+
+void CalendarEvent::setAvailabilityFromPlatformCalendarEvent()
+{
+    LOGD("Entered");
+    int ret, availability;
+    ret = calendar_record_get_int(m_platform_item,
+            _calendar_event.busy_status, &availability);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get visibility: %d", ret);
+        return;
+    }
+    switch (availability) {
+    case CALENDAR_EVENT_BUSY_STATUS_BUSY:
+        setAvailability(CalendarEventAvailability::CALENDAR_EVENT_AVAILABILITY_BUSY);
+        break;
+    default:
+        setAvailability(CalendarEventAvailability::CALENDAR_EVENT_AVAILABILITY_FREE);
+        break;
+    }
+}
+
+void CalendarEvent::setRecurrenceRuleFromPlatformCalendarEvent()
+{
+    LOGD("Entered");
+    int ret;
+    CalendarRecurrenceRulePtr rrule(new CalendarRecurrenceRule());
+
+    // load the recurrence frequency
+    int frequency;
+    ret = calendar_record_get_int(m_platform_item, _calendar_event.freq, &frequency);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get frequency: ", ret);
+        return;
+    }
+    LOGD("frequency = %d", frequency);
+    switch (frequency) {
+        case CALENDAR_RECURRENCE_NONE:
+            rrule->setFrequency(CalendarRecurrenceRule::NO_FREQUENCY);
+            return;
+        case CALENDAR_RECURRENCE_DAILY:
+            rrule->setFrequency(CalendarRecurrenceRule::DAILY_FREQUENCY);
+            break;
+        case CALENDAR_RECURRENCE_WEEKLY:
+            rrule->setFrequency(CalendarRecurrenceRule::WEEKLY_FREQUENCY);
+            break;
+        case CALENDAR_RECURRENCE_MONTHLY:
+            rrule->setFrequency(CalendarRecurrenceRule::MONTHLY_FREQUENCY);
+            break;
+        case CALENDAR_RECURRENCE_YEARLY:
+            rrule->setFrequency(CalendarRecurrenceRule::YEARLY_FREQUENCY);
+            break;
+        default:
+            LOGW("Unknown recurrence frequency");
+            rrule->setFrequency(CalendarRecurrenceRule::NO_FREQUENCY);
+            return;
+    }
+
+    // load the byday
+    std::vector<CalendarRecurrenceRule::RecurrenceRuleByDayValue> daysOfTheWeek;
+    char* byday = NULL;
+    ret = calendar_record_get_str_p(m_platform_item, _calendar_event.byday, &byday);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get byday: %d", ret);
+    }
+    if (byday) {
+        LOGD("Loaded byday: %s", byday);
+        char *saveptr = NULL;
+        char* pch = strtok_r(byday, ",", &saveptr);
+        while (NULL != pch) {
+            std::string day(pch);
+            daysOfTheWeek.push_back(
+                    CalendarRecurrenceRule::stringToRecurrenceRuleByDayValue(day));
+            pch = strtok_r(NULL, ",", &saveptr);
+        }
+    }
+    rrule->setDaysOfTheWeek(daysOfTheWeek);
+
+    // load the recurrence interval
+    int interval;
+    ret = calendar_record_get_int(m_platform_item, _calendar_event.interval, &interval);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get interval: %d", ret);
+    }
+    rrule->setInterval(interval);
+
+    // load the occurrence count
+    int occurrenceCount;
+    ret = calendar_record_get_int(m_platform_item, _calendar_event.count, &occurrenceCount);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get occurrence count: %d", ret);
+    }
+    rrule->setOccurrenceCount(occurrenceCount);
+
+    // load the recurrence end date
+    calendar_time_s cal = {CALENDAR_TIME_UTIME, {0}};
+    ret = calendar_record_get_caltime(m_platform_item, _calendar_event.until_time, &cal);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get recurrence end date: %d", ret);
+    }
+
+    char *timeZone = NULL;
+    ret = calendar_record_get_str_p(m_platform_item, _calendar_event.start_tzid, &timeZone);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get timeZone: %d", ret);
+    }
+
+    if (cal.time.utime > 0) {
+        if (CALENDAR_RECORD_NO_UNTIL == cal.time.utime) {
+            LOGD("untilDate is not set");
+        } else {
+            rrule->setUntilDate(cal.time.utime);
+        }
+    } else {
+        LOGD("untilDate is not set");
+    }
+    rrule->setTimezone(timeZone);
+
+    LOGD("endDate from platform = %d", rrule->getUntilDate());
+
+    // load the exceptions
+    std::vector<DeviceAPI::Time::TZDatePtr> exceptions;
+    char* exdate = NULL;
+    ret = calendar_record_get_str_p(m_platform_item, _calendar_event.exdate, &exdate);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get exdate: %d", ret);
+    }
+    if (exdate) {
+        LOGD("Loaded exdate: %s" ,exdate);
+        char *saveptr = NULL;
+        char *pch = strtok_r(exdate, ",", &saveptr);
+        while (NULL != pch) {
+            std::stringstream ss(pch);
+            long long int oneException;
+            ss>>oneException;
+            DeviceAPI::Time::TZDatePtr date = CalendarUtility::utcTimeToTZDate(
+                timeZone, oneException, true);
+            exceptions.push_back(date);
+            pch = strtok_r(NULL, ",", &saveptr);
+        }
+    }
+    rrule->setExceptions(exceptions);
+
+    // load the setPositions
+    std::vector<long long int> positions;
+    char* bysetpos = NULL;
+    ret = calendar_record_get_str_p(m_platform_item, _calendar_event.bysetpos, &bysetpos);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get bysetpos: %d", ret);
+    }
+    if (bysetpos) {
+        LOGD("Loaded bysetpos: %s", bysetpos);
+        char *saveptr = NULL;
+        char *pch = strtok_r(bysetpos, ",", &saveptr);
+        while (NULL != pch) {
+            std::stringstream ss(pch);
+            long long int setPos;
+            ss>>setPos;
+            positions.push_back(setPos);
+            pch = strtok_r(NULL, ",", &saveptr);
+        }
+    }
+    rrule->setSetPositions(positions);
+
+    // set the loaded recurrence rule
+    setRecurrenceRule(rrule);
+}
+
+void CalendarEvent::setRecurrenceIdFromPlatformCalendarEvent()
+{
+    LOGD("Entered");
+    char* recurrence_id = NULL;
+    int ret = calendar_record_get_str_p(m_platform_item,
+            _calendar_event.recurrence_id, &recurrence_id);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get recurrence id: %d", ret);
+        return;
+    }
+
+    if (recurrence_id && EMPTY_STRING != recurrence_id) {
+        LOGD("Set the recurrence id: %s", recurrence_id);
+        m_id->setRid(std::string(recurrence_id));
+    } else {
+        m_id->setRid("");
+        m_id->setIsSet(CALENDAR_EVENT_ID_ATTRIBUTE_RID, false);
+    }
+}
+
+void CalendarEvent::setAlarmsFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    unsigned int count = 0;
+    calendar_list_h list = NULL;
+
+    if (CALENDAR_ERROR_NONE != calendar_record_get_child_record_count(m_platform_item,
+                _calendar_event.calendar_alarm, &count)) {
+        LOGW("Can't get alarms count");
+    }
+    if (!count) {
+        LOGD("No alarms to set.");
+        return;
+    }
+    LOGD("Number of alarms: %d", count);
+
+    if (CALENDAR_ERROR_NONE != calendar_record_clone_child_record_list(m_platform_item,
+                _calendar_event.calendar_alarm, &list)) {
+        LOGW("Can't get alarms list");
+        return;
+    }
+
+    int tick, tick_unit;
+    calendar_record_h alarm = NULL;
+    for (unsigned int i = 0; i < count; ++i)
+    {
+        LOGD("Processing the alarm %d", i);
+
+        if (CALENDAR_ERROR_NONE != calendar_record_get_child_record_at_p(m_platform_item,
+                    _calendar_event.calendar_alarm, i, &alarm)) {
+            LOGW("Can't get the alarm");
+            continue;
+        }
+        CalendarAlarmPtr the_alarm(new CalendarAlarm());
+
+        if (CALENDAR_ERROR_NONE != calendar_record_get_int(alarm,
+                _calendar_alarm.tick_unit, &tick_unit)) {
+            LOGW("Cannot read alarm tick unit");
+            continue;
+        }
+        if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == tick_unit) {
+            calendar_time_s at;
+            if (CALENDAR_ERROR_NONE != calendar_record_get_caltime(alarm,
+                    _calendar_alarm.alarm_time, &at)) {
+                LOGW("Can't get alarm tick");
+                continue;
+            }
+            the_alarm->setAbsoluteDateResetBefore(at.time.utime);
+            the_alarm->setTimeZone(m_time_zone);
+            LOGD("Loaded absolute date");
+        } else {
+            if (CALENDAR_ERROR_NONE != calendar_record_get_int(alarm,
+                    _calendar_alarm.tick, &tick)) {
+                LOGW("Cannot read alarm tick. Stop processing alarms.");
+                continue;
+            }
+            TimeDurationPtr duration_ptr(new TimeDuration());
+            if (CALENDAR_ALARM_TIME_UNIT_MINUTE==tick_unit) {
+                duration_ptr->setUnit(MINS);
+                duration_ptr->setLength(tick);
+            } else if (CALENDAR_ALARM_TIME_UNIT_HOUR==tick_unit) {
+                duration_ptr->setUnit(HOURS);
+                duration_ptr->setLength(tick);
+            } else if (CALENDAR_ALARM_TIME_UNIT_DAY==tick_unit) {
+                duration_ptr->setUnit(DAYS);
+                duration_ptr->setLength(tick);
+            } else if (CALENDAR_ALARM_TIME_UNIT_WEEK==tick_unit) {
+                duration_ptr->setUnit(DAYS);
+                duration_ptr->setLength(tick*7);
+            } else {
+                LOGW("Wrong tick unit: %d", tick_unit);
+            }
+            the_alarm->setBeforeResetAbsoluteDate(duration_ptr);
+        }
+
+        int type;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_int(alarm,
+                _calendar_alarm.action, &type)) {
+            LOGW("Cannot read alarm type");
+            continue;
+        }
+        the_alarm->setAlarmMethod(static_cast<CalendarAlarmMethod>(type));
+
+        char* description = NULL;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(alarm,
+                _calendar_alarm.description, &description)) {
+            LOGW("Cannot read alarm description");
+            the_alarm->setDescription("");
+        } else {
+            if (description) {
+                LOGD("Alarm description: %s", description);
+                the_alarm->setDescription(std::string(description));
+            }
+        }
+        // Save the alarm.
+        m_alarms.push_back(the_alarm);
+    }
+
+    if (list) {
+        calendar_list_destroy(list, true);
+        list = NULL;
+    }
+}
+
+void CalendarEvent::setCategoriesFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    m_categories.clear();
+    char *categories = NULL;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(m_platform_item,
+                _calendar_event.categories, &categories)) {
+        LOGW("Can't get categories");
+    }
+
+    if (categories) {
+        LOGD("Loaded categories: %d", categories);
+        char *saveptr = NULL;
+        char* pch = strtok_r(categories, ",", &saveptr);
+
+        auto l_categories = getCategories();
+        while (NULL != pch) {
+            try{
+                l_categories.push_back(pch);
+                pch = strtok_r(NULL, ",", &saveptr);
+            }
+            catch (...) {
+                LOGE("Exception in push_back function");
+                throw UnknownException(
+                    "Exception in push_back in setCategoriesFromPlatformCalendarEvent");
+            }
+        }
+
+        setCategories(l_categories);
+    }
+}
+
+void CalendarEvent::setAttendeesFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (!m_attendees.empty()) {
+        m_attendees.clear();
+    }
+    unsigned int count = 0, i;
+    calendar_record_h attendee = NULL;
+    calendar_list_h list = NULL;
+
+
+    if (CALENDAR_ERROR_NONE != calendar_record_get_child_record_count(m_platform_item,
+                _calendar_event.calendar_attendee, &count)) {
+        LOGW("Can't get attendee count");
+        return;
+    }
+
+    if (!count) {
+        LOGD("No attendees to set.");
+        return;
+    }
+
+    if (CALENDAR_ERROR_NONE != calendar_record_clone_child_record_list(m_platform_item,
+                _calendar_event.calendar_attendee, &list)) {
+        LOGW("Can't get attendee list");
+        return;
+    }
+
+    for (i = 0; i < count; ++i)
+    {
+        LOGD("Processing the attendee %d", i);
+        if (CALENDAR_ERROR_NONE != calendar_record_get_child_record_at_p(m_platform_item,
+                    _calendar_event.calendar_attendee, i, &attendee)) {
+            LOGW("Can't get attendee record");
+            continue;
+        }
+
+        CalendarAttendeePtr attendee_ptr(new CalendarAttendee());
+        // load name
+        char* attendee_name = NULL;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(attendee, _calendar_attendee.name, &attendee_name)) {
+            LOGW("Cannot read attendee name. Setting an empty string.");
+            attendee_ptr->setName("");
+        } else {
+            if (attendee_name) {
+                attendee_ptr->setName(attendee_name);
+            }
+        }
+        // load URI
+        char* attendee_URI = NULL;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(attendee, _calendar_attendee.email, &attendee_URI)) {
+            LOGW("Cannot read attendee URI. Setting an empty string.");
+            attendee_ptr->setURI("");
+        } else {
+            if (attendee_URI) {
+                attendee_ptr->setURI(attendee_URI);
+            }
+        }
+
+        // load role
+        int attendee_role;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_int(attendee, _calendar_attendee.role, &attendee_role)) {
+            LOGW("Cannot read attendee role. Setting the default value.");
+        }
+        switch (attendee_role) {
+            case CALENDAR_ATTENDEE_ROLE_OPT_PARTICIPANT:
+                attendee_ptr->setRole(CalendarAttendee::OPT_PARTICIPANT_ROLE);
+                break;
+            case CALENDAR_ATTENDEE_ROLE_NON_PARTICIPANT:
+                attendee_ptr->setRole(CalendarAttendee::NON_PARTICIPANT_ROLE);
+                break;
+            case CALENDAR_ATTENDEE_ROLE_CHAIR:
+                attendee_ptr->setRole(CalendarAttendee::CHAIR_ROLE);
+                break;
+            default:
+                attendee_ptr->setRole(CalendarAttendee::REQ_PARTICIPANT_ROLE);
+                break;
+        }
+
+        // load status
+        int attendee_status;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_int(attendee, _calendar_attendee.status, &attendee_status)) {
+            LOGW("Cannot read attendee status. Setting the default value.");
+        }
+        switch (attendee_status) {
+            case CALENDAR_ATTENDEE_STATUS_ACCEPTED:
+                attendee_ptr->setStatus(CalendarAttendee::ACCEPTED_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_DECLINED:
+                attendee_ptr->setStatus(CalendarAttendee::DECLINED_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_TENTATIVE:
+                attendee_ptr->setStatus(CalendarAttendee::TENTATIVE_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_DELEGATED:
+                attendee_ptr->setStatus(CalendarAttendee::DELEGATED_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_COMPLETED:
+                attendee_ptr->setStatus(CalendarAttendee::COMPLETED_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_IN_PROCESS:
+                attendee_ptr->setStatus(CalendarAttendee::IN_PROCESS_AT_STATUS);
+                break;
+            default:
+                attendee_ptr->setStatus(CalendarAttendee::PENDING_AT_STATUS);
+                break;
+        }
+
+        // load RSVP
+        int attendee_RSVP;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_int(attendee, _calendar_attendee.rsvp, &attendee_RSVP)) {
+            LOGW("Cannot read attendee RSVP. Setting the default value.");
+        }
+        attendee_ptr->setRSVP(attendee_RSVP>0 ? true : false);
+
+        // load type
+        int attendee_type;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_int(attendee, _calendar_attendee.cutype, &attendee_type)) {
+            LOGW("Cannot read attendee type. Setting the default value.");
+        }
+        attendee_ptr->setType(static_cast<CalendarAttendee::CalendarAttendeeType> (attendee_type));
+
+        // load group
+        char* attendee_group = NULL;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(attendee, _calendar_attendee.group, &attendee_group)) {
+            LOGW("Cannot read attendee group. Setting an empty string.");
+            attendee_ptr->setGroup("");
+        } else {
+            if (attendee_group) {
+                attendee_ptr->setGroup(attendee_group);
+            }
+        }
+        // load delegatorURI
+        char* attendee_delegator_URI = NULL;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(attendee, _calendar_attendee.delegator_uri,
+                &attendee_delegator_URI)) {
+            LOGW("Cannot read attendee delegatorURI. Setting an empty string.");
+            attendee_ptr->setDelegatorURI("");
+        } else {
+            if (attendee_delegator_URI) {
+                attendee_ptr->setDelegatorURI(std::string(attendee_delegator_URI));
+            }
+        }
+        // load delegateURI
+        char* attendee_delegate_URI = NULL;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(attendee, _calendar_attendee.delegatee_uri,
+                &attendee_delegate_URI)) {
+            LOGW("Cannot read attendee delegateURI. Setting an empty string.");
+            attendee_ptr->setDelegateURI("");
+        } else {
+            if (attendee_delegate_URI) {
+                attendee_ptr->setDelegateURI(std::string(attendee_delegate_URI));
+            }
+        }
+        // load contactId
+        char *attendee_contact_Id = NULL;
+        Contact::ContactRefPtr ref_ptr;
+        if (!attendee_ptr->isContactRefSet()) {
+            ref_ptr.reset(new Contact::ContactRef());
+            attendee_ptr->setContactRef(ref_ptr);
+        }
+        else {
+            ref_ptr = attendee_ptr->getContactRef();
+        }
+
+        if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(attendee, _calendar_attendee.uid, &attendee_contact_Id)) {
+            LOGW("Cannot read attendee UId. Setting an empty string.");
+            ref_ptr->setContactIdString("");
+        } else {
+            if (attendee_contact_Id) {
+                ref_ptr->setContactIdString(attendee_contact_Id);
+            }
+        }
+
+        // load addressBookId
+        int attendee_address_book_id;
+        if (CALENDAR_ERROR_NONE != calendar_record_get_int(attendee, _calendar_attendee.person_id, &attendee_address_book_id)) {
+            LOGW("Cannot read attendee address book id. Setting an empty string.");
+            attendee_address_book_id = -1;
+        }
+        std::string id;
+        if (attendee_address_book_id >= 0) {
+            id = std::to_string(attendee_address_book_id);
+        } else {
+            id = "";
+        }
+        ref_ptr->setAddressBookIdString(id);
+
+        try {
+            m_attendees.push_back(attendee_ptr);
+        } catch (...) {
+            LOGE("Exception in push_back function");
+            throw UnknownException("Exception in push_back in setAttendeesFromPlatformCalendarEvent");
+        }
+    }
+    if (list) {
+        calendar_list_destroy(list, true);
+        list = NULL;
+    }
+}
+
+void CalendarEvent::setEndDateFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    if (NULL == m_platform_item) {
+        LOGE("m_platformEvent is not set");
+        throw UnknownException("m_platformEvent is not set");
+    }
+    calendar_time_s cal;
+    // Retrive the time zone info only when the start time is loaded.
+    char *time_zone = NULL;
+    if (CALENDAR_ERROR_NONE != calendar_record_get_str_p(m_platform_item, _calendar_event.end_tzid, &time_zone)) {
+        LOGW("Can't get Timezone");
+    }
+
+    m_time_zone = std::string(time_zone);
+
+    if (CALENDAR_ERROR_NONE != calendar_record_get_caltime(m_platform_item, _calendar_event.end_time, &cal)) {
+        LOGW("Can't get due/end time");
+        return;
+    }
+    // if the user use duration he should get the duration not end-date
+    // Set the isAllDay flag also.
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE] = true;
+    if (CALENDAR_TIME_LOCALTIME == cal.type) {
+        m_end_date = CalendarUtility::calTimeToLLI(time_zone, cal);
+        setIsAllDay(true);
+    } else {
+        LOGD("cal.time.utime = %lld, time_zone = %s", cal.time.utime, time_zone);
+        m_end_date = cal.time.utime;
+        if (UNDEFINED_TIME == cal.time.utime) {
+            m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE] = false;
+        }
+        setIsAllDay(false);
+    }
+}
+
+gboolean CalendarEvent::expandRecurrenceCompleted(void *data)
+{
+    auto callback = static_cast<CalendarEventCallbackUserData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            JSValueRef result = callback->getJSArrayEvents();
+            callback->callSuccessCallback(result);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Error %s, with msg: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("UnknownError");
+    }
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+void* CalendarEvent::expandRecurrenceThread(void *data)
+{
+    LOGD("Entered");
+    auto callback = static_cast<CalendarEventCallbackUserData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+    CalendarEventPtrVector expandResultsVector;
+
+    const long long int startDate = callback->getStartDate();
+    const long long int endDate = callback->getEndDate();
+    bool isAllDay = callback->getEvent()->getIsAllDay();
+
+    calendar_query_h query = NULL;
+    calendar_filter_h filter = NULL;
+    calendar_list_h list = NULL;
+
+    try {
+        if (CalendarRecurrenceRule::NO_FREQUENCY ==
+                callback->getEvent()->getRecurrenceRule()->getFrequency()) {
+            LOGE("This is not a recurring event.");
+            throw InvalidValuesException("This is not a recurring event.");
+        }
+
+        calendar_record_h currentRecord = NULL;
+        int ret, currentRecordIndex, count=0;
+
+        calendar_time_s st, et;
+        if (isAllDay) {
+            st.type = CALENDAR_TIME_LOCALTIME;
+            st.time.date = CalendarUtility::LLIToCalTime(
+                    callback->getEvent()->getTimezone().c_str(), startDate).time.date;
+
+            et.type = CALENDAR_TIME_LOCALTIME;
+            et.time.date = CalendarUtility::LLIToCalTime(
+                    callback->getEvent()->getTimezone().c_str(), endDate).time.date;
+        } else {
+            st.type = CALENDAR_TIME_UTIME;
+            st.time.utime = startDate;
+
+            et.type = CALENDAR_TIME_UTIME;
+            et.time.utime = endDate;
+        }
+
+        if (isAllDay) {
+            ret = calendar_query_create(_calendar_instance_localtime_calendar_book._uri, &query);
+        } else {
+            ret = calendar_query_create(_calendar_instance_utime_calendar_book._uri, &query);
+        }
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Creating a query failed.");
+            throw UnknownException("Creating a query failed");
+        }
+
+        if (isAllDay) {
+            ret = calendar_filter_create(_calendar_instance_localtime_calendar_book._uri, &filter);
+        } else {
+            ret = calendar_filter_create(_calendar_instance_utime_calendar_book._uri, &filter);
+        }
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Creating a filter failed.");
+            throw UnknownException("Creating a filter failed.");
+        }
+
+        if (isAllDay) {
+            ret = calendar_filter_add_caltime(filter,
+                    _calendar_instance_localtime_calendar_book.start_time,
+                    CALENDAR_MATCH_GREATER_THAN_OR_EQUAL, st);
+        } else {
+            ret = calendar_filter_add_caltime(filter,
+                    _calendar_instance_utime_calendar_book.start_time,
+                    CALENDAR_MATCH_GREATER_THAN_OR_EQUAL, st);
+        }
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Adding a caltime filter failed.");
+            throw UnknownException( "Adding a caltime filter failed.");
+        }
+
+        ret = calendar_filter_add_operator(filter, CALENDAR_FILTER_OPERATOR_AND);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Adding a filter operator failed.");
+            throw UnknownException("Adding a filter operator failed.");
+        }
+
+        if (isAllDay) {
+            ret = calendar_filter_add_caltime(filter,
+                    _calendar_instance_localtime_calendar_book.end_time,
+                    CALENDAR_MATCH_LESS_THAN_OR_EQUAL, et);
+        } else {
+            ret = calendar_filter_add_caltime(filter,
+                    _calendar_instance_utime_calendar_book.end_time,
+                    CALENDAR_MATCH_LESS_THAN_OR_EQUAL, et);
+        }
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Adding a caltime filter failed.");
+            throw UnknownException( "Adding a caltime filter failed.");
+        }
+
+        ret = calendar_query_set_filter(query, filter);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Setting a filter.");
+            throw UnknownException( "Setting a filter.");
+        }
+
+        ret = calendar_db_get_records_with_query(query, 0, 0, &list);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Getting event instances failed.");
+            throw UnknownException("Getting event instances failed.");
+        }
+
+        ret = calendar_list_get_count(list, &count);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Can't get the item count.");
+            throw UnknownException("Can't get the item count.");
+        } else {
+            LOGD("Item count: %d", count, ", isAllDay: %s", (isAllDay) ? "Yes" : "No");
+        }
+
+        calendar_list_first(list);
+        std::string time_zone = callback->getEvent()->getTimezone();
+        while(count--)
+        {
+            currentRecord = NULL;
+            ret = calendar_list_get_current_record_p(list, &currentRecord);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("Can't get current record.");
+                throw UnknownException("Can't get current record.");
+            }
+
+            if (isAllDay) {
+                ret = calendar_record_get_int(currentRecord,
+                        _calendar_instance_localtime_calendar_book.event_id, &currentRecordIndex);
+            } else {
+            ret = calendar_record_get_int(currentRecord,
+                    _calendar_instance_utime_calendar_book.event_id, &currentRecordIndex);
+            }
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("Can't get current record id.");
+                throw UnknownException("Can't get current record id.");
+            }
+
+            if (currentRecordIndex==callback->getEvent()->getId()->getUid()) {
+                calendar_record_h rec;
+                CalendarEventPtr loadedEventPtr = CalendarEventPtr(new CalendarEvent());
+
+                int uid = callback->getEvent()->getId()->getUid();
+
+                if (CALENDAR_ERROR_NONE != calendar_db_get_record(_calendar_event._uri,uid, &rec)) {
+                    LOGE("Event not found in database");
+                    throw UnknownException("Event not found in database");
+                }
+                loadedEventPtr->convertPlatFormEventToAbstractCalendarEvent(rec);
+                // Set distinctive attributes of each instance.
+                if (isAllDay) {
+                    ret = calendar_record_get_caltime(currentRecord,
+                            _calendar_instance_localtime_calendar_book.start_time, &st);
+
+                    long long int stLli = CalendarUtility::calTimeToLLI(time_zone.c_str(), st);
+
+                    CalendarEventId eventId;
+                    eventId.setUid(uid);
+                    eventId.setRid(std::to_string(stLli));
+
+                    loadedEventPtr->setId(std::make_shared<CalendarEventId> (eventId));
+                    loadedEventPtr->setStartDate(stLli, time_zone);
+                }
+                else {
+                    ret = calendar_record_get_caltime(currentRecord,
+                            _calendar_instance_utime_calendar_book.start_time, &st);
+
+                    std::string rid= std::to_string(st.time.utime);
+
+                    CalendarEventId eventId;
+                    eventId.setUid(uid);
+                    eventId.setRid(rid.c_str());
+
+                    loadedEventPtr->setId(std::make_shared<CalendarEventId> (eventId));
+                    loadedEventPtr->setStartDate(st.time.utime, time_zone);
+                }
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGE("Can't get current record start time");
+                    throw UnknownException("Can't get current record start time.");
+                }
+
+                if (isAllDay) {
+                    ret = calendar_record_get_caltime(currentRecord,
+                            _calendar_instance_localtime_calendar_book.end_time, &et);
+
+                    long long int etLli = CalendarUtility::calTimeToLLI(time_zone.c_str(), et);
+                    loadedEventPtr->setEndDate(etLli, time_zone);
+                }
+                else {
+                    ret = calendar_record_get_caltime(currentRecord,
+                            _calendar_instance_utime_calendar_book.end_time, &et);
+                    loadedEventPtr->setEndDate(et.time.utime, time_zone);
+                }
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGE("Can't get current record end time");
+                    throw UnknownException( "Can't get current record end time.");
+                }
+                std::string rid = loadedEventPtr->getId()->getRid();
+                LOGD("Found a valid event instance with rid: %s", rid.c_str());
+
+                expandResultsVector.push_back(loadedEventPtr);
+
+            } else {
+                LOGD("Skip unmatched instance with event_id: %d", currentRecordIndex,
+                        " and parent id: %d", callback->getEvent()->getId()->getUid());
+            }
+
+            calendar_list_next(list);
+        }
+
+        if (query) {
+            calendar_query_destroy(query);
+            query = NULL;
+        }
+        if (filter) {
+            calendar_filter_destroy(filter);
+            filter = NULL;
+        }
+        if (list) {
+            calendar_list_destroy(list, true);
+            list = NULL;
+        }
+
+        // Consider the detached events also.
+        currentRecord = NULL;
+        int parentId = callback->getEvent()->getId()->getUid();
+
+        ret = calendar_query_create(_calendar_event._uri, &query);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Creating a query failed");
+            throw UnknownException("Creating a query failed.");
+        }
+
+        ret = calendar_filter_create(_calendar_event._uri, &filter);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Creating a filter failed");
+            throw UnknownException("Creating a filter failed.");
+        }
+
+        ret = calendar_filter_add_int(filter, _calendar_event.original_event_id,
+                CALENDAR_MATCH_EQUAL, parentId);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Adding an int filter failed");
+            throw UnknownException("Adding an int filter failed.");
+        }
+
+        ret = calendar_query_set_filter(query, filter);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Setting a filter");
+            throw UnknownException("Setting a filter.");
+        }
+
+        ret = calendar_db_get_records_with_query(query, 0, 0, &list);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Finding detached instances failed");
+            throw UnknownException("Finding detached instances failed.");
+        }
+
+        ret = calendar_list_get_count(list, &count);
+        if (CALENDAR_ERROR_NONE!=ret) {
+            LOGE("Can't get the item count");
+            throw UnknownException("Can't get the item count.");
+        } else {
+            LOGD("Item count: %d", count);
+        }
+
+        calendar_list_first(list);
+
+        while(count--)
+        {
+            currentRecord = NULL;
+            ret = calendar_list_get_current_record_p(list, &currentRecord);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("Can't get current record");
+                throw UnknownException("Can't get current record.");
+            }
+
+            ret = calendar_record_get_int(currentRecord, _calendar_event.id, &currentRecordIndex);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("Can't get current record id");
+                throw UnknownException("Can't get current record id.");
+            }
+
+            st = {CALENDAR_TIME_UTIME, {0}};
+            ret = calendar_record_get_caltime(currentRecord, _calendar_event.start_time, &st);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("Can't get current record start time");
+                throw UnknownException("Can't get current record start time.");
+            }
+
+            et = {CALENDAR_TIME_UTIME, {0}};
+            ret = calendar_record_get_caltime(currentRecord, _calendar_event.end_time, &et);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("Can't get current record end time");
+                throw UnknownException("Can't get current record end time.");
+            }
+
+            if (st.time.utime>=startDate && et.time.utime<=endDate) {
+                LOGD("Found a valid detached event: %d", st.time.utime);
+                calendar_record_h rec;
+                CalendarEventPtr loadedDetachedEventPtr;
+
+                int uid = callback->getEvent()->getId()->getUid();
+
+                if (CALENDAR_ERROR_NONE != calendar_db_get_record(_calendar_event._uri,uid, &rec)) {
+                    LOGE("calendar_db_get_record  error");
+                    throw UnknownException("Event not found in database.");
+                }
+                loadedDetachedEventPtr->convertPlatFormEventToAbstractCalendarEvent(rec);
+                // Set the same parent uid to each instances
+                CalendarEventId eventId;
+                eventId.setUid(parentId);
+                // Set distintive attributes of each instance.
+                eventId.setRid((std::to_string(st.time.utime)).c_str());
+
+                loadedDetachedEventPtr->setStartDate(st.time.utime, time_zone);
+                loadedDetachedEventPtr->setEndDate(et.time.utime, time_zone);
+
+                expandResultsVector.push_back(loadedDetachedEventPtr);
+            }
+
+            calendar_list_next(list);
+        }
+        const int size = expandResultsVector.size();
+        LOGD("Length of total expanded events: %d", size);
+
+        JSObjectRef js_result;
+        JSContextRef context = callback->getContext();
+        JSValueRef exception = NULL;
+        std::vector<JSObjectRef> js_expanded_event_vector;
+        js_expanded_event_vector.reserve(size);
+
+        for (int i = 0; i < size; i++) {
+            js_expanded_event_vector.push_back(JSCalendarEvent::makeJSObject(context,
+                                expandResultsVector[i]));
+        }
+
+        js_result = JSObjectMakeArray(context, size,
+                size > 0 ? &js_expanded_event_vector[0] : NULL, &exception);
+        if (NULL != exception) {
+            LOGE("Could not create a result array.");
+            throw UnknownException(context, exception);
+        }
+        callback->setJSArrayEvents(js_result);
+
+        if (query) {
+            calendar_query_destroy(query);
+            query = NULL;
+        }
+        if (filter) {
+            calendar_filter_destroy(filter);
+            filter = NULL;
+        }
+        if (list) {
+            calendar_list_destroy(list, true);
+            list = NULL;
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Error %s, with msg: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch (...) {
+        LOGE("UnknownError");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "UnknownError.");
+    }
+
+    if (query) {
+        calendar_query_destroy(query);
+    }
+    if (filter) {
+        calendar_filter_destroy(filter);
+    }
+    if (list) {
+        calendar_list_destroy(list, true);
+    }
+
+    if (0 == g_idle_add(expandRecurrenceCompleted, data)) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+    return NULL;
+}
+
+void CalendarEvent::expandRecurrence(CalendarEventCallbackUserData *callback)
+{
+    LOGD("Entered");
+    if (NULL == callback) {
+        throw UnknownException("NULL cbdata error.");
+    }
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, expandRecurrenceThread,
+            static_cast<void*>(callback))) {
+        LOGE("Failed to create pthread for expandRecurrence()");
+        throw UnknownException("pthread_create error.");
+    }
+    if (pthread_detach(thread)) {
+        LOGW("Failed to detach the pthread for expandRecurrence()");
+    }
+}
+
+} //Calendar
+} //DeviceAPI
diff --git a/src/Calendar/CalendarEvent.h b/src/Calendar/CalendarEvent.h
new file mode 100644 (file)
index 0000000..33e4d9f
--- /dev/null
@@ -0,0 +1,183 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        CalendarEvent.h
+*/
+
+#ifndef _TIZEN_CALENDAR_EVENT_H_
+#define _TIZEN_CALENDAR_EVENT_H_
+
+#include <CallbackUserData.h>
+#include "CalendarItem.h"
+#include "CalendarEventId.h"
+#include "CalendarRecurrenceRule.h"
+#include <glib.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+
+class CalendarEvent;
+typedef std::shared_ptr<CalendarEvent> CalendarEventPtr;
+typedef std::vector<CalendarEventPtr> CalendarEventPtrVector;
+
+extern const std::string AVAILABILITY_BUSY;
+extern const std::string AVAILABILITY_FREE;
+extern const std::string EMPTY_STRING;
+
+enum CalendarEventAvailability{
+    CALENDAR_EVENT_AVAILABILITY_BUSY,
+    CALENDAR_EVENT_AVAILABILITY_FREE,
+    CALENDAR_EVENT_AVAILABILITY_UNDEFINED
+};
+
+enum CalendarEventAttribute{
+    CALENDAR_EVENT_ATTRIBUTE_ID = CalendarItemAttribute::CALENDAR_ITEM_NUMBER_OF_ATTRIBUTES,
+    CALENDAR_EVENT_ATTRIBUTE_IS_DETACHED,
+    CALENDAR_EVENT_ATTRIBUTE_AVAILABILITY,
+    CALENDAR_EVENT_ATTRIBUTE_RECURRENCE_RULE,
+    CALENDAR_EVENT_NUMBER_OF_ATTRIBUTES
+};
+
+class CalendarEventCallbackUserData : public Common::CallbackUserData
+{
+public:
+    CalendarEventCallbackUserData(JSContextRef globalCtx);
+    virtual ~CalendarEventCallbackUserData();
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    const std::string& getErrorName() const;
+    const std::string& getErrorMessage() const;
+
+    long long int getStartDate() const;
+    void setStartDate(long long int start_date, const std::string& time_zone);
+
+    long long int getEndDate() const;
+    void setEndDate(long long int end_date, const std::string& time_zone);
+
+    JSObjectRef getJSArrayEvents() const;
+    void setJSArrayEvents(JSObjectRef js_array_events);
+
+    CalendarEventPtr getEvent() const;
+    void setEvent(CalendarEventPtr event);
+
+private:
+    bool m_is_error;
+
+    std::string m_err_name;
+    std::string m_err_message;
+
+    std::string m_time_zone;
+    long long int m_start_date;
+    long long int m_end_date;
+
+    CalendarEventPtr m_event;
+
+    JSObjectRef m_js_array_events;
+};
+
+class CalendarEvent : public CalendarItem{
+public:
+
+    CalendarEvent();
+    CalendarEvent(const CalendarEvent& calendar_event);
+    virtual ~CalendarEvent();
+
+    CalendarEventIdPtr getId() const;
+    void setId(CalendarEventIdPtr id);
+
+    bool getIsDetached() const;
+    void setIsDetached(bool isDetached);
+
+    CalendarEventAvailability getAvailability() const;
+    void setAvailability(CalendarEventAvailability availability);
+
+    CalendarRecurrenceRulePtr getRecurrenceRule() const;
+    void setRecurrenceRule(CalendarRecurrenceRulePtr recurrence_rule);
+    void unsetRecurrenceRule();
+
+    bool isSet(CalendarEventAttribute attribute) const;
+    void setIsSet(CalendarEventAttribute attribute, bool is_set);
+
+    static CalendarEventAvailability stringToCalendarEventAvailability(
+        const std::string& string_event_attribute);
+    static std::string calendarEventAvailabilityToString(
+        CalendarEventAvailability event_attribute);
+
+    void convertPlatFormEventToAbstractCalendarEvent(
+            calendar_record_h platform_event_tmp = NULL);
+    calendar_record_h convertAbstractCalendarEventToPlatformCalendarEvent(
+        bool loadBeforeConvert = false);
+
+    void expandRecurrence(CalendarEventCallbackUserData *callback);
+
+private:
+    void setCalendarIdFromPlatformCalendarItem();
+    void setLastModifiedDateFromPlatformCalendarItem();
+    void setDescriptionFromPlatformCalendarItem();
+    void setSummaryFromPlatformCalendarItem();
+    void setIsAllDayAndStartDateFromPlatformCalendarItem();
+    void setLocationFromPlatformCalendarItem();
+    void setGeolocationFromPlatformCalendarItem();
+    void setOrganizerFromPlatformCalendarItem();
+    void setVisibilityFromPlatformCalendarItem();
+    void setStatusFromPlatformCalendarItem();
+    void setPriorityFromPlatformCalendarItem();
+    void setIdFromPlatformCalendarEvent();
+    void setIsDetachedFromPlatformCalendarEvent();
+    void setAvailabilityFromPlatformCalendarEvent();
+    void setRecurrenceRuleFromPlatformCalendarEvent();
+    void setRecurrenceIdFromPlatformCalendarEvent();
+    void setAlarmsFromPlatformCalendarItem();
+    void setCategoriesFromPlatformCalendarItem();
+    void setAttendeesFromPlatformCalendarItem();
+    void setEndDateFromPlatformCalendarItem();
+
+    void setAvailabilityToPlatformCalendarEvent();
+    void setCalendarIdToPlatformCalendarItem();
+    void setDescriptionToPlatformCalendarItem();
+    void setSummaryToPlatformCalendarItem();
+    void setIsAllDayAndStartDateToPlatformCalendarItem();
+    void setLocationToPlatformCalendarItem();
+    void setGeolocationToPlatformCalendarItem();
+    void setOrganizerToPlatformCalendarItem();
+    void setVisibilityToPlatformCalendarItem();
+    void setStatusToPlatformCalendarItem();
+    void setPriorityToPlatformCalendarItem();
+    void setAlarmsToPlatformCalendarItem();
+    void setCategoriesToPlatformCalendarItem();
+    void setAttendeesToPlatformCalendarItem();
+    void setEndDateToPlatformCalendarItem();
+    void setRecurrenceRuleToPlatformCalendarEvent();
+    void setRecurrenceIdToPlatformCalendarEvent();
+
+    static gboolean expandRecurrenceCompleted(void *data);
+    static void* expandRecurrenceThread(void *data);
+
+    CalendarEventIdPtr m_id;
+    bool m_is_detached;
+    CalendarEventAvailability m_availability;
+    CalendarRecurrenceRulePtr m_recurrence_rule;
+};
+
+}//Calendar
+}//DeviceAPI
+
+#endif
diff --git a/src/Calendar/CalendarEventId.cpp b/src/Calendar/CalendarEventId.cpp
new file mode 100644 (file)
index 0000000..7fde627
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CalendarEventId.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+CalendarEventId::CalendarEventId()
+{
+    m_uid = 0;
+    m_rid = "";
+    m_is_set[CALENDAR_EVENT_ID_ATTRIBUTE_UID] = false;
+    m_is_set[CALENDAR_EVENT_ID_ATTRIBUTE_RID] = false;
+}
+
+CalendarEventId::~CalendarEventId()
+{
+}
+
+int CalendarEventId::getUid() const
+{
+    return m_uid;
+}
+
+void CalendarEventId::setUid(int uid)
+{
+    m_is_set[CALENDAR_EVENT_ID_ATTRIBUTE_UID] = true;
+    m_uid = uid;
+}
+
+const std::string& CalendarEventId::getRid() const
+{
+    return m_rid;
+}
+
+void CalendarEventId::setRid(const std::string& rid)
+{
+    m_is_set[CALENDAR_EVENT_ID_ATTRIBUTE_RID] = true;
+    m_rid = rid;
+}
+
+bool CalendarEventId::isSet(CalendarEventIdAttribute attribute) const
+{
+    return m_is_set[attribute];
+}
+
+void CalendarEventId::setIsSet(CalendarEventIdAttribute attribute, bool is_set)
+{
+    m_is_set[attribute] = is_set;
+}
+
+} //Calendar
+} //DeviceAPI
diff --git a/src/Calendar/CalendarEventId.h b/src/Calendar/CalendarEventId.h
new file mode 100644 (file)
index 0000000..cbe9db1
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CALENDAR_EVENTID_H_
+#define _TIZEN_CALENDAR_EVENTID_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class CalendarEventId;
+typedef std::shared_ptr<CalendarEventId> CalendarEventIdPtr;
+typedef std::vector<CalendarEventIdPtr> CalendarEventIdPtrVector;
+
+enum CalendarEventIdAttribute{
+    CALENDAR_EVENT_ID_ATTRIBUTE_UID,
+    CALENDAR_EVENT_ID_ATTRIBUTE_RID,
+    CALENDAR_EVENT_ID_NUMBER_OF_ATTRIBUTES
+};
+
+class CalendarEventId{
+public:
+    CalendarEventId();
+    ~CalendarEventId();
+
+    int getUid() const;
+    void setUid(int uid);
+
+    const std::string& getRid() const;
+    void setRid(const std::string& rid);
+
+    bool isSet(CalendarEventIdAttribute attribute) const;
+    void setIsSet(CalendarEventIdAttribute attribute, bool is_set);
+
+private:
+    int m_uid;
+    std::string m_rid;
+
+    bool m_is_set[CALENDAR_EVENT_ID_NUMBER_OF_ATTRIBUTES];
+};
+} //Calendar
+} //DeviceAPI
+
+#endif
diff --git a/src/Calendar/CalendarFindCallbackData.cpp b/src/Calendar/CalendarFindCallbackData.cpp
new file mode 100644 (file)
index 0000000..c516aaa
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "CalendarFindCallbackData.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+using namespace Tizen;
+
+CalendarFindCallbackData::CalendarFindCallbackData(JSContextRef globalCtx):
+        Common::CallbackUserData(globalCtx),
+        m_is_error(false),
+        m_calendar_id(0),
+        m_type(CalendarUtility::CalendarType::UNDEFINED),
+        m_filter_is_set(false),
+        m_sort_mode_is_set(false)
+{
+
+}
+
+CalendarFindCallbackData::~CalendarFindCallbackData()
+{
+
+}
+
+void CalendarFindCallbackData::setError(const std::string &err_name, const std::string &err_message)
+{
+    m_err_name = err_name;
+    m_err_message = err_message;
+    m_is_error = true;
+}
+
+bool CalendarFindCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+const std::string& CalendarFindCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+const std::string& CalendarFindCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void CalendarFindCallbackData::setCalendarId(int calendar_id)
+{
+    m_calendar_id = calendar_id;
+}
+
+int CalendarFindCallbackData::getCalendarId() const
+{
+    return m_calendar_id;
+}
+
+void CalendarFindCallbackData::setType(CalendarUtility::CalendarType type)
+{
+    m_type = type;
+}
+
+CalendarUtility::CalendarType CalendarFindCallbackData::getType() const
+{
+    return m_type;
+}
+
+bool CalendarFindCallbackData::getFilterIsSet() const
+{
+    return m_filter_is_set;
+}
+
+void CalendarFindCallbackData::setFilter(Tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+    m_filter_is_set = true;
+}
+
+AbstractFilterPtr CalendarFindCallbackData::getFilter() const
+{
+    return m_filter;
+}
+
+bool CalendarFindCallbackData::getSortModeIsSet() const
+{
+    return m_sort_mode_is_set;
+}
+
+void CalendarFindCallbackData::setSortMode(Tizen::SortModePtr sort_mode)
+{
+    m_sort_mode = sort_mode;
+    m_sort_mode_is_set = true;
+}
+
+Tizen::SortModePtr CalendarFindCallbackData::getSortMode() const
+{
+    return m_sort_mode;
+}
+
+void CalendarFindCallbackData::setItems(const std::shared_ptr<CalendarItemPtrVector>& items)
+{
+    m_items = items;
+}
+
+const std::shared_ptr<CalendarItemPtrVector>& CalendarFindCallbackData::getItems() const
+{
+    return m_items;
+}
+
+
+}
+}
diff --git a/src/Calendar/CalendarFindCallbackData.h b/src/Calendar/CalendarFindCallbackData.h
new file mode 100644 (file)
index 0000000..ee22de4
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __CALENDAR_FIND_CALLBACK_DATA_H__
+#define __CALENDAR_FIND_CALLBACK_DATA_H__
+
+#include <CallbackUserData.h>
+#include <AttributeFilter.h>
+#include <SortMode.h>
+
+#include "CalendarItem.h"
+#include "CalendarUtility.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+using namespace Tizen;
+
+class CalendarFindCallbackData : public Common::CallbackUserData
+{
+public:
+    CalendarFindCallbackData(JSContextRef globalCtx);
+    virtual ~CalendarFindCallbackData();
+
+    void setError(const std::string &err_name, const std::string &err_message);
+    bool isError() const;
+    const std::string& getErrorName() const;
+    const std::string& getErrorMessage() const;
+
+    void setCalendarId(int calendar_id);
+    int getCalendarId() const;
+
+    void setType(CalendarUtility::CalendarType type);
+    CalendarUtility::CalendarType getType() const;
+
+    bool getFilterIsSet() const;
+    void setFilter(Tizen::AbstractFilterPtr filter);
+    AbstractFilterPtr getFilter() const;
+
+    bool getSortModeIsSet() const;
+    void setSortMode(Tizen::SortModePtr sort_mode);
+    Tizen::SortModePtr getSortMode() const;
+
+    void setItems(const std::shared_ptr<CalendarItemPtrVector>& items);
+    const std::shared_ptr<CalendarItemPtrVector>& getItems() const;
+
+private:
+
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+
+    int m_calendar_id;
+    CalendarUtility::CalendarType m_type;
+
+    bool m_filter_is_set;
+    AbstractFilterPtr m_filter;
+
+    bool m_sort_mode_is_set;
+    Tizen::SortModePtr m_sort_mode;
+    std::shared_ptr<CalendarItemPtrVector> m_items;
+};
+
+} //Calendar
+} //DeviceAPI
+
+#endif
diff --git a/src/Calendar/CalendarItem.cpp b/src/Calendar/CalendarItem.cpp
new file mode 100755 (executable)
index 0000000..711e132
--- /dev/null
@@ -0,0 +1,752 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        CalendarItem.cpp
+*/
+
+#include "CalendarItem.h"
+#include "CalendarUtility.h"
+#include <PlatformException.h>
+#include <Logger.h>
+#include <algorithm>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+const char* CALENDAR_ITEM = "CalendarItem";
+
+const char* CALENDAR_ITEM_CALENDAR_ID = "calendarId";
+const char* CALENDAR_ITEM_LAST_MODIFICATION_DATE = "lastModificationDate";
+const char* CALENDAR_ITEM_DESCRIPTION = "description";
+const char* CALENDAR_ITEM_SUMMARY = "summary";
+const char* CALENDAR_ITEM_IS_ALL_DAY = "isAllDay";
+const char* CALENDAR_ITEM_START_DATE = "startDate";
+const char* CALENDAR_ITEM_DURATION = "duration";
+const char* CALENDAR_ITEM_LOCATION = "location";
+const char* CALENDAR_ITEM_GEOLOCATION = "geolocation";
+const char* CALENDAR_ITEM_ORGANIZER = "organizer";
+const char* CALENDAR_ITEM_VISIBILITY = "visibility";
+const char* CALENDAR_ITEM_STATUS = "status";
+const char* CALENDAR_ITEM_PRIORITY  = "priority";
+const char* CALENDAR_ITEM_ALARMS = "alarms";
+const char* CALENDAR_ITEM_CATEGORIES = "categories";
+const char* CALENDAR_ITEM_ATTENDEES = "attendees";
+
+const std::string TYPE_PUBLIC_VISIBILITY = "PUBLIC";
+const std::string TYPE_PRIVATE_VISIBILITY = "PRIVATE";
+const std::string TYPE_CONFIDENTIAL_VISIBILITY = "CONFIDENTIAL";
+
+const std::string TYPE_TENTATIVE_STATUS = "TENTATIVE";
+const std::string TYPE_CONFIRMED_STATUS = "CONFIRMED";
+const std::string TYPE_CANCELLED_STATUS = "CANCELLED";
+const std::string TYPE_NEEDS_ACTION_STATUS = "NEEDS_ACTION";
+const std::string TYPE_IN_PROCESS_STATUS = "IN_PROCESS";
+const std::string TYPE_COMPLETED_STATUS = "COMPLETED";
+
+const std::string TYPE_HIGH_PRIORITY = "HIGH";
+const std::string TYPE_MEDIUM_PRIORITY = "MEDIUM";
+const std::string TYPE_LOW_PRIORITY = "LOW";
+
+const std::string TYPE_ICALENDAR_20 = "ICALENDAR_20";
+const std::string TYPE_VCALENDAR_10 = "VCALENDAR_10";
+
+const char* CALENDAR_MANAGER_ATTRIBUTENAME = "CalendarManager";
+
+CalendarItem::CalendarItem():
+    SecurityAccessor(),
+    m_calendar_id(UNDEFINED_CALENDAR_ID),
+    m_time_zone(""),
+    m_last_modification_date(UNDEFINED_TIME),
+    m_start_date(UNDEFINED_TIME),
+    m_duration(new TimeDuration()),
+    m_geolocation(new Tizen::SimpleCoordinates(UNDEFINED_GEO, UNDEFINED_GEO)),
+    m_end_date(UNDEFINED_TIME),
+    m_format(""),
+    m_is_set(CALENDAR_ITEM_NUMBER_OF_ATTRIBUTES)
+{
+    LOGD("Entered");
+    for (int i = CALENDAR_ITEM_ATTRIBUTE_LAST_MODIFICATION_DATE; i < CALENDAR_ITEM_NUMBER_OF_ATTRIBUTES; ++i) {
+        m_is_set[i] = false;
+    }
+    setPriority(CALENDAR_ITEM_PRIORITY_LOW);
+    setVisibility(CALENDAR_ITEM_VISIBILITY_PUBLIC);
+    setOrganizer("");
+    setLocation("");
+    setIsAllDay(false);
+    setSummary("");
+    setDescription("");
+    setStatus(TASK_STATUS_NEEDS_ACTION);
+    //By default, these attributes are set to an empty array.
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_ALARMS] = true;
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_CATEGORIES] = true;
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_ATTENDEES] = true;
+}
+
+CalendarItem::CalendarItem(const CalendarItem& calendar_item):
+    SecurityAccessor(calendar_item),
+    m_calendar_id(calendar_item.m_calendar_id),
+    m_time_zone(calendar_item.m_time_zone),
+    m_last_modification_date(calendar_item.m_last_modification_date),
+    m_description(calendar_item.m_description),
+    m_summary(calendar_item.m_summary),
+    m_is_all_day(calendar_item.m_is_all_day),
+    m_start_date(calendar_item.m_start_date),
+    m_location(calendar_item.m_location),
+    m_geolocation(new Tizen::SimpleCoordinates(
+        calendar_item.getGeolocation()->getLatitude(),
+        calendar_item.getGeolocation()->getLongitude())),
+    m_organizer(calendar_item.m_organizer),
+    m_visibility(calendar_item.m_visibility),
+    m_status(calendar_item.m_status),
+    m_priority(calendar_item.m_priority),
+    m_alarms(CalendarUtility::cloneVector<CalendarAlarmPtr,CalendarAlarm>(
+        calendar_item.getAlarms())),
+    m_categories(calendar_item.m_categories),
+    m_attendees(CalendarUtility::cloneVector<CalendarAttendeePtr,CalendarAttendee>(
+        calendar_item.getAttendees())),
+    m_format(calendar_item.m_format),
+    m_type(calendar_item.m_type),
+    m_platform_item(NULL)
+{
+    LOGD("Entered");
+    if (calendar_item.m_is_set[CALENDAR_ITEM_ATTRIBUTE_DURATION]) {
+        m_duration = TimeDurationPtr(new TimeDuration(*calendar_item.getDuration()));
+        m_end_date = UNDEFINED_TIME;
+    }
+    if (calendar_item.m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE]) {
+        m_end_date = calendar_item.m_end_date;
+        m_duration = TimeDurationPtr(new TimeDuration());
+    }
+    int ret = calendar_record_clone(calendar_item.m_platform_item, &m_platform_item);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Cannot clone the records : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+}
+
+CalendarItem::~CalendarItem()
+{
+    LOGD("Entered");
+    freePlatformCalendarItem();
+}
+
+int CalendarItem::getCalendarId() const
+{
+    LOGD("Entered");
+    return m_calendar_id;
+}
+
+void CalendarItem::setCalendarId(int calendar_id)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_CALENDAR_ID] = true;
+    m_calendar_id = calendar_id;
+}
+
+long long int CalendarItem::getLastModificationDate() const
+{
+    LOGD("Entered");
+    return m_last_modification_date;
+}
+
+void CalendarItem::setLastModificationDate(long long int last_modification_date)
+{
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_LAST_MODIFICATION_DATE] = true;
+    m_last_modification_date = last_modification_date;
+}
+
+const std::string& CalendarItem::getDescription() const
+{
+    LOGD("Entered");
+    return m_description;
+}
+
+void CalendarItem::setDescription(const std::string& description)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_DESCRIPTION] = true;
+    m_description = description;
+}
+
+const std::string& CalendarItem::getSummary() const
+{
+    LOGD("Entered");
+    return m_summary;
+}
+
+void CalendarItem::setSummary(const std::string& summary)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_SUMMARY] = true;
+    m_summary = summary;
+}
+
+bool CalendarItem::getIsAllDay() const
+{
+    LOGD("Entered");
+    return m_is_all_day;
+}
+
+void CalendarItem::setIsAllDay(bool is_all_day)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_IS_ALL_DAY] = true;
+    m_is_all_day = is_all_day;
+}
+
+const std::string& CalendarItem::getTimezone()
+{
+    return m_time_zone;
+}
+
+long long int CalendarItem::getStartDate() const
+{
+    LOGD("Entered");
+    return m_start_date;
+}
+
+void CalendarItem::setStartDate(long long int start_date, const std::string& time_zone)
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE]) {
+        if (m_time_zone != time_zone) {
+            LOGE("Start date should have the same timezone as due date/end date");
+            throw InvalidValuesException(
+                    "Start date should have the same timezone as due date/end date");
+        }
+    }
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE] = true;
+    m_start_date = start_date;
+    m_time_zone = time_zone;
+}
+
+TimeDurationPtr CalendarItem::getDuration() const
+{
+    LOGD("Entered");
+    return m_duration;
+}
+
+void CalendarItem::setDuration(TimeDurationPtr duration)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_DURATION] = true;
+    m_duration = duration;
+
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE] = false;
+    m_end_date = UNDEFINED_TIME;
+}
+
+const std::string& CalendarItem::getLocation() const
+{
+    LOGD("Entered");
+    return m_location;
+}
+
+void CalendarItem::setLocation(const std::string& location)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_LOCATION] = true;
+    m_location = location;
+}
+
+
+Tizen::SimpleCoordinatesPtr CalendarItem::getGeolocation() const
+{
+    LOGD("Entered");
+    return m_geolocation;
+}
+
+void CalendarItem::setGeolocation(Tizen::SimpleCoordinatesPtr geolocation)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_GEOLOCATION] = true;
+    m_geolocation = geolocation;
+}
+
+const std::string& CalendarItem::getOrganizer() const
+{
+    LOGD("Entered");
+    return m_organizer;
+}
+
+void CalendarItem::setOrganizer(const std::string& organizer)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_ORGANIZER] = true;
+    m_organizer = organizer;
+}
+
+CalendarItemVisibility CalendarItem::getVisibility() const
+{
+    LOGD("Entered");
+    return m_visibility;
+}
+
+void CalendarItem::setVisibility(CalendarItemVisibility visibility)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_VISIBILITY] = true;
+    m_visibility = visibility;
+}
+
+ItemStatus CalendarItem::getStatus() const
+{
+    LOGD("Entered");
+    return m_status;
+}
+
+void CalendarItem::setStatus(ItemStatus status)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_STATUS] = true;
+    m_status = status;
+}
+
+CalendarItemPriority CalendarItem::getPriority() const
+{
+    LOGD("Entered");
+    return m_priority;
+}
+
+void CalendarItem::setPriority(CalendarItemPriority priority)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_PRIORITY] = true;
+    m_priority = priority;
+}
+
+std::vector<CalendarAlarmPtr> CalendarItem::getAlarms() const
+{
+    LOGD("Entered");
+    return m_alarms;
+}
+
+JSObjectRef CalendarItem::getJSAlarms(JSContextRef global_ctx)
+{
+    LOGD("Entered");
+    return m_alarms.getJSArray(global_ctx);
+}
+
+void CalendarItem::setAlarms(const std::vector<CalendarAlarmPtr>& alarms)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_ALARMS] = true;
+    m_alarms = alarms;
+}
+
+std::vector<std::string> CalendarItem::getCategories() const
+{
+    LOGD("Entered");
+    return m_categories;
+}
+
+void CalendarItem::setCategories(const std::vector<std::string>& categories)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_CATEGORIES] = true;
+
+    m_categories = categories;
+}
+
+JSObjectRef CalendarItem::getJSCategories(JSContextRef global_ctx)
+{
+    return m_categories.getJSArray(global_ctx);
+}
+
+std::vector<CalendarAttendeePtr> CalendarItem::getAttendees() const
+{
+    LOGD("Entered");
+    return m_attendees;
+}
+
+JSObjectRef CalendarItem::getJSAttendees(JSContextRef global_ctx)
+{
+    LOGD("Entered");
+    return m_attendees.getJSArray(global_ctx);
+}
+
+void CalendarItem::setAttendees(const std::vector<CalendarAttendeePtr>& attendees)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_ATTENDEES] = true;
+    m_attendees = attendees;
+}
+
+long long int CalendarItem::getEndDate() const
+{
+    LOGD("Entered");
+    return m_end_date;
+}
+
+void CalendarItem::setEndDate(long long int end_date, const std::string& time_zone)
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        if (time_zone != m_time_zone) {
+            LOGE("Due date/end date should have the same timezone as start date");
+            throw InvalidValuesException(
+                    "Due date/end date should have the same timezone as start date");
+        }
+    }
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE] = true;
+    m_end_date = end_date;
+    m_time_zone = time_zone;
+
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_DURATION] = false;
+    m_duration.reset();
+}
+
+
+
+const std::string& CalendarItem::calendarItemVisibilityToString(CalendarItemVisibility visibility) {
+    LOGD("Entered");
+    if (CALENDAR_ITEM_VISIBILITY_PUBLIC == visibility) {
+        return TYPE_PUBLIC_VISIBILITY;
+    }
+    if (CALENDAR_ITEM_VISIBILITY_PRIVATE == visibility) {
+        return TYPE_PRIVATE_VISIBILITY;
+    }
+    if (CALENDAR_ITEM_VISIBILITY_CONFIDENTIAL == visibility) {
+        return TYPE_CONFIDENTIAL_VISIBILITY;
+    }
+    LOGE("Invalid CalendarItemVisibility");
+    throw TypeMismatchException("Invalid MessageType");
+}
+
+CalendarItemVisibility CalendarItem::stringToCalendarItemVisibility(const std::string& string_visibility) {
+    LOGD("Entered");
+    if (TYPE_PUBLIC_VISIBILITY == string_visibility) {
+        return CALENDAR_ITEM_VISIBILITY_PUBLIC;
+    }
+    if (TYPE_PRIVATE_VISIBILITY == string_visibility) {
+        return CALENDAR_ITEM_VISIBILITY_PRIVATE;
+    }
+    if (TYPE_CONFIDENTIAL_VISIBILITY == string_visibility) {
+        return CALENDAR_ITEM_VISIBILITY_CONFIDENTIAL;
+    }
+    LOGE("Invalid CalendarItemVisibility");
+    throw TypeMismatchException("Invalid MessageType");
+}
+
+const std::string& CalendarItem::calendarItemStatusToString(ItemStatus status,
+        CalendarItemType type) {
+
+    LOGD("Entered");
+    if (CALENDAR_EVENT == type) {
+        if (EVENT_STATUS_TENTATIVE == status) {
+            return TYPE_TENTATIVE_STATUS;
+        }
+        if (EVENT_STATUS_CONFIRMED == status) {
+            return TYPE_CONFIRMED_STATUS;
+        }
+        if (EVENT_STATUS_CANCELLED == status) {
+            return TYPE_CANCELLED_STATUS;
+        }
+        LOGE("Invalid CalendarItemStatus");
+        throw TypeMismatchException("Invalid Event Status Type");
+    }
+    else if (CALENDAR_TASK == type) {
+        if (TASK_STATUS_NEEDS_ACTION == status) {
+            return TYPE_NEEDS_ACTION_STATUS;
+        }
+        if (TASK_STATUS_IN_PROCESS == status) {
+            return TYPE_IN_PROCESS_STATUS;
+        }
+        if (TASK_STATUS_COMPLETED == status) {
+            return TYPE_COMPLETED_STATUS;
+        }
+        if (TASK_STATUS_CANCELLED == status) {
+                return TYPE_CANCELLED_STATUS;
+        }
+        LOGE("Invalid CalendarItemStatus");
+        throw TypeMismatchException("Invalid Task Status Type");
+    }
+    else{
+        LOGE("Invalid Item Type");
+        throw TypeMismatchException("Invalid Item Type");
+    }
+}
+
+ItemStatus CalendarItem::stringToCalendarItemStatus(const std::string& string_status,
+        CalendarItemType type) {
+
+    LOGD("Entered");
+    if (CALENDAR_EVENT == type) {
+        if (TYPE_TENTATIVE_STATUS == string_status) {
+            return EVENT_STATUS_TENTATIVE;
+        }
+        if (TYPE_CONFIRMED_STATUS == string_status) {
+            return EVENT_STATUS_CONFIRMED;
+        }
+        if (TYPE_CANCELLED_STATUS == string_status) {
+            return EVENT_STATUS_CANCELLED;
+        }
+        LOGE("Invalid CalendarItemStatus");
+        throw TypeMismatchException("Invalid MessageType");
+    }
+    else if (CALENDAR_TASK == type) {
+        if (TYPE_NEEDS_ACTION_STATUS == string_status) {
+            return TASK_STATUS_NEEDS_ACTION;
+        }
+        if (TYPE_IN_PROCESS_STATUS == string_status) {
+            return TASK_STATUS_IN_PROCESS;
+        }
+        if (TYPE_COMPLETED_STATUS == string_status) {
+            return TASK_STATUS_COMPLETED;
+        }
+        if (TYPE_CANCELLED_STATUS == string_status) {
+            return TASK_STATUS_CANCELLED;
+        }
+        LOGE("Invalid CalendarItemStatus");
+        throw TypeMismatchException("Invalid MessageType");
+    }
+    else{
+        LOGE("Invalid Item Type");
+        throw TypeMismatchException("Invalid Item Type");
+    }
+}
+
+const std::string& CalendarItem::calendarItemPriorityToString(CalendarItemPriority priority) {
+    LOGD("Entered");
+    if (CALENDAR_ITEM_PRIORITY_LOW == priority) {
+        return TYPE_LOW_PRIORITY;
+    }
+    if (CALENDAR_ITEM_PRIORITY_MEDIUM == priority) {
+        return TYPE_MEDIUM_PRIORITY;
+    }
+    if (CALENDAR_ITEM_PRIORITY_HIGH == priority) {
+        return TYPE_HIGH_PRIORITY;
+    }
+    LOGE("Invalid CalendarItemPriority");
+    throw TypeMismatchException("Invalid MessageType");
+}
+
+CalendarItemPriority CalendarItem::stringToCalendarItemPriority(const std::string& string_priority) {
+    if (TYPE_LOW_PRIORITY == string_priority) {
+        return CALENDAR_ITEM_PRIORITY_LOW;
+    }
+    if (TYPE_MEDIUM_PRIORITY == string_priority) {
+        return CALENDAR_ITEM_PRIORITY_MEDIUM;
+    }
+    if (TYPE_HIGH_PRIORITY == string_priority) {
+        return CALENDAR_ITEM_PRIORITY_HIGH;
+    }
+    LOGE("Invalid CalendarItemPriority");
+    throw TypeMismatchException("Invalid MessageType");
+}
+
+const std::string& CalendarItem::calendarTextFormatToString(CalendarTextFormat format) {
+    if (CALENDAR_TEXT_FORMAT_ICALENDAR_20 == format) {
+        return TYPE_ICALENDAR_20;
+    }
+    if (CALENDAR_TEXT_FORMAT_VCALENDAR_10 == format) {
+        return TYPE_VCALENDAR_10;
+    }
+    LOGE("Invalid CalendarTextFormat");
+    throw TypeMismatchException("Invalid MessageType");
+}
+
+CalendarTextFormat CalendarItem::stringToCalendarTextFormat(const std::string& string_format) {
+    LOGD("Entered");
+    if (TYPE_ICALENDAR_20 == string_format) {
+        return CALENDAR_TEXT_FORMAT_ICALENDAR_20;
+    }
+    if (TYPE_VCALENDAR_10 == string_format) {
+        return CALENDAR_TEXT_FORMAT_VCALENDAR_10;
+    }
+    LOGE("Invalid CalendarTextFormat");
+    throw TypeMismatchException("Invalid MessageType");
+}
+
+bool CalendarItem::isSet(CalendarItemAttribute attribute) const
+{
+    LOGD("Entered");
+    return m_is_set[attribute];
+}
+
+void CalendarItem::setIsSet(CalendarItemAttribute attribute, bool is_set)
+{
+    LOGD("Entered");
+    m_is_set[attribute] = is_set;
+}
+
+const std::vector<bool>& CalendarItem::getIsSet() const
+{
+    LOGD("Entered");
+    return m_is_set;
+}
+
+const std::string& CalendarItem::getFormat() const
+{
+    return m_format;
+}
+void CalendarItem::setFormat(const std::string& format)
+{
+    m_format = format;
+}
+
+CalendarItemType CalendarItem::getType() const
+{
+   return m_type;
+}
+
+/**********************************************************/
+void CalendarItem::createPlatformCalendarItemFromString(const std::string& value)
+{
+    LOGD("Entered vCalendar = %s", value.c_str());
+    if (value.empty()) {
+        LOGE("Entered");
+        throw UnknownException("Failed to create an item from string.");
+    }
+    calendar_list_h list = NULL;
+    int ret;
+
+    ret = calendar_vcalendar_parse_to_calendar(value.c_str(), &list);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_vcalendar_parse_to_calendar()");
+    }
+    if (NULL == list) {
+        LOGE("No items converted.");
+        throw UnknownException("No items converted.");
+    }
+    int count = -1;
+    LOGD("count = %d", count);
+    ret = calendar_list_get_count(list, &count);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Getting list count failed. count = %d", count);
+        LOGW("Failed calendar_list_get_count : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    } else {
+        LOGD("List count: %d", count);
+    }
+
+    calendar_record_h current_item = NULL;
+
+    char* uri = NULL;
+
+    calendar_list_first(list);
+
+    if (count > 0) {
+        while(count--) {
+            LOGD("List count: %d", count);
+            // We cover only one item per string.
+            current_item = NULL;
+
+            ret = calendar_list_get_current_record_p(list, &current_item);
+
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Getting current record failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            // Filter out the extended features.
+            uri = NULL;
+            ret = calendar_record_get_uri_p(current_item, &uri);
+            if (CALENDAR_ERROR_NONE!=ret) {
+                LOGW("Getting uri failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            if (0==strcmp(uri, _calendar_event._uri) && CALENDAR_EVENT == getType()) {
+                LOGD("Found an event.");
+            } else if (0==strcmp(uri, _calendar_todo._uri) && CALENDAR_TASK == getType()) {
+                LOGD("Found a task.");
+            } else {
+                LOGD("Skip an extended feature.");
+                calendar_list_next(list);
+                continue;
+            }
+            ret = calendar_record_clone(current_item, &m_platform_item);
+            if (CALENDAR_ERROR_NONE!=ret) {
+                LOGW("Clonning failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+    }
+    if (list) {
+        calendar_list_destroy(list, true);
+    }
+}
+
+std::string CalendarItem::exportCalendarItemToString()
+{
+    LOGD("Entered");
+    char *v_strings = NULL;
+    calendar_list_h list = NULL;
+    int ret;
+    std::string return_string;
+
+    ret = calendar_list_create(&list);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_list_create()");
+    }
+
+    ret = calendar_list_add(list, m_platform_item);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_list_create()");
+    }
+
+    ret = calendar_vcalendar_make_from_records(list, &v_strings);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_list_create()");
+    }
+    if (NULL==v_strings) {
+        LOGE("Can't add list item.");
+        throw UnknownException("Can't add list item.");
+    }
+
+    return_string = std::string(v_strings);
+
+    if (v_strings) free(v_strings);
+    v_strings = NULL;
+
+    if (list) {
+        // Don't destroy the record itself.
+        calendar_list_destroy(list, false);
+    }
+
+    return return_string;
+}
+
+void CalendarItem::freePlatformCalendarItem(calendar_record_h platform_item_tmp)
+{
+    LOGD("Entered");
+    int ret;
+    if (NULL == platform_item_tmp) {
+        platform_item_tmp = m_platform_item;
+    }
+
+    if (NULL != platform_item_tmp) {
+        ret = calendar_record_destroy(platform_item_tmp, true);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't destroy calendar record : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        platform_item_tmp = NULL;
+        m_platform_item = NULL;
+    } else {
+        LOGD("Null platform event.");
+    }
+}
+
+calendar_record_h CalendarItem::getPlatformCalendarItem()
+{
+    return m_platform_item;
+}
+
+} // Calendar
+} // DeviceAPI
diff --git a/src/Calendar/CalendarItem.h b/src/Calendar/CalendarItem.h
new file mode 100644 (file)
index 0000000..28b5239
--- /dev/null
@@ -0,0 +1,265 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        CalendarItem.h
+*/
+
+#ifndef _TIZEN_CALENDAR_ITEM_H_
+#define _TIZEN_CALENDAR_ITEM_H_
+
+#include "CalendarAttendee.h"
+#include "JSCalendarAttendee.h"
+#include "CalendarAlarm.h"
+#include "JSCalendarAlarm.h"
+#include <string>
+#include <memory>
+#include <vector>
+#include <SimpleCoordinates.h>
+#include <TimeDuration.h>
+#include <calendar.h>
+#include <JSVector.h>
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+#define UNDEFINED_CALENDAR_ID -1
+#define UNDEFINED_ITEM_ID -1
+#define UNDEFINED_GEO 1000
+
+class CalendarItem;
+typedef std::shared_ptr<CalendarItem> CalendarItemPtr;
+typedef std::vector<CalendarItemPtr> CalendarItemPtrVector;
+
+extern const char* CALENDAR_ITEM;
+
+extern const char* CALENDAR_ITEM_CALENDAR_ID;
+extern const char* CALENDAR_ITEM_LAST_MODIFICATION_DATE;
+extern const char* CALENDAR_ITEM_DESCRIPTION;
+extern const char* CALENDAR_ITEM_SUMMARY;
+extern const char* CALENDAR_ITEM_IS_ALL_DAY;
+extern const char* CALENDAR_ITEM_START_DATE;
+extern const char* CALENDAR_ITEM_DURATION;
+extern const char* CALENDAR_ITEM_LOCATION;
+extern const char* CALENDAR_ITEM_GEOLOCATION;
+extern const char* CALENDAR_ITEM_ORGANIZER;
+extern const char* CALENDAR_ITEM_VISIBILITY;
+extern const char* CALENDAR_ITEM_STATUS;
+extern const char* CALENDAR_ITEM_PRIORITY;
+extern const char* CALENDAR_ITEM_ALARMS;
+extern const char* CALENDAR_ITEM_CATEGORIES;
+extern const char* CALENDAR_ITEM_ATTENDEES;
+
+extern const std::string TYPE_PUBLIC_VISIBILITY;
+extern const std::string TYPE_PRIVATE_VISIBILITY;
+extern const std::string TYPE_CONFIDENTIAL_VISIBILITY;
+
+extern const std::string TYPE_TENTATIVE_STATUS;
+extern const std::string TYPE_CONFIRMED_STATUS;
+extern const std::string TYPE_CANCELLED_STATUS;
+extern const std::string TYPE_NEEDS_ACTION_STATUS;
+extern const std::string TYPE_IN_PROCESS_STATUS;
+extern const std::string TYPE_COMPLETED_STATUS;
+
+extern const std::string TYPE_HIGH_PRIORITY;
+extern const std::string TYPE_MEDIUM_PRIORITY;
+extern const std::string TYPE_LOW_PRIORITY;
+
+extern const std::string TYPE_ICALENDAR_20;
+extern const std::string TYPE_VCALENDAR_10;
+
+extern const char* CALENDAR_MANAGER_ATTRIBUTENAME;
+
+enum CalendarItemType{
+    CALENDAR_EVENT,
+    CALENDAR_TASK
+};
+
+enum ItemStatus {
+    TASK_STATUS_NEEDS_ACTION,
+    TASK_STATUS_IN_PROCESS,
+    TASK_STATUS_COMPLETED,
+    TASK_STATUS_CANCELLED,
+    TASK_STATUS_UNDEFINED,
+    EVENT_STATUS_TENTATIVE,
+    EVENT_STATUS_CONFIRMED,
+    EVENT_STATUS_CANCELLED,
+    EVENT_STATUS_UNDEFINED
+};
+
+enum CalendarItemAttribute{
+    CALENDAR_ITEM_ATTRIBUTE_CALENDAR_ID,
+    CALENDAR_ITEM_ATTRIBUTE_LAST_MODIFICATION_DATE,
+    CALENDAR_ITEM_ATTRIBUTE_DESCRIPTION,
+    CALENDAR_ITEM_ATTRIBUTE_SUMMARY,
+    CALENDAR_ITEM_ATTRIBUTE_IS_ALL_DAY,
+    CALENDAR_ITEM_ATTRIBUTE_START_DATE,
+    CALENDAR_ITEM_ATTRIBUTE_DURATION,
+    CALENDAR_ITEM_ATTRIBUTE_LOCATION,
+    CALENDAR_ITEM_ATTRIBUTE_GEOLOCATION,
+    CALENDAR_ITEM_ATTRIBUTE_ORGANIZER,
+    CALENDAR_ITEM_ATTRIBUTE_VISIBILITY,
+    CALENDAR_ITEM_ATTRIBUTE_STATUS,
+    CALENDAR_ITEM_ATTRIBUTE_PRIORITY,
+    CALENDAR_ITEM_ATTRIBUTE_ALARMS,
+    CALENDAR_ITEM_ATTRIBUTE_CATEGORIES,
+    CALENDAR_ITEM_ATTRIBUTE_ATTENDEES,
+    CALENDAR_ITEM_ATTRIBUTE_END_DATE,
+    CALENDAR_ITEM_NUMBER_OF_ATTRIBUTES
+};
+
+enum CalendarItemVisibility {
+    CALENDAR_ITEM_VISIBILITY_PUBLIC,
+    CALENDAR_ITEM_VISIBILITY_PRIVATE,
+    CALENDAR_ITEM_VISIBILITY_CONFIDENTIAL,
+    CALENDAR_ITEM_VISIBILITY_UNDEFINED
+};
+
+enum CalendarItemPriority {
+    CALENDAR_ITEM_PRIORITY_HIGH,
+    CALENDAR_ITEM_PRIORITY_MEDIUM,
+    CALENDAR_ITEM_PRIORITY_LOW,
+    CALENDAR_ITEM_PRIORITY_UNDEFINED
+};
+
+enum CalendarTextFormat {
+    CALENDAR_TEXT_FORMAT_ICALENDAR_20,
+    CALENDAR_TEXT_FORMAT_VCALENDAR_10,
+    CALENDAR_TEXT_FORMAT_UNDEFINED
+};
+
+class CalendarItem : public Common::SecurityAccessor {
+public:
+    CalendarItem();
+    CalendarItem(const CalendarItem& calendar_item);
+    virtual ~CalendarItem();
+
+    int getCalendarId() const;
+    void setCalendarId(int calendar_id);
+
+    long long int getLastModificationDate() const;
+    void setLastModificationDate(long long int last_modification_date);
+
+    const std::string& getDescription() const;
+    void setDescription(const std::string& description);
+
+    const std::string& getSummary() const;
+    void setSummary(const std::string& summary);
+
+    bool getIsAllDay() const;
+    void setIsAllDay(bool is_all_day);
+
+    const std::string& getTimezone();
+    long long int getStartDate() const;
+    void setStartDate(long long int start_date, const std::string& time_zone);
+
+    Time::TimeDurationPtr getDuration() const;
+    void setDuration(Time::TimeDurationPtr duration);
+
+    const std::string& getLocation() const;
+    void setLocation(const std::string& location);
+
+    Tizen::SimpleCoordinatesPtr getGeolocation() const;
+    void setGeolocation(Tizen::SimpleCoordinatesPtr geolocation);
+
+    const std::string& getOrganizer() const;
+    void setOrganizer(const std::string& organizer);
+
+    CalendarItemVisibility getVisibility() const;
+    void setVisibility(CalendarItemVisibility visibility);
+
+    ItemStatus getStatus() const;
+    void setStatus(ItemStatus status);
+
+    CalendarItemPriority getPriority() const;
+    void setPriority(CalendarItemPriority priority);
+
+    std::vector<CalendarAlarmPtr> getAlarms() const;
+    JSObjectRef getJSAlarms(JSContextRef global_ctx);
+    void setAlarms(const std::vector<CalendarAlarmPtr>& alarms);
+
+    std::vector<std::string> getCategories() const;
+    JSObjectRef getJSCategories(JSContextRef global_ctx);
+    void setCategories(const std::vector<std::string>& categories);
+
+    std::vector<CalendarAttendeePtr> getAttendees() const;
+    JSObjectRef getJSAttendees(JSContextRef global_ctx);
+    void setAttendees(const std::vector<CalendarAttendeePtr>& attendees);
+
+    long long int getEndDate() const;
+    void setEndDate(long long int end_date, const std::string& time_zone);
+
+    static const std::string& calendarItemVisibilityToString(CalendarItemVisibility visibility);
+    static CalendarItemVisibility stringToCalendarItemVisibility(const std::string& string_visibility);
+
+    static const std::string& calendarItemStatusToString(ItemStatus status, CalendarItemType type);
+    static ItemStatus stringToCalendarItemStatus(const std::string& string_status,
+            CalendarItemType type);
+
+    static const std::string& calendarItemPriorityToString(CalendarItemPriority priority);
+    static CalendarItemPriority stringToCalendarItemPriority(const std::string& string_priority);
+
+    static const std::string& calendarTextFormatToString(CalendarTextFormat format);
+    static CalendarTextFormat stringToCalendarTextFormat(const std::string& string_format);
+
+    bool isSet(CalendarItemAttribute attribute) const;
+    void setIsSet(CalendarItemAttribute attribute, bool is_set);
+    const std::vector<bool>& getIsSet() const;
+
+    const std::string& getFormat() const;
+    void setFormat(const std::string& format);
+
+    CalendarItemType getType() const;
+
+    void createPlatformCalendarItemFromString(const std::string& value);
+    std::string exportCalendarItemToString();
+
+    calendar_record_h getPlatformCalendarItem();
+protected:
+    void freePlatformCalendarItem(calendar_record_h platform_item_tmp = NULL);
+
+    int m_calendar_id;
+    std::string m_time_zone;                //this attribute is used in all date attributes
+    long long int m_last_modification_date; //this attribute is changed in JS layer
+    std::string m_description;
+    std::string m_summary;
+    bool m_is_all_day;
+    long long int m_start_date; //this attribute is changed in JS layer
+    Time::TimeDurationPtr m_duration;
+    std::string m_location;
+    Tizen::SimpleCoordinatesPtr m_geolocation;
+    std::string m_organizer;
+    CalendarItemVisibility m_visibility;
+    ItemStatus m_status;
+    CalendarItemPriority m_priority;
+    Common::JSObjectVector<CalendarAlarmPtr, JSCalendarAlarm> m_alarms;
+    Common::JSStringVector m_categories;
+    Common::JSObjectVector<CalendarAttendeePtr, JSCalendarAttendee> m_attendees;
+    long long int m_end_date; //this attribute is changed in JS layer
+
+    std::string m_format;
+    std::vector<bool> m_is_set;
+
+    CalendarItemType m_type;
+    calendar_record_h m_platform_item;
+};
+
+} //Calendar
+} //DeviceAPI
+
+#endif
diff --git a/src/Calendar/CalendarItemSearchEngine.cpp b/src/Calendar/CalendarItemSearchEngine.cpp
new file mode 100755 (executable)
index 0000000..148606b
--- /dev/null
@@ -0,0 +1,1895 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Commons/Exception.h>
+#include <sstream>
+#include <Logger.h>
+#include <JSTZDate.h>
+
+#include "CalendarManager.h"
+#include "CalendarEvent.h"
+#include "CalendarTask.h"
+#include "CalendarUtility.h"
+#include "CalendarItemSearchEngine.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+using namespace DeviceAPI::Common;
+using namespace Tizen;
+
+// List of attributes that can be used as the filter argument.
+namespace {
+const std::string CALENDAR_FILTER_ATTRIBUTE_ID_UID = "id.uid"; // for event
+const std::string CALENDAR_FILTER_ATTRIBUTE_ID = "id"; // for task
+const std::string CALENDAR_FILTER_ATTRIBUTE_LAST_MODIFIED_DATE = "lastModificationDate";
+const std::string CALENDAR_FILTER_ATTRIBUTE_DESCRIPTION = "description";
+const std::string CALENDAR_FILTER_ATTRIBUTE_SUMMARY = "summary";
+const std::string CALENDAR_FILTER_ATTRIBUTE_IS_ALL_DAY = "isAllDay";
+const std::string CALENDAR_FILTER_ATTRIBUTE_START_DATE = "startDate";
+const std::string CALENDAR_FILTER_ATTRIBUTE_LOCATION = "location";
+const std::string CALENDAR_FILTER_ATTRIBUTE_LATITUDE = "geolocation.latitude";
+const std::string CALENDAR_FILTER_ATTRIBUTE_LONGITUDE = "geolocation.longitude";
+const std::string CALENDAR_FILTER_ATTRIBUTE_ORGANIZER = "organizer";
+const std::string CALENDAR_FILTER_ATTRIBUTE_VISIBILITY = "visibility";
+const std::string CALENDAR_FILTER_ATTRIBUTE_STATUS = "status";
+const std::string CALENDAR_FILTER_ATTRIBUTE_PRIORITY = "priority";
+const std::string CALENDAR_FILTER_ATTRIBUTE_ALARMS = "alarms";
+const std::string CALENDAR_FILTER_ATTRIBUTE_CATEGORIES = "categories";
+const std::string CALENDAR_FILTER_ATTRIBUTE_ATTENDEES = "attendees";
+const std::string CALENDAR_FILTER_ATTRIBUTE_DUE_DATE = "dueDate";
+const std::string CALENDAR_FILTER_ATTRIBUTE_COMPLETED_DATE = "completedDate";
+const std::string CALENDAR_FILTER_ATTRIBUTE_PROGRESS = "progress";
+const std::string CALENDAR_FILTER_ATTRIBUTE_IS_DETACHED = "isDetached";
+const std::string CALENDAR_FILTER_ATTRIBUTE_END_DATE = "endDate";
+const std::string CALENDAR_FILTER_ATTRIBUTE_AVAILABILITY = "availability";
+const std::string CALENDAR_FILTER_ATTRIBUTE_RECURRENCE_RULE = "recurrenceRule";
+}
+
+std::map<std::string, CalendarItemSearchEngine::FilterPropertyStruct> CalendarItemSearchEngine::s_event_attribute_map = {
+    {CALENDAR_FILTER_ATTRIBUTE_ID_UID,
+            {_calendar_event.id, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_LAST_MODIFIED_DATE,
+            {_calendar_event.last_modified_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_DESCRIPTION,
+            {_calendar_event.description, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_SUMMARY,
+            {_calendar_event.summary, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_IS_ALL_DAY,
+            {_calendar_event.is_allday, PrimitiveType_Boolean} },
+    {CALENDAR_FILTER_ATTRIBUTE_START_DATE,
+            {_calendar_event.start_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_LOCATION,
+            {_calendar_event.location, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_LATITUDE,
+            {_calendar_event.latitude, PrimitiveType_Double} },
+    {CALENDAR_FILTER_ATTRIBUTE_LONGITUDE,
+            {_calendar_event.longitude, PrimitiveType_Double} },
+    {CALENDAR_FILTER_ATTRIBUTE_ORGANIZER,
+            {_calendar_event.organizer_name, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_VISIBILITY,
+            {_calendar_event.sensitivity, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_STATUS,
+            {_calendar_event.event_status, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_PRIORITY,
+            {_calendar_event.priority, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_ALARMS,
+            {_calendar_event.has_alarm, PrimitiveType_Null} },
+    {CALENDAR_FILTER_ATTRIBUTE_CATEGORIES,
+            {_calendar_event.categories, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_ATTENDEES,
+            {_calendar_event.has_attendee, PrimitiveType_Null} },
+    {CALENDAR_FILTER_ATTRIBUTE_IS_DETACHED,
+            {_calendar_event.original_event_id, PrimitiveType_Boolean} },
+    {CALENDAR_FILTER_ATTRIBUTE_END_DATE,
+            {_calendar_event.end_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_AVAILABILITY,
+            {_calendar_event.busy_status, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_RECURRENCE_RULE,
+            {_calendar_event.freq, PrimitiveType_Null} }
+};
+
+std::map<std::string, CalendarItemSearchEngine::FilterPropertyStruct> CalendarItemSearchEngine::s_normal_instance_attribute_map = {
+    {CALENDAR_FILTER_ATTRIBUTE_ID_UID,
+            {_calendar_instance_utime_calendar_book.event_id, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_LAST_MODIFIED_DATE,
+            {_calendar_instance_utime_calendar_book.last_modified_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_DESCRIPTION,
+            {_calendar_instance_utime_calendar_book.description, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_SUMMARY,
+            {_calendar_instance_utime_calendar_book.summary, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_START_DATE,
+            {_calendar_instance_utime_calendar_book.start_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_LOCATION,
+            {_calendar_instance_utime_calendar_book.location, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_LATITUDE,
+            {_calendar_instance_utime_calendar_book.latitude, PrimitiveType_Double} },
+    {CALENDAR_FILTER_ATTRIBUTE_LONGITUDE,
+            {_calendar_instance_utime_calendar_book.longitude, PrimitiveType_Double} },
+    //{CALENDAR_FILTER_ATTRIBUTE_ORGANIZER,
+            //{_calendar_instance_utime_calendar_book.organizer_name, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_VISIBILITY,
+            {_calendar_instance_utime_calendar_book.sensitivity, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_STATUS,
+            {_calendar_instance_utime_calendar_book.event_status, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_ALARMS,
+            {_calendar_instance_utime_calendar_book.has_alarm, PrimitiveType_Null} },
+    //{CALENDAR_FILTER_ATTRIBUTE_CATEGORIES,
+            //{_calendar_instance_utime_calendar_book.categories, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_PRIORITY,
+            {_calendar_instance_utime_calendar_book.priority, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_IS_DETACHED,
+            {_calendar_instance_utime_calendar_book.original_event_id,  PrimitiveType_Boolean} },
+    //{CALENDAR_FILTER_ATTRIBUTE_IS_ALL_DAY,
+            //{_calendar_instance_utime_calendar_book.is_allday, PrimitiveType_Boolean} }, no meaning for instance.
+    //{CALENDAR_FILTER_ATTRIBUTE_ATTENDEES,
+            //{_calendar_instance_utime_calendar_book.has_attendee, PrimitiveType_Null} },
+    {CALENDAR_FILTER_ATTRIBUTE_END_DATE,
+            {_calendar_instance_utime_calendar_book.end_time, PrimitiveType_Boolean} },
+    {CALENDAR_FILTER_ATTRIBUTE_AVAILABILITY,
+            {_calendar_instance_utime_calendar_book.busy_status, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_RECURRENCE_RULE,
+            {_calendar_instance_utime_calendar_book.has_rrule, PrimitiveType_Null} }
+};
+
+std::map<std::string, CalendarItemSearchEngine::FilterPropertyStruct> CalendarItemSearchEngine::s_all_day_instance_attribute_map = {
+    {CALENDAR_FILTER_ATTRIBUTE_ID_UID,
+            {_calendar_instance_localtime_calendar_book.event_id, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_LAST_MODIFIED_DATE,
+            {_calendar_instance_localtime_calendar_book.last_modified_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_DESCRIPTION,
+            {_calendar_instance_localtime_calendar_book.description, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_SUMMARY,
+            {_calendar_instance_localtime_calendar_book.summary, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_START_DATE,
+            {_calendar_instance_localtime_calendar_book.start_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_LOCATION,
+            {_calendar_instance_localtime_calendar_book.location, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_LATITUDE,
+            {_calendar_instance_localtime_calendar_book.latitude, PrimitiveType_Double} },
+    {CALENDAR_FILTER_ATTRIBUTE_LONGITUDE,
+            {_calendar_instance_localtime_calendar_book.longitude, PrimitiveType_Double} },
+    //{CALENDAR_FILTER_ATTRIBUTE_ORGANIZER,
+            //{_calendar_instance_localtime_calendar_book.organizer_name, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_VISIBILITY,
+            {_calendar_instance_localtime_calendar_book.sensitivity, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_STATUS,
+            {_calendar_instance_localtime_calendar_book.event_status, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_ALARMS,
+            {_calendar_instance_localtime_calendar_book.has_alarm, PrimitiveType_Null} },
+    //{CALENDAR_FILTER_ATTRIBUTE_CATEGORIES,
+            //{_calendar_instance_localtime_calendar_book.categories, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_PRIORITY,
+            {_calendar_instance_localtime_calendar_book.priority, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_IS_DETACHED,
+            {_calendar_instance_localtime_calendar_book.original_event_id, PrimitiveType_Boolean} },
+    //{CALENDAR_FILTER_ATTRIBUTE_IS_ALL_DAY,
+            //{_calendar_instance_localtime_calendar_book.is_allday, PrimitiveType_Boolean} }, no meaning for instance.
+    //{CALENDAR_FILTER_ATTRIBUTE_ATTENDEES,
+            //{_calendar_instance_localtime_calendar_book.has_attendee, PrimitiveType_Null} },
+    {CALENDAR_FILTER_ATTRIBUTE_END_DATE,
+            {_calendar_instance_localtime_calendar_book.end_time, PrimitiveType_Boolean} },
+    {CALENDAR_FILTER_ATTRIBUTE_AVAILABILITY,
+            {_calendar_instance_localtime_calendar_book.busy_status, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_RECURRENCE_RULE,
+            {_calendar_instance_localtime_calendar_book.has_rrule, PrimitiveType_Null} }
+};
+
+std::map<std::string, CalendarItemSearchEngine::FilterPropertyStruct> CalendarItemSearchEngine::s_task_attribute_map = {
+    {CALENDAR_FILTER_ATTRIBUTE_ID,
+            {_calendar_todo.id, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_LAST_MODIFIED_DATE,
+            {_calendar_todo.last_modified_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_DESCRIPTION,
+            {_calendar_todo.description, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_SUMMARY,
+            {_calendar_todo.summary, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_START_DATE,
+            {_calendar_todo.start_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_LOCATION,
+            {_calendar_todo.location, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_LATITUDE,
+            {_calendar_todo.latitude, PrimitiveType_Double} },
+    {CALENDAR_FILTER_ATTRIBUTE_LONGITUDE,
+            {_calendar_todo.longitude, PrimitiveType_Double} },
+    {CALENDAR_FILTER_ATTRIBUTE_ORGANIZER,
+            {_calendar_todo.organizer_name, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_VISIBILITY,
+            {_calendar_todo.sensitivity, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_STATUS,
+            {_calendar_todo.todo_status, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_ALARMS,
+            {_calendar_todo.has_alarm, PrimitiveType_Null} },
+    {CALENDAR_FILTER_ATTRIBUTE_CATEGORIES,
+            {_calendar_todo.categories, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_PRIORITY,
+            {_calendar_todo.priority, PrimitiveType_String} },
+    {CALENDAR_FILTER_ATTRIBUTE_DUE_DATE,
+            {_calendar_todo.due_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_COMPLETED_DATE,
+            {_calendar_todo.completed_time, PrimitiveType_PlatformObject} },
+    {CALENDAR_FILTER_ATTRIBUTE_PROGRESS,
+            {_calendar_todo.progress, PrimitiveType_Long} },
+    {CALENDAR_FILTER_ATTRIBUTE_IS_ALL_DAY,
+            {_calendar_todo.is_allday, PrimitiveType_Boolean} },
+    {CALENDAR_FILTER_ATTRIBUTE_ATTENDEES,
+            {_calendar_todo.has_attendee, PrimitiveType_Null} }
+};
+
+FilterClass::FilterClass(CalendarUtility::CalendarType type_arg):
+        filter(NULL),
+        normal_instance_filter(NULL),
+        all_day_instance_filter(NULL)
+{
+    LOGD("Entered");
+    int ret =  CALENDAR_ERROR_NONE;
+    if (CalendarUtility::CalendarType::TASK == type_arg) {
+        ret = calendar_filter_create(_calendar_todo._uri, &filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Filter creation failed");
+        }
+    }
+    else if (CalendarUtility::CalendarType::EVENT == type_arg) {
+        ret = calendar_filter_create(_calendar_event._uri, &filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Filter creation failed");
+        }
+        ret = calendar_filter_create(_calendar_instance_utime_calendar_book._uri,
+                &normal_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Normal instance filter creation failed");
+        }
+        ret = calendar_filter_create(_calendar_instance_localtime_calendar_book._uri,
+                &all_day_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "All day instance filter creation failed");
+        }
+    }
+    else {
+        LOGE("Invalid calendar type");
+        throw TypeMismatchException("Invalid calendar type");
+    }
+    type = type_arg;
+}
+
+FilterClass::~FilterClass()
+{
+    LOGD("Entered");
+    int ret;
+    if (filter) {
+        ret = calendar_filter_destroy(filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            filter = NULL;
+        }
+    }
+    if (normal_instance_filter) {
+        ret = calendar_filter_destroy(normal_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            normal_instance_filter = NULL;
+        }
+    }
+    if (all_day_instance_filter) {
+        ret = calendar_filter_destroy(all_day_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            all_day_instance_filter = NULL;
+        }
+    }
+}
+
+FilterClass & FilterClass::operator =(const FilterClass& filters)
+{
+    return *this;
+}
+
+CalendarItemSearchEngine::CalendarItemSearchEngine(CalendarUtility::CalendarType type):
+        m_query(NULL),
+        m_filter(NULL),
+        m_normal_instance_query(NULL),
+        m_normal_instance_filter(NULL),
+        m_all_day_instance_query(NULL),
+        m_all_day_instance_filter(NULL),
+        m_enable_instance_search(false)
+{
+    LOGD("Entered");
+    int ret = CALENDAR_ERROR_NONE;
+    if (CalendarUtility::CalendarType::TASK == type) {
+        ret = calendar_query_create(_calendar_todo._uri, &m_query);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Query creation failed");
+        }
+
+        ret = calendar_filter_create(_calendar_todo._uri, &m_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Filter creation failed");
+        }
+
+    }
+    else if (CalendarUtility::CalendarType::EVENT == type) {
+        ret = calendar_query_create(_calendar_event._uri, &m_query);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Query creation failed");
+        }
+
+        ret = calendar_filter_create(_calendar_event._uri, &m_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Filter creation failed");
+        }
+
+        ret = calendar_query_create(_calendar_instance_utime_calendar_book._uri,
+                &m_normal_instance_query);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Normal instance query creation failed");
+        }
+
+        ret = calendar_filter_create(_calendar_instance_utime_calendar_book._uri,
+                &m_normal_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Normal instance filter creation failed");
+        }
+
+        ret = calendar_query_create(_calendar_instance_localtime_calendar_book._uri,
+                &m_all_day_instance_query);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "All day instance query creation failed");
+        }
+
+        ret = calendar_filter_create(_calendar_instance_localtime_calendar_book._uri,
+                &m_all_day_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "All day instance filter creation failed");
+        }
+
+    }
+    else {
+        LOGE("Invalid calendar type");
+        throw TypeMismatchException("Invalid calendar type");
+    }
+    m_type = type;
+}
+
+CalendarItemSearchEngine::~CalendarItemSearchEngine()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_query) {
+        ret = calendar_query_destroy(m_query);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy query failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            m_query = NULL;
+        }
+    }
+    if (m_filter) {
+        ret = calendar_filter_destroy(m_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            m_filter = NULL;
+        }
+    }
+    if (m_normal_instance_query) {
+        ret = calendar_query_destroy(m_normal_instance_query);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy query failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            m_normal_instance_query = NULL;
+        }
+    }
+    if (m_normal_instance_filter) {
+        ret = calendar_filter_destroy(m_normal_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            m_normal_instance_filter = NULL;
+        }
+    }
+    if (m_all_day_instance_query) {
+        ret = calendar_query_destroy(m_all_day_instance_query);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy query failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            m_all_day_instance_query = NULL;
+        }
+    }
+    if (m_all_day_instance_filter) {
+        ret = calendar_filter_destroy(m_all_day_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            m_all_day_instance_filter = NULL;
+        }
+    }
+}
+
+CalendarItemSearchEngine & CalendarItemSearchEngine::operator =( const CalendarItemSearchEngine& engine)
+{
+    return *this;
+}
+
+CalendarUtility::CalendarType CalendarItemSearchEngine::getType() const
+{
+    LOGD("Entered");
+    return m_type;
+}
+
+void CalendarItemSearchEngine::setCalendarId(int calendar_id, bool is_filter_set)
+{
+    LOGD("Entered");
+    int ret;
+    if (CalendarManager::UNIFIED_CALENDAR_ID == calendar_id) {
+        calendar_id = CALENDAR_BOOK_FILTER_ALL;
+    }
+
+    if (is_filter_set) {
+        calendar_filter_h super_filter = NULL;
+        calendar_filter_h normal_instance_super_filter = NULL;
+        calendar_filter_h all_day_instance_super_filter = NULL;
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            ret = calendar_filter_create(_calendar_todo._uri, &super_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter creation failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_add_filter(super_filter, m_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed.");
+            }
+        } else {
+            ret = calendar_filter_create(_calendar_event._uri, &super_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter creation failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_add_filter(super_filter, m_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_create(_calendar_instance_utime_calendar_book._uri,
+                    &normal_instance_super_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter creation failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_add_filter(normal_instance_super_filter,
+                    m_normal_instance_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_create(_calendar_instance_localtime_calendar_book._uri,
+                    &all_day_instance_super_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter creation failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_add_filter(all_day_instance_super_filter,
+                    m_all_day_instance_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        ret = calendar_filter_destroy(m_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        ret = calendar_filter_destroy(m_normal_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        ret = calendar_filter_destroy(m_all_day_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+
+        m_filter = super_filter;
+        m_normal_instance_filter = normal_instance_super_filter;
+        m_all_day_instance_filter = all_day_instance_super_filter;
+
+        ret = calendar_filter_add_operator(m_filter,
+                CALENDAR_FILTER_OPERATOR_AND);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        ret = calendar_filter_add_operator(m_normal_instance_filter,
+                CALENDAR_FILTER_OPERATOR_AND);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        ret = calendar_filter_add_operator(m_all_day_instance_filter,
+                CALENDAR_FILTER_OPERATOR_AND);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+
+    calendar_match_int_flag_e match_int_flag = CALENDAR_MATCH_EQUAL;
+    if (CALENDAR_BOOK_FILTER_ALL == calendar_id
+           || CalendarManager::UNIFIED_CALENDAR_ID == calendar_id) {
+        match_int_flag = CALENDAR_MATCH_GREATER_THAN;
+    }
+
+    if (CalendarUtility::CalendarType::TASK == m_type) {
+        ret = calendar_filter_add_int(m_filter, _calendar_todo.calendar_book_id,
+                match_int_flag, calendar_id);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        ret = calendar_filter_add_operator(m_filter, CALENDAR_FILTER_OPERATOR_AND);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        ret = calendar_filter_add_int(m_filter, _calendar_todo.is_deleted,
+                CALENDAR_MATCH_EQUAL, 0);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+   } else {
+        ret = calendar_filter_add_int(m_filter, _calendar_event.calendar_book_id,
+                 match_int_flag, calendar_id);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+
+        ret = calendar_filter_add_int(m_normal_instance_filter,
+                 _calendar_instance_utime_calendar_book.calendar_book_id,
+                 match_int_flag, calendar_id);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+
+        ret = calendar_filter_add_int(m_all_day_instance_filter,
+                 _calendar_instance_localtime_calendar_book.calendar_book_id,
+                 match_int_flag, calendar_id);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+
+        /* No matching is_deleted field for instance tables. */
+        ret = calendar_filter_add_operator(m_filter, CALENDAR_FILTER_OPERATOR_AND);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        ret = calendar_filter_add_int(m_filter, _calendar_event.is_deleted,
+                CALENDAR_MATCH_EQUAL, 0);
+        if (ret != CALENDAR_ERROR_NONE) {
+             LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarItemSearchEngine::findSupport(calendar_query_h query, calendar_filter_h filter,
+        unsigned int property_id, std::shared_ptr<CalendarItemPtrVector> items_vector)
+{
+    LOGD("Entered");
+    int ret = calendar_query_set_filter(query, filter);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("Setting a instance filter failed: %d", ret);
+        throw UnknownException("Setting a instance filter failed");
+    }
+
+    calendar_list_h record_list = NULL;
+    ret = calendar_db_get_records_with_query(query, 0, 0,
+            &record_list);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Getting a normal instance record list failed");
+    }
+
+    calendar_list_h_ptr record_list_ptr(&record_list,
+            listDeleterDeep);
+
+    int record_count = 0;
+    ret = calendar_list_get_count(*record_list_ptr,
+            &record_count);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Can't get a instance item count");
+    }
+    else {
+        LOGD("Normal instance item count");
+    }
+
+    calendar_list_first(*record_list_ptr);
+    while (record_count--) {
+        calendar_record_h current_record = NULL;
+        ret = calendar_list_get_current_record_p(*record_list_ptr,
+                &current_record);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't get current record");
+        }
+
+        int id = -1;
+        ret = calendar_record_get_int(current_record, property_id, &id);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't get the instance parent id");
+        }
+
+        // Skip if the parent item is already found.
+        int parent_count = items_vector->size();
+
+        bool found = false;
+        int cur_id;
+
+        if (CalendarUtility::CalendarType::EVENT == m_type) {
+            while (parent_count--) {
+                cur_id = -1;
+                CalendarItemPtr cur_item_ptr = items_vector->at(parent_count);
+                    cur_id = (std::dynamic_pointer_cast < CalendarEvent> (cur_item_ptr))->getId()->getUid();
+                if (id == cur_id) {
+                    found = true;
+                    break;
+                }
+            }
+        }
+        else if (CalendarUtility::CalendarType::TASK == m_type) {
+            while (parent_count--) {
+                cur_id = -1;
+                CalendarItemPtr cur_item_ptr = items_vector->at(parent_count);
+                    cur_id = (std::dynamic_pointer_cast < CalendarTask> (cur_item_ptr))->getId();
+                if (id == cur_id) {
+                    found = true;
+                    break;
+                }
+            }
+        }
+        if (!found) {
+            calendar_record_h record = NULL;
+            if (CalendarUtility::CalendarType::EVENT == m_type) {
+                ret = calendar_db_get_record(_calendar_event._uri, id, &record);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    CalendarUtility::throwCalendarException(ret, "Can't get record");
+                }
+                calendar_record_h_ptr record_ptr(&record, recordDeleterDeep);
+                CalendarEventPtr event_item(new CalendarEvent());
+                event_item->convertPlatFormEventToAbstractCalendarEvent(*record_ptr);
+                items_vector->push_back(event_item);
+            }
+            else if (CalendarUtility::CalendarType::TASK == m_type) {
+                ret = calendar_db_get_record(_calendar_todo._uri, id, &record);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    CalendarUtility::throwCalendarException(ret, "Can't get record");
+                }
+                calendar_record_h_ptr record_ptr(&record, recordDeleterDeep);
+                CalendarTaskPtr task_item(new CalendarTask());
+                task_item->convertPlatformTaskToAbstractCalendarTask(*record_ptr);
+                items_vector->push_back(task_item);
+            }
+        }
+        calendar_list_next(*record_list_ptr);
+    }
+}
+
+std::shared_ptr<CalendarItemPtrVector> CalendarItemSearchEngine::find()
+{
+    LOGD("Entered");
+    std::shared_ptr<CalendarItemPtrVector> items_vector(new CalendarItemPtrVector());
+    int ret = calendar_query_set_filter(m_query, m_filter);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Setting filter failed");
+    }
+    calendar_list_h record_list = NULL;
+    ret = calendar_db_get_records_with_query(m_query, 0, 0, &record_list);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Getting record list failed");
+    }
+    calendar_list_h_ptr record_list_ptr(&record_list, listDeleterDeep);
+
+    int record_count = 0;
+    ret = calendar_list_get_count(*record_list_ptr, &record_count);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "Can't get the item count");
+    }
+    else {
+        LOGD("Item count: %d", record_count);
+    }
+    items_vector->reserve(record_count);
+    //////////////////////////////////////////////////////////////////////////////////////
+    //main part of the search
+    //////////////////////////////////////////////////////////////////////////////////////
+    calendar_list_first(*record_list_ptr);
+    while (record_count--) {
+        calendar_record_h current_record = NULL;
+        ret = calendar_list_get_current_record_p(*record_list_ptr, &current_record);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "Can't get current record");
+        }
+        if (CalendarUtility::CalendarType::EVENT == m_type) {
+            CalendarEventPtr event_item(new CalendarEvent());
+            event_item->convertPlatFormEventToAbstractCalendarEvent(current_record);
+            items_vector->push_back(event_item);
+        }
+        else if (CalendarUtility::CalendarType::TASK == m_type) {
+            CalendarTaskPtr task_item(new CalendarTask());
+            task_item->convertPlatformTaskToAbstractCalendarTask(current_record);
+            items_vector->push_back(task_item);
+        }
+        else {
+            LOGE("Invalid calendar type");
+            throw UnknownException("Invalid calendar type");
+        }
+        calendar_list_next(*record_list_ptr);
+    }
+    if (m_enable_instance_search) {
+        LOGD("Perform query for instances");
+        findSupport(m_normal_instance_query, m_normal_instance_filter,
+                _calendar_instance_utime_calendar_book.event_id, items_vector);
+        findSupport(m_all_day_instance_query, m_all_day_instance_filter,
+                _calendar_instance_localtime_calendar_book.event_id, items_vector);
+    }
+    else {
+        LOGD("No need to perform query for instances.");
+    }
+    return items_vector;
+}
+
+void CalendarItemSearchEngine::applySortMode(SortModePtr sort_mode)
+{
+    LOGD("Entered");
+    int ret;
+    if (!sort_mode) {
+        LOGD("No sortMode set");
+        return;
+    }
+
+    std::string attr_name = sort_mode->getAttributeName();
+    if (attr_name.empty()) {
+       bool is_asc = false;
+
+       if (sort_mode->getOrder() == SortModeOrder::ASC) {
+           is_asc = true;
+       }
+
+       if (CalendarUtility::CalendarType::TASK == m_type) {
+           ret = calendar_query_set_sort(m_query,
+                   s_task_attribute_map[attr_name].property_id, is_asc);
+           if (ret != CALENDAR_ERROR_NONE) {
+               LOGW("Query set failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+           }
+       }
+       else {
+           ret = calendar_query_set_sort(m_query,
+                   s_event_attribute_map[attr_name].property_id, is_asc);
+           if (ret != CALENDAR_ERROR_NONE) {
+               LOGW("Query set failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+           }
+
+           ret = calendar_query_set_sort(m_normal_instance_query,
+                   s_normal_instance_attribute_map[attr_name].property_id, is_asc);
+           if (ret != CALENDAR_ERROR_NONE) {
+               LOGW("Query set failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+           }
+
+           ret = calendar_query_set_sort(m_all_day_instance_query,
+                   s_all_day_instance_attribute_map[attr_name].property_id, is_asc);
+           if (ret != CALENDAR_ERROR_NONE) {
+               LOGW("Query set failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+           }
+       }
+    }
+    else {
+        LOGW("Empty attribute name.");
+    }
+}
+
+void CalendarItemSearchEngine::applyFilter(AbstractFilterPtr filter)
+{
+    LOGD("Entered");
+    int ret;
+    if (!filter) {
+        LOGD("No AbstractFilter set");
+        return;
+    }
+
+    FilterClassPtr returned_filters;
+
+    switch (filter->getFilterType()) {
+        case ATTRIBUTE_FILTER:
+        {
+            AttributeFilterPtr attribute_filter = std::dynamic_pointer_cast
+                    < AttributeFilter > (filter);
+            if (!attribute_filter) {
+                LOGE("Could not cast AbstractFilterPtr to AttributeFilterPtr");
+                throw UnknownException("Wrong filter type");
+            }
+            returned_filters.reset(applyAttributeFilter(attribute_filter));
+            break;
+        }
+        case ATTRIBUTE_RANGE_FILTER:
+        {
+            AttributeRangeFilterPtr attribute_range_filter = std::dynamic_pointer_cast
+                    < AttributeRangeFilter > (filter);
+            if (!attribute_range_filter) {
+                LOGE("Could not cast AbstractFilterPtr to AttributeRangeFilterPtr");
+                throw UnknownException("Wrong filter type");
+            }
+            returned_filters.reset(applyAttributeRangeFilter(attribute_range_filter));
+            break;
+        }
+        case COMPOSITE_FILTER:
+        {
+            CompositeFilterPtr composite_filter = std::dynamic_pointer_cast
+                    < CompositeFilter > (filter);
+            if (!composite_filter) {
+                LOGE("Could not cast AbstractFilterPtr to CompositeFilterPtr");
+                throw UnknownException("Wrong filter type");
+            }
+            returned_filters.reset(applyCompositeFilter(composite_filter));
+            break;
+        }
+        default:
+            LOGE("Wrong filter type");
+            throw UnknownException("Wrong filter type");
+    }
+
+    if (m_filter) {
+        ret = calendar_filter_destroy(m_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            m_filter = NULL;
+        }
+    }
+
+    if (m_normal_instance_filter) {
+        ret = calendar_filter_destroy(m_normal_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            m_normal_instance_filter = NULL;
+        }
+    }
+
+    if (m_all_day_instance_filter) {
+        ret = calendar_filter_destroy(m_all_day_instance_filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("destroy filter failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        } else {
+            m_all_day_instance_filter = NULL;
+        }
+    }
+
+    m_filter = returned_filters->filter;
+    m_normal_instance_filter = returned_filters->normal_instance_filter;
+    m_all_day_instance_filter = returned_filters->all_day_instance_filter;
+    returned_filters.release();
+}
+
+void CalendarItemSearchEngine::calendarFilterAddInt(calendar_filter_h filter,
+        calendar_filter_h normal_instance_filter,
+        calendar_filter_h all_day_instance_filter,
+        const std::string& attr_name,
+        calendar_match_int_flag_e match, int value)
+{
+    int ret;
+
+    ret = calendar_filter_add_int(filter,
+            s_event_attribute_map[attr_name].property_id, match, value);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    ret = calendar_filter_add_int(normal_instance_filter,
+            s_normal_instance_attribute_map[attr_name].property_id, match, value);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    ret = calendar_filter_add_int(all_day_instance_filter,
+            s_all_day_instance_attribute_map[attr_name].property_id, match, value);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+}
+
+void CalendarItemSearchEngine::calendarFilterAddLLI(calendar_filter_h filter,
+        calendar_filter_h normal_instance_filter,
+        calendar_filter_h all_day_instance_filter,
+        const std::string& attr_name,
+        calendar_match_int_flag_e match, long long int value)
+{
+    int ret;
+
+    ret = calendar_filter_add_lli(filter,
+            s_event_attribute_map[attr_name].property_id, match, value);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    ret = calendar_filter_add_lli(normal_instance_filter,
+            s_normal_instance_attribute_map[attr_name].property_id, match, value);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    ret = calendar_filter_add_lli(all_day_instance_filter,
+            s_all_day_instance_attribute_map[attr_name].property_id, match, value);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+}
+
+void CalendarItemSearchEngine::calendarFilterAddDouble(calendar_filter_h filter,
+        calendar_filter_h normal_instance_filter,
+        calendar_filter_h all_day_instance_filter,
+        const std::string& attr_name,
+        calendar_match_int_flag_e match, double value)
+{
+    int ret;
+
+    ret = calendar_filter_add_double(filter,
+            s_event_attribute_map[attr_name].property_id, match, value);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    ret = calendar_filter_add_double(normal_instance_filter,
+            s_normal_instance_attribute_map[attr_name].property_id, match, value);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    ret = calendar_filter_add_double(all_day_instance_filter,
+            s_all_day_instance_attribute_map[attr_name].property_id, match, value);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+}
+
+void CalendarItemSearchEngine::calendarFilterAddStr(calendar_filter_h filter,
+        calendar_filter_h normal_instance_filter,
+        calendar_filter_h all_day_instance_filter,
+        const std::string& attr_name,
+        calendar_match_str_flag_e match, const std::string& value)
+{
+    int ret;
+
+    ret = calendar_filter_add_str(filter,
+            s_event_attribute_map[attr_name].property_id, match, value.c_str());
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    ret = calendar_filter_add_str(normal_instance_filter,
+            s_normal_instance_attribute_map[attr_name].property_id, match, value.c_str());
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    ret = calendar_filter_add_str(all_day_instance_filter,
+            s_all_day_instance_attribute_map[attr_name].property_id, match, value.c_str());
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+}
+
+FilterClass* CalendarItemSearchEngine::applyAttributeFilter(AttributeFilterPtr filter)
+{
+    LOGD("Entered");
+    int ret;
+    FilterClassPtr returned_filters(new FilterClass(m_type));
+
+    std::string attr_name = filter->getAttributeName();
+    FilterMatchFlag match_flag = filter->getMatchFlag();
+    AnyPtr match_value = filter->getMatchValue();
+
+    calendar_match_str_flag_e str_match_flag = CALENDAR_MATCH_EXACTLY;
+    calendar_match_int_flag_e int_match_flag = CALENDAR_MATCH_EQUAL;
+
+    switch (match_flag) {
+        case EXACTLY : {
+            str_match_flag = CALENDAR_MATCH_EXACTLY;
+            int_match_flag = CALENDAR_MATCH_EQUAL;
+            break;
+        }
+        case FULLSTRING : {
+            str_match_flag = CALENDAR_MATCH_FULLSTRING;
+            break;
+        }
+        case CONTAINS : {
+            str_match_flag = CALENDAR_MATCH_CONTAINS;
+            break;
+        }
+        case STARTSWITH : {
+            str_match_flag = CALENDAR_MATCH_STARTSWITH;
+            break;
+        }
+        case ENDSWITH : {
+            str_match_flag = CALENDAR_MATCH_ENDSWITH;
+            break;
+        }
+        case EXISTS : {
+            str_match_flag = CALENDAR_MATCH_EXISTS;
+            break;
+        }
+        default:
+            LOGW("Invalid matchFlag!");
+            break;
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Date part
+    //////////////////////////////////////////////////////////////////////////////////////
+    if (CALENDAR_FILTER_ATTRIBUTE_START_DATE == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_DUE_DATE == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_END_DATE == attr_name) {
+        calendar_time_s cal_time = { CALENDAR_TIME_UTIME, { 0 } };
+        cal_time.time.utime = getTimeTFromTZDateAny(match_value);
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            ret = calendar_filter_add_caltime(returned_filters->filter,
+                   s_task_attribute_map[attr_name].property_id,
+                   int_match_flag, cal_time);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            ret = calendar_filter_add_caltime(returned_filters->filter,
+                   s_event_attribute_map[attr_name].property_id,
+                   int_match_flag, cal_time);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            ret = calendar_filter_add_caltime(returned_filters->normal_instance_filter,
+                   s_normal_instance_attribute_map[attr_name].property_id,
+                   int_match_flag, cal_time);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            ret = calendar_filter_add_caltime(returned_filters->all_day_instance_filter,
+                   s_all_day_instance_attribute_map[attr_name].property_id,
+                   int_match_flag, cal_time);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+         }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Status ect part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_VISIBILITY == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_STATUS == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_PRIORITY == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_PROGRESS == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_AVAILABILITY == attr_name) {
+        int value = 0;
+
+        if (CALENDAR_FILTER_ATTRIBUTE_PROGRESS == attr_name) {
+            value = match_value->toLong();
+        }
+        else {
+            value = convertStringToIntValue(attr_name, match_value->toString());
+        }
+
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            ret = calendar_filter_add_int(returned_filters->filter,
+                    s_task_attribute_map[attr_name].property_id,
+                    int_match_flag, value);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            calendarFilterAddInt(returned_filters->filter,
+                    returned_filters->normal_instance_filter,
+                    returned_filters->all_day_instance_filter,
+                    attr_name, int_match_flag, value);
+        }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //IP part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_ID_UID == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_ID == attr_name) {
+       int id;
+       std::stringstream ss(match_value->toString());
+       ss >> id;
+
+       if (CalendarUtility::CalendarType::TASK == m_type) {
+           ret = calendar_filter_add_int(returned_filters->filter,
+                  s_task_attribute_map[attr_name].property_id, int_match_flag, id);
+           if (ret != CALENDAR_ERROR_NONE) {
+               LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+           }
+       }
+       else {
+           calendarFilterAddInt(returned_filters->filter,
+                   returned_filters->normal_instance_filter,
+                   returned_filters->all_day_instance_filter,
+                   attr_name, int_match_flag, id);
+
+           // Include the detached events.
+           ret = calendar_filter_add_operator(returned_filters->filter,
+                   CALENDAR_FILTER_OPERATOR_OR);
+           if (ret != CALENDAR_ERROR_NONE) {
+               LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+           }
+           ret = calendar_filter_add_operator(returned_filters->normal_instance_filter,
+                   CALENDAR_FILTER_OPERATOR_OR);
+           if (ret != CALENDAR_ERROR_NONE) {
+               LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+           }
+           ret = calendar_filter_add_operator(returned_filters->all_day_instance_filter,
+                   CALENDAR_FILTER_OPERATOR_OR);
+           if (ret != CALENDAR_ERROR_NONE) {
+               LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+           }
+
+           calendarFilterAddInt(returned_filters->filter,
+                   returned_filters->normal_instance_filter,
+                   returned_filters->all_day_instance_filter,
+                   CALENDAR_FILTER_ATTRIBUTE_IS_DETACHED, CALENDAR_MATCH_EQUAL, id);
+       }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Date part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_LAST_MODIFIED_DATE == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_COMPLETED_DATE == attr_name) {
+        long long int time = getTimeTFromTZDateAny(match_value);
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            ret = calendar_filter_add_lli(returned_filters->filter,
+                    s_task_attribute_map[attr_name].property_id, int_match_flag, time);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            calendarFilterAddLLI(returned_filters->filter,
+                    returned_filters->normal_instance_filter,
+                    returned_filters->all_day_instance_filter,
+                    attr_name, int_match_flag, time);
+        }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //String part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_DESCRIPTION == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_SUMMARY == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_LOCATION == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_ORGANIZER == attr_name) {
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            ret = calendar_filter_add_str(returned_filters->filter,
+                    s_task_attribute_map[attr_name].property_id, str_match_flag,
+                    match_value->toString().c_str());
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            calendarFilterAddStr(returned_filters->filter,
+                    returned_filters->normal_instance_filter,
+                    returned_filters->all_day_instance_filter,
+                    attr_name, str_match_flag, match_value->toString());
+        }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Is all day part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_IS_ALL_DAY == attr_name) {
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            ret = calendar_filter_add_int(returned_filters->filter,
+                    s_task_attribute_map[attr_name].property_id, CALENDAR_MATCH_EQUAL,
+                    match_value->toBool() ? 1 : 0);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            ret = calendar_filter_add_int(returned_filters->filter,
+                    s_event_attribute_map[attr_name].property_id, CALENDAR_MATCH_EQUAL,
+                    match_value->toBool() ? 1 : 0);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            // Exclude the normal instance table.
+            ret = calendar_filter_add_int(returned_filters->normal_instance_filter,
+                    s_normal_instance_attribute_map[CALENDAR_FILTER_ATTRIBUTE_ID_UID].property_id,
+                    CALENDAR_MATCH_EQUAL, -999);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            // Exclude the allday instance table.
+            ret = calendar_filter_add_int(returned_filters->all_day_instance_filter,
+                    s_all_day_instance_attribute_map[CALENDAR_FILTER_ATTRIBUTE_ID_UID].property_id,
+                    CALENDAR_MATCH_EQUAL, -999);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Geaolocation part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_LATITUDE == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_LONGITUDE == attr_name) {
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            ret = calendar_filter_add_double(returned_filters->filter,
+                    s_task_attribute_map[attr_name].property_id, int_match_flag,
+                    match_value->toDouble());
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            calendarFilterAddDouble(returned_filters->filter,
+                    returned_filters->normal_instance_filter,
+                    returned_filters->all_day_instance_filter,
+                    attr_name, int_match_flag, match_value->toDouble());
+        }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Alarm and Attendees part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_ALARMS == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_ATTENDEES == attr_name) {
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            if (EXACTLY == match_flag) {
+                if (match_value->isNullOrUndefined()) {
+                    ret = calendar_filter_add_int(returned_filters->filter,
+                            s_task_attribute_map[attr_name].property_id,
+                            CALENDAR_MATCH_EQUAL, 0);
+                    if (ret != CALENDAR_ERROR_NONE) {
+                        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                    }
+                }
+                else {
+                    ret = calendar_filter_add_int(returned_filters->filter,
+                                s_task_attribute_map[attr_name].property_id,
+                                CALENDAR_MATCH_EQUAL, 1);
+                    if (ret != CALENDAR_ERROR_NONE) {
+                        LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                    }
+                }
+            }
+            else {
+                ret = calendar_filter_add_int(returned_filters->filter,
+                        s_task_attribute_map[attr_name].property_id,
+                        CALENDAR_MATCH_EQUAL, 1);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+        }
+        else {
+            int value = 1;
+            if (EXACTLY == match_flag && match_value->isNullOrUndefined()) {
+                value = 0;
+            }
+            calendarFilterAddInt(returned_filters->filter,
+                    returned_filters->normal_instance_filter,
+                    returned_filters->all_day_instance_filter,
+                    attr_name, CALENDAR_MATCH_EQUAL, value);
+        }
+        LOGD("Added int filter.");
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Categories part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_CATEGORIES == attr_name) {
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            ret = calendar_filter_add_str(returned_filters->filter,
+                   s_task_attribute_map[attr_name].property_id,
+                   CALENDAR_MATCH_CONTAINS, match_value->toString().c_str());
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            calendarFilterAddStr(returned_filters->filter,
+                    returned_filters->normal_instance_filter,
+                    returned_filters->all_day_instance_filter,
+                    attr_name, CALENDAR_MATCH_CONTAINS, match_value->toString());
+        }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //IS_DETACHED part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_IS_DETACHED == attr_name) {
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            LOGW("isDetached not supported for a task.");
+        }
+        else {
+            calendarFilterAddInt(returned_filters->filter,
+                    returned_filters->normal_instance_filter,
+                    returned_filters->all_day_instance_filter,
+                    attr_name, CALENDAR_MATCH_GREATER_THAN, 0);
+        }
+        LOGD("Added int filter for isDetached with value 0.");
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Recurence rule part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_RECURRENCE_RULE == attr_name) {
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            LOGW("rule not supported for a task.");
+        }
+        else {
+            calendar_match_int_flag_e match = CALENDAR_MATCH_GREATER_THAN;
+            if (EXACTLY == match_flag && match_value->isNullOrUndefined()) {
+                match = CALENDAR_MATCH_EQUAL;
+            }
+            calendarFilterAddInt(returned_filters->filter,
+                    returned_filters->normal_instance_filter,
+                    returned_filters->all_day_instance_filter,
+                    attr_name, match, 0);
+        }
+    }
+    else {
+        LOGW("Not supported filter attribute: ");
+    }
+    LOGD("Attribute visit done.");
+
+    FilterClass* return_filters = returned_filters.release();
+    return return_filters;
+}
+
+calendar_filter_shared_ptr CalendarItemSearchEngine::calendarRangeFilterSupport(
+        AnyPtr initial_value, AnyPtr end_value, unsigned int property_id,
+        calendar_time_s start_time, calendar_time_s end_time,
+        const char* view_uri, calendar_filter_h& filter)
+{
+    LOGD("Entered");
+
+    int ret = calendar_filter_create(view_uri, &filter);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "filter creation failed");
+    }
+
+    calendar_filter_shared_ptr filter_ptr(&filter, filterDeleter);
+    if (!initial_value->isNullOrUndefined()) {
+        ret = calendar_filter_add_caltime(*filter_ptr,
+                property_id, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL, start_time);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+    if (!initial_value->isNullOrUndefined() && !end_value->isNullOrUndefined()) {
+        ret = calendar_filter_add_operator(*filter_ptr,
+                CALENDAR_FILTER_OPERATOR_AND);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+    if (!end_value->isNullOrUndefined()) {
+        ret = calendar_filter_add_caltime(*filter_ptr,
+                property_id, CALENDAR_MATCH_LESS_THAN_OR_EQUAL, end_time);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+    return filter_ptr;
+}
+
+FilterClass* CalendarItemSearchEngine::applyAttributeRangeFilter(AttributeRangeFilterPtr filter)
+{
+    LOGD("Entered");
+    FilterClassPtr returned_filters(new FilterClass(m_type));
+
+    AnyPtr initial_value = filter->getInitialValue();
+    AnyPtr end_value = filter->getEndValue();
+    std::string attr_name = filter->getAttributeName();
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Date part
+    //////////////////////////////////////////////////////////////////////////////////////
+    int ret = CALENDAR_ERROR_NONE;
+    if (CALENDAR_FILTER_ATTRIBUTE_START_DATE==attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_DUE_DATE==attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_END_DATE==attr_name) {
+        calendar_time_s start_time = {CALENDAR_TIME_UTIME, {0}};
+        calendar_time_s end_time = {CALENDAR_TIME_UTIME, {0}};
+        calendar_time_s start_time_all_day = {CALENDAR_TIME_LOCALTIME, {0}};
+        calendar_time_s end_time_all_day = {CALENDAR_TIME_LOCALTIME, {0}};
+        if (!initial_value->isNullOrUndefined()) {
+            start_time.time.utime = getTimeTFromTZDateAny(initial_value);
+            start_time_all_day.time.date = CalendarUtility::LLIToCalTime(NULL,
+                    getTimeTFromTZDateAny(initial_value)).time.date;
+        }
+        if (!end_value->isNullOrUndefined()) {
+            end_time.time.utime = getTimeTFromTZDateAny(end_value);
+            end_time_all_day.time.date = CalendarUtility::LLIToCalTime(NULL,
+                    getTimeTFromTZDateAny(end_value)).time.date;
+        }
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            calendar_filter_h sub_filter = NULL;
+            ret = calendar_filter_create(_calendar_todo._uri, &sub_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Filter creation failed");
+            }
+            calendar_filter_h_ptr sub_filter_ptr(&sub_filter, filterDeleter);
+
+            calendar_filter_h sub_filter2 = NULL;
+            calendar_filter_shared_ptr sub_filter2_ptr = calendarRangeFilterSupport(
+                    initial_value, end_value, s_task_attribute_map[attr_name].property_id,
+                    start_time, end_time, _calendar_todo._uri, sub_filter2);
+
+            calendar_filter_h sub_filter3 = NULL;
+            calendar_filter_shared_ptr sub_filter3_ptr = calendarRangeFilterSupport(
+                    initial_value, end_value, s_task_attribute_map[attr_name].property_id,
+                    start_time_all_day, end_time_all_day, _calendar_todo._uri, sub_filter3);
+
+            ret = calendar_filter_add_filter(*sub_filter_ptr,
+                    *sub_filter2_ptr);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_add_operator(*sub_filter_ptr,
+                    CALENDAR_FILTER_OPERATOR_OR);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_add_filter(*sub_filter_ptr,
+                    *sub_filter3_ptr);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            sub_filter3_ptr.reset();
+
+            ret = calendar_filter_add_filter(returned_filters->filter,
+                    *sub_filter_ptr);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            calendar_filter_h sub_filter = NULL;
+            ret = calendar_filter_create(_calendar_event._uri, &sub_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGE("ret : %d", ret);
+                CalendarUtility::throwCalendarException(ret, "Filter creation failed");
+            }
+            calendar_filter_h_ptr sub_filter_ptr(&sub_filter, filterDeleter);
+
+            calendar_filter_h sub_filter2 = NULL;
+            calendar_filter_shared_ptr sub_filter2_ptr = calendarRangeFilterSupport(
+                    initial_value, end_value, s_event_attribute_map[attr_name].property_id,
+                    start_time, end_time, _calendar_event._uri, sub_filter2);
+
+            calendar_filter_h sub_filter3 = NULL;
+            calendar_filter_shared_ptr sub_filter3_ptr = calendarRangeFilterSupport(
+                    initial_value, end_value, s_event_attribute_map[attr_name].property_id,
+                    start_time_all_day, end_time_all_day,_calendar_event._uri, sub_filter3);
+
+            ret = calendar_filter_add_filter(*sub_filter_ptr,
+                    *sub_filter2_ptr);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            ret = calendar_filter_add_operator(*sub_filter_ptr,
+                    CALENDAR_FILTER_OPERATOR_OR);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            ret = calendar_filter_add_filter(*sub_filter_ptr,
+                    *sub_filter3_ptr);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            ret = calendar_filter_add_filter(returned_filters->filter,
+                    *sub_filter_ptr);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            LOGD("Query for normal instances");
+
+            calendar_filter_h sub_filter_normal = NULL;
+            calendar_filter_shared_ptr sub_filter_normal_ptr = calendarRangeFilterSupport(
+                    initial_value, end_value, s_normal_instance_attribute_map[attr_name].property_id,
+                    start_time, end_time, _calendar_instance_utime_calendar_book._uri,
+                    sub_filter_normal);
+            ret = calendar_filter_add_filter(returned_filters->normal_instance_filter,
+                    *sub_filter_normal_ptr);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            LOGD("Query for allday instances.");
+            calendar_filter_h sub_filter_all_day = NULL;
+            calendar_filter_shared_ptr sub_filter_all_day_ptr = calendarRangeFilterSupport(
+                    initial_value, end_value, s_all_day_instance_attribute_map[attr_name].property_id,
+                    start_time_all_day, end_time_all_day, _calendar_instance_localtime_calendar_book._uri,
+                    sub_filter_all_day);
+
+            ret = calendar_filter_add_filter(returned_filters->all_day_instance_filter,
+                    *sub_filter_all_day_ptr);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+
+            LOGD("Enable the instance table search.");
+            m_enable_instance_search = true;
+        }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Geolocation part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_LATITUDE == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_LONGITUDE == attr_name) {
+        if (CalendarUtility::CalendarType::TASK==m_type) {
+            if (!initial_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_double(returned_filters->filter,
+                        s_task_attribute_map[attr_name].property_id,
+                        CALENDAR_MATCH_GREATER_THAN_OR_EQUAL, initial_value->toDouble());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+            if (!initial_value->isNullOrUndefined() && !end_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_operator(returned_filters->filter,
+                        CALENDAR_FILTER_OPERATOR_AND);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+            if (!end_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_double(returned_filters->filter,
+                        s_task_attribute_map[attr_name].property_id,
+                        CALENDAR_MATCH_LESS_THAN_OR_EQUAL, end_value->toDouble());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+        }
+        else {
+            if (!initial_value->isNullOrUndefined()) {
+                calendarFilterAddDouble(returned_filters->filter,
+                        returned_filters->normal_instance_filter,
+                        returned_filters->all_day_instance_filter,
+                        attr_name,CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+                        initial_value->toDouble());
+            }
+            if (!initial_value->isNullOrUndefined() && !end_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_operator(returned_filters->filter,
+                        CALENDAR_FILTER_OPERATOR_AND);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                ret = calendar_filter_add_operator(returned_filters->normal_instance_filter,
+                        CALENDAR_FILTER_OPERATOR_AND);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                ret = calendar_filter_add_operator(returned_filters->all_day_instance_filter,
+                        CALENDAR_FILTER_OPERATOR_AND);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+            if (!end_value->isNullOrUndefined()) {
+                calendarFilterAddDouble(returned_filters->filter,
+                        returned_filters->normal_instance_filter,
+                        returned_filters->all_day_instance_filter,
+                        attr_name, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+                        end_value->toDouble());
+            }
+        }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Date part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_LAST_MODIFIED_DATE == attr_name
+           || CALENDAR_FILTER_ATTRIBUTE_COMPLETED_DATE == attr_name) {
+        if (CalendarUtility::CalendarType::TASK==m_type) {
+            if (!initial_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_lli(returned_filters->filter,
+                        s_task_attribute_map[attr_name].property_id,
+                        CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+                        getTimeTFromTZDateAny(initial_value));
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+            if (!initial_value->isNullOrUndefined() && !end_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_operator(returned_filters->filter,
+                        CALENDAR_FILTER_OPERATOR_AND);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+            if (!end_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_lli(returned_filters->filter,
+                        s_task_attribute_map[attr_name].property_id,
+                        CALENDAR_MATCH_LESS_THAN_OR_EQUAL, getTimeTFromTZDateAny(end_value));
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+        }
+        else {
+            if (!initial_value->isNullOrUndefined()) {
+                calendarFilterAddLLI(returned_filters->filter,
+                        returned_filters->normal_instance_filter,
+                        returned_filters->all_day_instance_filter,
+                        attr_name, CALENDAR_MATCH_GREATER_THAN_OR_EQUAL,
+                        getTimeTFromTZDateAny(initial_value));
+            }
+            if (!initial_value->isNullOrUndefined() && !end_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_operator(returned_filters->filter,
+                        CALENDAR_FILTER_OPERATOR_AND);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                ret = calendar_filter_add_operator(returned_filters->normal_instance_filter,
+                        CALENDAR_FILTER_OPERATOR_AND);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                ret = calendar_filter_add_operator(returned_filters->all_day_instance_filter,
+                        CALENDAR_FILTER_OPERATOR_AND);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+            if (!end_value->isNullOrUndefined()) {
+                calendarFilterAddLLI(returned_filters->filter,
+                        returned_filters->normal_instance_filter,
+                        returned_filters->all_day_instance_filter,
+                        attr_name, CALENDAR_MATCH_LESS_THAN_OR_EQUAL,
+                        getTimeTFromTZDateAny(end_value));
+            }
+        }
+    }
+    //////////////////////////////////////////////////////////////////////////////////////
+    //Progres part
+    //////////////////////////////////////////////////////////////////////////////////////
+    else if (CALENDAR_FILTER_ATTRIBUTE_PROGRESS == attr_name) {
+        if (CalendarUtility::CalendarType::TASK == m_type) {
+            if (!initial_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_int(returned_filters->filter,
+                        s_task_attribute_map[attr_name].property_id,
+                        CALENDAR_MATCH_GREATER_THAN_OR_EQUAL, initial_value->toLong());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+
+            }
+            if (!initial_value->isNullOrUndefined() && !end_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_operator(returned_filters->filter,
+                        CALENDAR_FILTER_OPERATOR_AND);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+            if (!end_value->isNullOrUndefined()) {
+                ret = calendar_filter_add_int(returned_filters->filter,
+                        s_task_attribute_map[attr_name].property_id,
+                        CALENDAR_MATCH_LESS_THAN_OR_EQUAL, end_value->toLong());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+        }
+        else {
+            LOGW("progress not supported for an event");
+        }
+    }
+    else {
+        LOGW("Not supported filter attribute");
+    }
+    LOGD("Attribute range visit done.");
+
+    FilterClass* return_filters = returned_filters.release();
+    return return_filters;
+}
+
+FilterClass* CalendarItemSearchEngine::applyCompositeFilter(CompositeFilterPtr filter)
+{
+    LOGD("Entered");
+    int ret;
+    FilterClassPtr all_returned_filters(new FilterClass(m_type));
+
+    auto filters = filter->getFilters();
+    CompositeFilterType type = filter->getType();
+
+    const size_t filter_count = filters.size();
+    for (size_t i = 0; i < filter_count; i++) {
+        FilterClassPtr returned_filter;
+        switch (filters[i]->getFilterType()) {
+            case ATTRIBUTE_FILTER: {
+                AttributeFilterPtr attribute_filter =
+                        std::dynamic_pointer_cast<AttributeFilter>(filters[i]);
+                if (!attribute_filter) {
+                    LOGE("Could not cast AbstractFilterPtr to AttributeFilterPtr");
+                    throw UnknownException("Wrong filter type");
+                }
+                returned_filter.reset(applyAttributeFilter(attribute_filter));
+                break;
+            }
+            case ATTRIBUTE_RANGE_FILTER: {
+                AttributeRangeFilterPtr attribute_range_filter =
+                        std::dynamic_pointer_cast<AttributeRangeFilter>(filters[i]);
+                if (!attribute_range_filter) {
+                    LOGE("Could not cast AbstractFilterPtr to AttributeRangeFilterPtr");
+                    throw UnknownException("Wrong filter type");
+                }
+                returned_filter.reset(applyAttributeRangeFilter(attribute_range_filter));
+                break;
+            }
+            case COMPOSITE_FILTER: {
+                CompositeFilterPtr composite_filter =
+                        std::dynamic_pointer_cast<CompositeFilter>(filters[i]);
+                if (!composite_filter) {
+                    LOGE("Could not cast AbstractFilterPtr to CompositeFilterPtr");
+                    throw UnknownException("Wrong filter type");
+                }
+                returned_filter.reset(applyCompositeFilter(composite_filter));
+                break;
+            }
+            default:
+                LOGE("Wrong filter type");
+                throw UnknownException("Wrong filter type");
+        }
+
+        ret = calendar_filter_add_filter(all_returned_filters->filter,
+                returned_filter->filter);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        if (CalendarUtility::CalendarType::EVENT == m_type) {
+            ret = calendar_filter_add_filter(all_returned_filters->normal_instance_filter,
+                    returned_filter->normal_instance_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_add_filter(all_returned_filters->all_day_instance_filter,
+                    returned_filter->all_day_instance_filter);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+
+        calendar_filter_operator_e filter_operator = CALENDAR_FILTER_OPERATOR_AND;
+        if (UNION == type) {
+            filter_operator = CALENDAR_FILTER_OPERATOR_OR;
+        }
+
+        ret = calendar_filter_add_operator(all_returned_filters->filter, filter_operator);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        if (CalendarUtility::CalendarType::EVENT == m_type) {
+            ret = calendar_filter_add_operator(all_returned_filters->normal_instance_filter, filter_operator);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+            ret = calendar_filter_add_operator(all_returned_filters->all_day_instance_filter, filter_operator);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Filter add failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+    }
+
+    FilterClass* all_return_filters = all_returned_filters.release();
+    return all_return_filters;
+}
+
+int CalendarItemSearchEngine::convertStringToIntValue(const std::string &attr_name,
+        const std::string &value_string)
+{
+    LOGD("Entered");
+    if (attr_name == CALENDAR_FILTER_ATTRIBUTE_VISIBILITY) {
+        if (TYPE_PUBLIC_VISIBILITY == value_string) {
+            return CALENDAR_SENSITIVITY_PUBLIC;
+        }
+        else if (TYPE_PRIVATE_VISIBILITY == value_string) {
+            return CALENDAR_SENSITIVITY_PRIVATE;
+        }
+        else if (TYPE_CONFIDENTIAL_VISIBILITY == value_string) {
+            return CALENDAR_SENSITIVITY_CONFIDENTIAL;
+        }
+        else {
+            LOGW("Wrong visibility value.");
+        }
+    }
+    else if (CALENDAR_FILTER_ATTRIBUTE_STATUS == attr_name) {
+        if (TYPE_TENTATIVE_STATUS == value_string) {
+            return CALENDAR_EVENT_STATUS_TENTATIVE;
+        }
+        else if (TYPE_CONFIRMED_STATUS == value_string) {
+            return CALENDAR_EVENT_STATUS_CONFIRMED;
+        }
+        else if (TYPE_CANCELLED_STATUS == value_string) {
+            if (CalendarUtility::CalendarType::TASK == m_type) {
+                return CALENDAR_TODO_STATUS_CANCELED;
+            }
+            else {
+                return CALENDAR_EVENT_STATUS_CANCELLED;
+            }
+        }
+        else if (TYPE_NEEDS_ACTION_STATUS == value_string) {
+            return CALENDAR_TODO_STATUS_NEEDS_ACTION;
+        }
+        else if (TYPE_IN_PROCESS_STATUS == value_string) {
+            return CALENDAR_TODO_STATUS_IN_PROCESS;
+        }
+        else if (TYPE_COMPLETED_STATUS == value_string) {
+            return CALENDAR_TODO_STATUS_COMPLETED;
+        }
+        else {
+            LOGW("Wrong status value.");
+        }
+    }
+    else if (CALENDAR_FILTER_ATTRIBUTE_PRIORITY == attr_name) {
+        if (TYPE_HIGH_PRIORITY == value_string) {
+            return CALENDAR_EVENT_PRIORITY_HIGH;
+        }
+        else if (TYPE_MEDIUM_PRIORITY == value_string) {
+            return CALENDAR_EVENT_PRIORITY_NORMAL;
+        }
+        else if (TYPE_LOW_PRIORITY == value_string) {
+            return CALENDAR_EVENT_PRIORITY_LOW;
+        }
+        else {
+            LOGW("Wrong priority value.");
+        }
+    }
+    else if (CALENDAR_FILTER_ATTRIBUTE_AVAILABILITY == attr_name) {
+        if (AVAILABILITY_BUSY == value_string) {
+            return CALENDAR_EVENT_BUSY_STATUS_BUSY;
+        }
+        else if (AVAILABILITY_FREE == value_string) {
+            return CALENDAR_EVENT_BUSY_STATUS_FREE;
+        }
+        else {
+            LOGW("Wrong availability value.");
+        }
+    }
+    else {
+        LOGW("Invalid Attribute Name");
+    }
+
+    return -1;
+}
+
+long long int CalendarItemSearchEngine::getTimeTFromTZDateAny(AnyPtr any) const
+{
+    LOGD("Entered");
+    Time::TZDatePtr date_ptr = Time::JSTZDate::getPrivateObject(any->getContext(),
+            any->getValue());
+    return CalendarUtility::localTimeToUTCTime(date_ptr);
+}
+
+} //Calendar
+} //DeviceAPI
diff --git a/src/Calendar/CalendarItemSearchEngine.h b/src/Calendar/CalendarItemSearchEngine.h
new file mode 100755 (executable)
index 0000000..5c08d0e
--- /dev/null
@@ -0,0 +1,141 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _CALENDAR_FILTER_H_
+#define _CALENDAR_FILTER_H_
+
+#include <map>
+#include <string>
+#include <calendar.h>
+#include "CalendarItem.h"
+
+#include <Any.h>
+#include <SortMode.h>
+#include <AbstractFilter.h>
+#include <AttributeFilter.h>
+#include <AttributeRangeFilter.h>
+#include <CompositeFilter.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+using namespace Tizen;
+
+class FilterClass;
+typedef std::unique_ptr<FilterClass> FilterClassPtr;
+
+class FilterClass{
+public:
+    CalendarUtility::CalendarType type;
+    calendar_filter_h filter;
+    calendar_filter_h normal_instance_filter;
+    calendar_filter_h all_day_instance_filter;
+
+    FilterClass(CalendarUtility::CalendarType type_arg);
+    ~FilterClass();
+private:
+    FilterClass(const FilterClass& filters) {};
+    FilterClass & operator =(const FilterClass& filters);
+};
+
+class CalendarItemSearchEngine {
+public:
+    CalendarItemSearchEngine(CalendarUtility::CalendarType type);
+    virtual ~CalendarItemSearchEngine();
+
+    CalendarUtility::CalendarType getType() const;
+
+    void setCalendarId(int calendar_id, bool is_filter_set);
+
+    void applySortMode(SortModePtr sort_mode);
+    void applyFilter(AbstractFilterPtr filter);
+
+    std::shared_ptr<CalendarItemPtrVector> find();
+private:
+    CalendarItemSearchEngine() {};
+    CalendarItemSearchEngine(const CalendarItemSearchEngine& engine) {};
+    CalendarItemSearchEngine & operator =( const CalendarItemSearchEngine& engine);
+
+    void findSupport(calendar_query_h query,calendar_filter_h filter,
+            unsigned int property_id, std::shared_ptr<CalendarItemPtrVector> items_vector);
+
+    void calendarFilterAddInt(calendar_filter_h filter,
+            calendar_filter_h normal_instance_filter,
+            calendar_filter_h all_day_instance_filter,
+            const std::string& attr_name,
+            calendar_match_int_flag_e match, int value);
+
+    void calendarFilterAddLLI(calendar_filter_h filter,
+            calendar_filter_h normal_instance_filter,
+            calendar_filter_h all_day_instance_filter,
+            const std::string& attr_name,
+            calendar_match_int_flag_e match, long long int value);
+
+    void calendarFilterAddDouble(calendar_filter_h filter,
+            calendar_filter_h normal_instance_filter,
+            calendar_filter_h all_day_instance_filter,
+            const std::string& attr_name,
+            calendar_match_int_flag_e match, double value);
+
+    void calendarFilterAddStr(calendar_filter_h filter,
+            calendar_filter_h normal_instance_filter,
+            calendar_filter_h all_day_instance_filter,
+            const std::string& attr_name,
+            calendar_match_str_flag_e match, const std::string& value);
+
+    calendar_filter_shared_ptr calendarRangeFilterSupport(
+            AnyPtr initial_value, AnyPtr end_value, unsigned int property_id,
+            calendar_time_s start_time, calendar_time_s end_time,
+            const char* view_uri, calendar_filter_h& filter);
+
+    CalendarUtility::CalendarType m_type;
+
+    calendar_query_h m_query;
+    calendar_filter_h m_filter;
+
+    // Additional filters for recurring event range filter.
+    calendar_query_h m_normal_instance_query;
+    calendar_filter_h m_normal_instance_filter;
+
+    calendar_query_h m_all_day_instance_query;
+    calendar_filter_h m_all_day_instance_filter;
+
+    bool m_enable_instance_search;
+
+    struct FilterPropertyStruct {
+        const unsigned int property_id;
+        const PrimitiveType type;
+    };
+
+    static std::map<std::string, FilterPropertyStruct> s_event_attribute_map;
+    static std::map<std::string, FilterPropertyStruct> s_normal_instance_attribute_map;
+    static std::map<std::string, FilterPropertyStruct> s_all_day_instance_attribute_map;
+    static std::map<std::string, FilterPropertyStruct> s_task_attribute_map;
+
+    FilterClass* applyAttributeFilter(AttributeFilterPtr filter);
+    FilterClass* applyAttributeRangeFilter(AttributeRangeFilterPtr filter);
+    FilterClass* applyCompositeFilter(CompositeFilterPtr filter);
+
+    int convertStringToIntValue(const std::string &attr_name, const std::string &value_string);
+    long long int getTimeTFromTZDateAny(AnyPtr any) const;
+};
+
+} //Calendar
+} //DeviceAPI
+
+#endif /* _CALENDAR_FILTER_H_ */
diff --git a/src/Calendar/CalendarManager.cpp b/src/Calendar/CalendarManager.cpp
new file mode 100755 (executable)
index 0000000..6cc8469
--- /dev/null
@@ -0,0 +1,515 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+#include <memory>
+#include <Logger.h>
+#include <Export.h>
+#include <calendar_types.h>
+
+#include "Calendar.h"
+#include "JSCalendar.h"
+#include "CalendarManager.h"
+#include "CalendarUtility.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+using namespace Common;
+
+namespace {
+const char* UNIFIED_CALENDAR_NAME = "";
+}
+
+CalendarManagerCallbackUserData::CalendarManagerCallbackUserData(
+        JSContextRef globalCtx,
+        CalendarUtility::CalendarType type) :
+        CallbackUserData(globalCtx),
+        m_type(type),
+        m_is_error(false),
+        m_err_name(""),
+        m_err_message("")
+{
+}
+
+CalendarUtility::CalendarType CalendarManagerCallbackUserData::getType()
+{
+    return m_type;
+}
+
+
+const std::vector<CalendarPtr>& CalendarManagerCallbackUserData::getFoundCalendars() const
+{
+    return m_found_calendars;
+}
+
+void CalendarManagerCallbackUserData::setFoundCalendars(
+        const std::vector<CalendarPtr> &calendars)
+{
+    m_found_calendars = calendars;
+}
+
+void CalendarManagerCallbackUserData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool CalendarManagerCallbackUserData::isError() const
+{
+    return m_is_error;
+}
+
+const std::string& CalendarManagerCallbackUserData::getErrorName() const
+{
+    return m_err_name;
+}
+
+const std::string& CalendarManagerCallbackUserData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void CalendarRecordDeleter(calendar_record_h &rec) {
+    int ret = calendar_record_destroy(rec, true);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_destroy()");
+    }
+    rec = NULL;
+}
+
+CalendarManager::CalendarManager():
+        SecurityAccessor()
+{
+    LOGD("Connect to the calendar DB.");
+    int ret = calendar_connect();
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_connect()");
+    }
+}
+
+CalendarManager::~CalendarManager() {
+    LOGD("Disconnect calendar DB.");
+    int ret = calendar_disconnect();
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_disconnect()");
+    }
+}
+
+CalendarManager&  CalendarManager::getInstance() {
+    static CalendarManager instance;
+    return instance;
+}
+
+static gboolean getCalendarsCompleted(void *data) {
+    LOGD("Entered");
+
+    auto callback = static_cast<CalendarManagerCallbackUserData*>(data);
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+    JSContextRef context = callback->getContext();
+    auto calendars = callback->getFoundCalendars();
+    const size_t size = calendars.size();
+
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            JSValueRef exception = NULL;
+            JSObjectRef js_calendars[size];
+
+            for (unsigned int i = 0; i < size; i++) {
+                js_calendars[i] = JSCalendar::makeJSObject(context, calendars.at(i));
+                if (NULL == js_calendars[i]) {
+                    LOGE("Calendar object creation failed");
+                    throw Common::UnknownException("Calendar object creation failed");
+                }
+            }
+
+            JSObjectRef result = JSObjectMakeArray(context,
+                    size, size > 0 ? js_calendars : NULL, &exception);
+            if (exception != NULL) {
+                throw UnknownException("JSObjectMakeArray failed");
+            }
+            callback->callSuccessCallback(result);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context, err);
+        callback->callErrorCallback(errobj);
+    }
+    catch (...) {
+        LOGE("getCalendars failed");
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown Error");
+        callback->callErrorCallback(errobj);
+    }
+
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+static void* getCalendarsThread(void *data)
+{
+    LOGD("getCalendarsThread started");
+    CalendarManagerCallbackUserData* callback = static_cast<CalendarManagerCallbackUserData*>(data);
+    if (NULL == callback) {
+          LOGE("Callback is null");
+          return NULL;
+    }
+
+    calendar_list_h list = NULL;
+
+    try {
+        if (NULL == callback) {
+            LOGE("Callback is null");
+            throw UnknownException("Callback is null");
+        }
+
+        int ret = calendar_db_get_all_records(_calendar_book._uri, 0, 0, &list);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "calendar_db_get_all_records()");
+     }
+
+        int count = 0;
+        ret = calendar_list_get_count(list, &count);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "calendar_list_get_count()");
+        } else {
+            LOGD("Calendar list count: %d", count);
+        }
+
+        ret = calendar_list_first(list);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "calendar_list_first()");
+        }
+
+
+
+        std::vector<CalendarPtr> calendars_vector;
+        calendars_vector.reserve(count);
+
+        int current_calendar_type = 0;
+        if (CalendarUtility::CalendarType::EVENT == callback->getType()) {
+            current_calendar_type = CALENDAR_BOOK_TYPE_EVENT;
+        }  else if (CalendarUtility::CalendarType::TASK == callback->getType()) {
+            current_calendar_type = CALENDAR_BOOK_TYPE_TODO;
+        }
+
+        calendar_record_h calendar = NULL;
+        char* name = NULL;
+        int id, account_id, store_type;
+
+        while (count-- > 0)
+        {
+            ret = calendar_list_get_current_record_p(list, &calendar);
+            if (ret != CALENDAR_ERROR_NONE) {
+                 LOGE("ret : %d", ret);
+                 CalendarUtility::throwCalendarException(ret, "calendar_list_get_current_record_p()");
+            }
+
+            ret = calendar_record_get_str(calendar, _calendar_book.name, &name);
+            if (ret != CALENDAR_ERROR_NONE) {
+                 LOGE("ret : %d", ret);
+                 CalendarUtility::throwCalendarException(ret, "calendar_record_get_str()");
+            }
+            if (name != NULL) {
+
+                    ret = calendar_record_get_int(calendar, _calendar_book.store_type, &store_type);
+                    if (ret != CALENDAR_ERROR_NONE) {
+                        LOGE("ret : %d", ret);
+                        CalendarUtility::throwCalendarException(ret, "calendar_record_get_int()");
+                    }
+                    if (current_calendar_type == store_type) {
+
+                    ret = calendar_record_get_int(calendar, _calendar_book.id, &id);
+                    if (ret != CALENDAR_ERROR_NONE) {
+                        LOGE("ret : %d", ret);
+                        CalendarUtility::throwCalendarException(ret, "calendar_record_get_int()");
+                    }
+
+                    ret = calendar_record_get_int(calendar, _calendar_book.account_id, &account_id);
+                    if (ret != CALENDAR_ERROR_NONE) {
+                        LOGE("ret : %d", ret);
+                        CalendarUtility::throwCalendarException(ret, "calendar_record_get_int()");
+                    }
+
+                    LOGD("Got calendar, id: %d, name: %s, account id: %d, storeType: %d", id, name, account_id, store_type);
+
+                    CalendarPtr new_calendar_ptr = CalendarPtr(new Calendar());
+                    new_calendar_ptr->setId(id);
+                    new_calendar_ptr->setType(callback->getType());
+                    new_calendar_ptr->setName(name);
+                    new_calendar_ptr->setAccountId(account_id);
+
+                    calendars_vector.push_back(new_calendar_ptr);
+                }
+
+                free(name);
+                name = NULL;
+            }
+
+            calendar_list_next(list);
+        }
+
+        if (list) {
+            calendar_list_destroy(list, true);
+        }
+
+        callback->setFoundCalendars(calendars_vector);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getCalendarsCallback fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+        if (list) {
+            calendar_list_destroy(list, 0);
+        }
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch (...) {
+        LOGE("getCalendarsCallback fails");
+        if (list) {
+            calendar_list_destroy(list, 0);
+        }
+        callback->setError("UnknownError", "getCalendars failed");
+    }
+
+    if (0 == g_idle_add(getCalendarsCompleted, data)) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+void CalendarManager::getCalendars(CalendarManagerCallbackUserData* callback) {
+
+    LOGD("Enter");
+    if (NULL == callback) {
+        throw UnknownException("NULL cbdata error.");
+    }
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, getCalendarsThread, static_cast<void*>(callback))) {
+        LOGE("Failed to create pthread for getCalendars()");
+        delete callback;
+        callback = NULL;
+        throw UnknownException("pthread_create error.");
+    }
+    if (pthread_detach(thread)) {
+        LOGW("Failed to detach the pthread for getCalendars()");
+    }
+}
+
+CalendarPtr CalendarManager::getUnifiedCalendar(CalendarUtility::CalendarType type) {
+    LOGD("Entered");
+
+    CalendarPtr calendar;
+    try {
+        calendar = CalendarPtr(new Calendar());
+    }
+    catch (const std::bad_alloc &err) {
+        LOGE("Memory allocation error, msg: %s", err.what());
+        throw UnknownException("Memory allocation error");
+    }
+
+    calendar->setId(CalendarManager::UNIFIED_CALENDAR_ID);
+    calendar->setName(UNIFIED_CALENDAR_NAME);
+    calendar->setType(type);
+
+    return calendar;
+}
+
+CalendarPtr CalendarManager::getDefaultCalendar(CalendarUtility::CalendarType type) {
+
+    if (CalendarUtility::CalendarType::EVENT == type) {
+        return getCalendar(type, DEFAULT_EVENT_CALENDAR_BOOK_ID);
+    }
+    if (CalendarUtility::CalendarType::TASK == type) {
+        return getCalendar(type, DEFAULT_TODO_CALENDAR_BOOK_ID);
+    }
+    LOGE("Invalid calendar type");
+    throw TypeMismatchException("Invalid calendar type");
+}
+
+void CalendarManager::addCalendar(CalendarPtr calendar) {
+    calendar_record_h calendar_record;
+    int ret = calendar_record_create(_calendar_book._uri, &calendar_record);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_create()");
+    }
+
+    ret = calendar_record_set_str(calendar_record, _calendar_book.name,
+        calendar->getName().c_str());
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_set_str()");
+    }
+
+    ret = calendar_record_set_int(calendar_record, _calendar_book.account_id,
+        static_cast<int>(calendar->getAccountId()));
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_set_int()");
+    }
+
+    ret = calendar_record_set_int(calendar_record, _calendar_book.store_type,
+            calendar->getType());
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_set_int()");
+    }
+
+    int record_id;
+    ret = calendar_db_insert_record(calendar_record, &record_id);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_db_insert_record()");
+    }
+
+    calendar->setId(static_cast<long>(record_id));
+    CalendarRecordDeleter(calendar_record);
+}
+
+void CalendarManager::removeCalendar(CalendarUtility::CalendarType type, long calendar_id) {
+    CalendarPtr calendar = getCalendar(type, calendar_id);
+
+    if (calendar_id == UNIFIED_CALENDAR_ID) {
+        LOGE("Unified calendar can not be deleted");
+        throw InvalidValuesException("Unified calendar can not be deleted");
+    } else if (calendar_id == DEFAULT_EVENT_CALENDAR_BOOK_ID) {
+        LOGE("Default event calendar can not be deleted");
+        throw InvalidValuesException("Default event calendar can not be deleted");
+    } else if (calendar_id == DEFAULT_TODO_CALENDAR_BOOK_ID) {
+        LOGE("Default todo calendar can not be deleted");
+        throw InvalidValuesException("Default todo calendar can not be deleted");
+    }
+
+    int ret = calendar_db_delete_record(_calendar_book._uri, calendar_id);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_db_delete_record()");
+    }
+}
+
+CalendarPtr CalendarManager::getCalendar(CalendarUtility::CalendarType type, long calendar_id) {
+
+    calendar_record_h calendar_record;
+    int ret = calendar_db_get_record(_calendar_book._uri, calendar_id, &calendar_record);
+    if (ret != CALENDAR_ERROR_NONE || NULL == calendar_record) {
+        LOGE("ret: %d", ret);
+        CalendarUtility::throwCalendarException<NotFoundException>(ret, "calendar_db_get_record");
+    }
+
+    int calendar_type = CalendarUtility::CalendarType::UNDEFINED;
+    ret = calendar_record_get_int(calendar_record, _calendar_book.store_type,
+            &calendar_type);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_get_int()");
+    }
+
+
+    if (type != calendar_type) {
+        CalendarRecordDeleter(calendar_record);
+        LOGE("Fail to get calendar record with specific type, error code: %d", ret);
+        throw NotFoundException("Fail to get calendar record with specific type");
+    }
+
+    char* calendarName = NULL;
+    int id, accountId;
+
+    ret = calendar_record_get_str(calendar_record, _calendar_book.name, &calendarName);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        free(calendarName);
+        calendarName = NULL;
+        CalendarRecordDeleter(calendar_record);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_get_str()");
+    }
+
+    ret = calendar_record_get_int(calendar_record, _calendar_book.id, &id);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        free(calendarName);
+        calendarName = NULL;
+        CalendarRecordDeleter(calendar_record);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_get_int()");
+    }
+
+    ret = calendar_record_get_int(calendar_record, _calendar_book.account_id, &accountId);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        free(calendarName);
+        calendarName = NULL;
+        CalendarRecordDeleter(calendar_record);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_get_int()");
+    }
+
+    CalendarPtr calendar;
+    try {
+        calendar = CalendarPtr(new Calendar());
+    }
+    catch (const std::bad_alloc &err) {
+        LOGE("Memory allocation error, msg: %s", err.what());
+        free(calendarName);
+        calendarName = NULL;
+        CalendarRecordDeleter(calendar_record);
+        throw UnknownException("Memory allocation error");
+    }
+    calendar->setId(id);
+    calendar->setName(calendarName);
+    calendar->setType(type);
+    calendar->setAccountId(accountId);
+
+    CalendarRecordDeleter(calendar_record);
+
+    free(calendarName);
+    calendarName = NULL;
+
+    return calendar;
+}
+
+}// namespace Calendar
+}//namespace DeviceAPI
diff --git a/src/Calendar/CalendarManager.h b/src/Calendar/CalendarManager.h
new file mode 100644 (file)
index 0000000..62cabca
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+/*
+ * @file CalendarManager.h
+ *
+ *  Created on: Aug 13, 2013
+ * @autor  Radoslaw Czerski
+ */
+
+#ifndef CALENDARMANAGER_H_
+#define CALENDARMANAGER_H_
+
+#include <string>
+#include <vector>
+#include "CalendarEventId.h"
+#include "Calendar.h"
+#include "CalendarUtility.h"
+#include <CallbackUserData.h>
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class CalendarManager;
+typedef std::shared_ptr<CalendarManager> CalendarManagerPtr;
+
+class CalendarManagerCallbackUserData: public Common::CallbackUserData {
+public:
+    CalendarManagerCallbackUserData(JSContextRef globalCtx,
+            CalendarUtility::CalendarType type);
+
+    CalendarUtility::CalendarType getType();
+
+    const std::vector<CalendarPtr>& getFoundCalendars() const;
+    void setFoundCalendars(const std::vector<CalendarPtr> &calendars);
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    const std::string& getErrorName() const;
+    const std::string& getErrorMessage() const;
+
+private:
+    CalendarUtility::CalendarType m_type;
+
+    std::vector<CalendarPtr> m_found_calendars;
+
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+};
+
+
+class CalendarManager : public Common::SecurityAccessor {
+public:
+
+    static const long UNIFIED_CALENDAR_ID = 0;
+
+    static CalendarManager& getInstance();
+    ~CalendarManager();
+
+    void getCalendars(CalendarManagerCallbackUserData* callback);
+    CalendarPtr getUnifiedCalendar(CalendarUtility::CalendarType type);
+    CalendarPtr getDefaultCalendar(CalendarUtility::CalendarType type);
+    CalendarPtr getCalendar(CalendarUtility::CalendarType type, long calendar_id);
+    void addCalendar(CalendarPtr calendar);
+    void removeCalendar(CalendarUtility::CalendarType type, long calendar_id);
+
+private:
+    CalendarManager();
+    CalendarManager(const CalendarManager&);
+    CalendarManager& operator=(const CalendarManager&);
+};
+
+}
+}
+
+#endif /* CALENDARMANAGER_H_ */
diff --git a/src/Calendar/CalendarRecurrenceRule.cpp b/src/Calendar/CalendarRecurrenceRule.cpp
new file mode 100755 (executable)
index 0000000..8735dc8
--- /dev/null
@@ -0,0 +1,273 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CalendarRecurrenceRule.h"
+#include "CalendarUtility.h"
+#include <PlatformException.h>
+#include <Logger.h>
+#include <algorithm>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+namespace {
+const std::string DAILY = "DAILY";
+const std::string WEEKLY = "WEEKLY";
+const std::string MONTHLY = "MONTHLY";
+const std::string YEARLY = "YEARLY";
+
+const std::string MONDAY = "MO";
+const std::string TUESDAY = "TU";
+const std::string WEDNESDAY = "WE";
+const std::string THURSDAY = "TH";
+const std::string FRIDAY = "FR";
+const std::string SATURDAY = "SA";
+const std::string SUNDAY = "SU";
+}
+
+CalendarRecurrenceRule::CalendarRecurrenceRule() :
+        m_is_until_date_set(false),
+        m_frequency(RecurrenceRuleFrequency::NO_FREQUENCY),
+        m_interval(1),
+        m_time_zone(""),
+        m_untilDate(-1),
+        m_occurrenceCount(-1)
+{
+    LOGD("Entered");
+}
+
+CalendarRecurrenceRule::CalendarRecurrenceRule(const CalendarRecurrenceRule&
+        calendar_recurence_rule):
+        m_is_until_date_set(calendar_recurence_rule.m_is_until_date_set),
+        m_frequency(calendar_recurence_rule.m_frequency),
+        m_interval(calendar_recurence_rule.m_interval),
+        m_time_zone(calendar_recurence_rule.m_time_zone),
+        m_untilDate(calendar_recurence_rule.m_untilDate),
+        m_occurrenceCount(calendar_recurence_rule.m_occurrenceCount),
+        m_daysOfTheWeek(calendar_recurence_rule.m_daysOfTheWeek),
+        m_setPositions(calendar_recurence_rule.m_setPositions),
+        m_exceptions(CalendarUtility::cloneVector<TZDatePtr, TZDate>(
+            calendar_recurence_rule.m_exceptions))
+{
+    LOGD("Entered");
+}
+
+CalendarRecurrenceRule::~CalendarRecurrenceRule()
+{
+}
+
+const std::string& CalendarRecurrenceRule::getTimezone()
+{
+    return m_time_zone;
+}
+void CalendarRecurrenceRule::setTimezone(const std::string& time_zone)
+{
+    m_time_zone = time_zone;
+}
+
+bool CalendarRecurrenceRule::isUntilDateSet() const
+{
+    return m_is_until_date_set;
+}
+
+CalendarRecurrenceRule::RecurrenceRuleFrequency CalendarRecurrenceRule::getFrequency() const
+{
+    return m_frequency;
+}
+
+void CalendarRecurrenceRule::setFrequency(
+        const CalendarRecurrenceRule::RecurrenceRuleFrequency value)
+{
+    m_frequency = value;
+}
+
+int CalendarRecurrenceRule::getInterval() const
+{
+    return m_interval;
+}
+
+void CalendarRecurrenceRule::setInterval(int value)
+{
+    m_interval = value;
+}
+
+long long int CalendarRecurrenceRule::getUntilDate() const
+{
+    return m_untilDate;
+}
+
+void CalendarRecurrenceRule::setUntilDate(long long int value)
+{
+    m_untilDate = value;
+    m_is_until_date_set = true;
+}
+
+void CalendarRecurrenceRule::unsetUntilDate()
+{
+    m_is_until_date_set = false;
+}
+
+long CalendarRecurrenceRule::getOccurrenceCount() const
+{
+    return m_occurrenceCount;
+}
+
+void CalendarRecurrenceRule::setOccurrenceCount(long value)
+{
+    m_occurrenceCount = value;
+}
+
+std::vector<CalendarRecurrenceRule::RecurrenceRuleByDayValue>
+        CalendarRecurrenceRule::getDaysOfTheWeek() const
+{
+    return m_daysOfTheWeek;
+}
+
+void CalendarRecurrenceRule::setDaysOfTheWeek(
+        const std::vector<CalendarRecurrenceRule::RecurrenceRuleByDayValue>& value)
+{
+    m_daysOfTheWeek = value;
+}
+
+JSObjectRef CalendarRecurrenceRule::getJSDaysOfTheWeek(
+        JSContextRef global_ctx)
+{
+    return m_daysOfTheWeek.getJSArray(global_ctx);
+}
+
+std::vector<long long int>   CalendarRecurrenceRule::getSetPositions() const
+{
+    return m_setPositions;
+}
+
+void CalendarRecurrenceRule::setSetPositions(const std::vector<long long int>& value)
+{
+    m_setPositions = value;
+}
+
+JSObjectRef CalendarRecurrenceRule::getJSSetPositions(
+        JSContextRef global_ctx)
+{
+    return m_setPositions.getJSArray(global_ctx);
+}
+
+TZDatePtrVector CalendarRecurrenceRule::getExceptions() const
+{
+    return m_exceptions;
+}
+
+JSObjectRef CalendarRecurrenceRule::getJSExceptions(
+        JSContextRef global_ctx)
+{
+    return m_exceptions.getJSArray(global_ctx);
+}
+
+void CalendarRecurrenceRule::setExceptions(const TZDatePtrVector &value)
+{
+    m_exceptions = value;
+}
+
+CalendarRecurrenceRule::RecurrenceRuleFrequency CalendarRecurrenceRule::stringToRecurrenceRuleFrequency(const std::string& frequency) {
+    if (DAILY == frequency) {
+        return CalendarRecurrenceRule::RecurrenceRuleFrequency::DAILY_FREQUENCY;
+    }
+    if (WEEKLY == frequency) {
+        return CalendarRecurrenceRule::RecurrenceRuleFrequency::WEEKLY_FREQUENCY;
+    }
+    if (MONTHLY == frequency) {
+        return CalendarRecurrenceRule::RecurrenceRuleFrequency::MONTHLY_FREQUENCY;
+    }
+    if (YEARLY == frequency) {
+        return CalendarRecurrenceRule::RecurrenceRuleFrequency::YEARLY_FREQUENCY;
+    }
+
+    LOGW("Invalid RecurrenceRule frequency");
+    throw TypeMismatchException("Invalid RecurrenceRule frequency");
+}
+
+
+const std::string& CalendarRecurrenceRule::recurrenceRuleFrequencyToString(RecurrenceRuleFrequency frequency)
+{
+    switch (frequency) {
+        case CalendarRecurrenceRule::RecurrenceRuleFrequency::DAILY_FREQUENCY:
+            return DAILY;
+        case CalendarRecurrenceRule::RecurrenceRuleFrequency::WEEKLY_FREQUENCY:
+            return WEEKLY;
+        case CalendarRecurrenceRule::RecurrenceRuleFrequency::MONTHLY_FREQUENCY:
+            return MONTHLY;
+        case CalendarRecurrenceRule::RecurrenceRuleFrequency::YEARLY_FREQUENCY:
+            return YEARLY;
+        default:
+            LOGW("Invalid RecurrenceRule frequency");
+            throw TypeMismatchException("Invalid RecurrenceRule frequency");
+    }
+}
+
+CalendarRecurrenceRule::RecurrenceRuleByDayValue CalendarRecurrenceRule::stringToRecurrenceRuleByDayValue(const std::string& day) {
+    if (MONDAY == day) {
+        return CalendarRecurrenceRule::RecurrenceRuleByDayValue::MO;
+    }
+    if (TUESDAY == day) {
+        return CalendarRecurrenceRule::RecurrenceRuleByDayValue::TU;
+    }
+    if (WEDNESDAY == day) {
+        return CalendarRecurrenceRule::RecurrenceRuleByDayValue::WE;
+    }
+    if (THURSDAY == day) {
+        return CalendarRecurrenceRule::RecurrenceRuleByDayValue::TH;
+    }
+    if (FRIDAY == day) {
+        return CalendarRecurrenceRule::RecurrenceRuleByDayValue::FR;
+    }
+    if (SATURDAY == day) {
+        return CalendarRecurrenceRule::RecurrenceRuleByDayValue::SA;
+    }
+    if (SUNDAY == day) {
+        return CalendarRecurrenceRule::RecurrenceRuleByDayValue::SU;
+    }
+
+    LOGW("Invalid RecurrenceRule byDayValue");
+    throw TypeMismatchException("Invalid RecurrenceRule byDayValue");
+}
+
+std::string CalendarRecurrenceRule::recurrenceRuleByDayValueToString(const RecurrenceRuleByDayValue day)
+{
+    switch (day) {
+        case CalendarRecurrenceRule::RecurrenceRuleByDayValue::MO:
+            return MONDAY;
+        case CalendarRecurrenceRule::RecurrenceRuleByDayValue::TU:
+            return TUESDAY;
+        case CalendarRecurrenceRule::RecurrenceRuleByDayValue::WE:
+            return WEDNESDAY;
+        case CalendarRecurrenceRule::RecurrenceRuleByDayValue::TH:
+            return THURSDAY;
+        case CalendarRecurrenceRule::RecurrenceRuleByDayValue::FR:
+            return FRIDAY;
+        case CalendarRecurrenceRule::RecurrenceRuleByDayValue::SA:
+            return SATURDAY;
+        case CalendarRecurrenceRule::RecurrenceRuleByDayValue::SU:
+            return SUNDAY;
+        default:
+            LOGW("Invalid RecurrenceRule byDayValue");
+            throw TypeMismatchException("Invalid RecurrenceRule byDayValue");
+    }
+}
+}
+}
diff --git a/src/Calendar/CalendarRecurrenceRule.h b/src/Calendar/CalendarRecurrenceRule.h
new file mode 100644 (file)
index 0000000..8a1d985
--- /dev/null
@@ -0,0 +1,107 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _CALENDAR_RECURRENCE_RULE_H_
+#define _CALENDAR_RECURRENCE_RULE_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <TZDate.h>
+#include <JSTZDate.h>
+#include <TimeDuration.h>
+#include <JSVector.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class CalendarRecurrenceRule;
+typedef std::shared_ptr<CalendarRecurrenceRule> CalendarRecurrenceRulePtr;
+
+typedef std::vector<DeviceAPI::Time::TZDatePtr> TZDatePtrVector;
+
+class CalendarRecurrenceRule {
+public:
+    typedef enum {
+        NO_FREQUENCY,
+        DAILY_FREQUENCY,
+        WEEKLY_FREQUENCY,
+        MONTHLY_FREQUENCY,
+        YEARLY_FREQUENCY,
+        UNDEFINED_FREQUENCY
+    } RecurrenceRuleFrequency;
+
+    typedef enum { MO, TU, WE, TH, FR, SA, SU } RecurrenceRuleByDayValue;
+
+    CalendarRecurrenceRule();
+    CalendarRecurrenceRule(const CalendarRecurrenceRule& calendar_recurence_rule);
+    virtual ~CalendarRecurrenceRule();
+
+    RecurrenceRuleFrequency getFrequency() const;
+    void setFrequency(const RecurrenceRuleFrequency value);
+
+    int getInterval() const;
+    void setInterval(int value);
+
+    const std::string& getTimezone();
+    void setTimezone(const std::string& time_zone);
+
+    bool isUntilDateSet() const;
+    long long int getUntilDate() const;
+    void setUntilDate(long long int until_date);
+    void unsetUntilDate();
+
+    long getOccurrenceCount() const;
+    void setOccurrenceCount(long value);
+
+    std::vector<RecurrenceRuleByDayValue> getDaysOfTheWeek() const;
+    void setDaysOfTheWeek(const std::vector<RecurrenceRuleByDayValue>& value);
+
+    std::vector<long long int> getSetPositions() const;
+    void setSetPositions(const std::vector<long long int>& value);
+
+    TZDatePtrVector getExceptions() const;
+    void setExceptions(const TZDatePtrVector &value);
+
+    JSObjectRef getJSDaysOfTheWeek(JSContextRef globalCtx);
+    JSObjectRef getJSSetPositions(JSContextRef globalCtx);
+    JSObjectRef getJSExceptions(JSContextRef globalCtx);
+
+    static RecurrenceRuleFrequency stringToRecurrenceRuleFrequency(const std::string& frequency);
+    static const std::string& recurrenceRuleFrequencyToString(RecurrenceRuleFrequency frequency);
+    static RecurrenceRuleByDayValue stringToRecurrenceRuleByDayValue(const std::string& day);
+    static std::string recurrenceRuleByDayValueToString(const RecurrenceRuleByDayValue day);
+
+private:
+    bool m_is_until_date_set;
+    RecurrenceRuleFrequency m_frequency;
+    int m_interval;
+    std::string m_time_zone;
+    long long int m_untilDate;             //this attribute is used in all date attributes
+    long m_occurrenceCount;
+    Common::JSEnumVector<RecurrenceRuleByDayValue,
+        stringToRecurrenceRuleByDayValue,
+        recurrenceRuleByDayValueToString> m_daysOfTheWeek;
+    Common::JSLongLongVector m_setPositions;
+    Common::JSObjectVector<Time::TZDatePtr, Time::JSTZDate> m_exceptions;
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif /* _CALENDAR_RECURRENCE_RULE_H_ */
+
diff --git a/src/Calendar/CalendarTask.cpp b/src/Calendar/CalendarTask.cpp
new file mode 100755 (executable)
index 0000000..37eb120
--- /dev/null
@@ -0,0 +1,1601 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        CalendarTask.cpp
+*/
+
+#include "CalendarTask.h"
+#include "CalendarUtility.h"
+#include "CalendarManager.h"
+#include <calendar.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+#define UNDEFINED_TIME -1
+
+struct CalendarTaskHolder {
+    CalendarTaskPtr ptr;
+};
+
+CalendarTask::CalendarTask() :
+        CalendarItem(),
+        m_id(0),
+        m_completedDate(UNDEFINED_TIME)
+{
+    try{
+        m_is_set.resize(CALENDAR_TASK_NUMBER_OF_ATTRIBUTES, false);
+    }
+    catch (...) {
+        LOGE("Resize vector failed");
+        throw UnknownException("Can't create the CalendarEvent object");
+    }
+    m_type = CALENDAR_TASK;
+    setStatus(TASK_STATUS_NEEDS_ACTION);
+    setProgress(0);
+    m_platform_item = NULL;
+}
+
+CalendarTask::CalendarTask(const CalendarTask &calendar_task) :
+    CalendarItem(calendar_task),
+    m_id(calendar_task.getId()),
+    m_completedDate(calendar_task.m_completedDate),
+    m_progress(calendar_task.getProgress())
+{
+    LOGD("Entered");
+    m_type = CALENDAR_TASK;
+    m_is_set = calendar_task.getIsSet();
+}
+
+CalendarTask::~CalendarTask()
+{
+    LOGD("Entered");
+}
+
+int CalendarTask::getId() const
+{
+    LOGD("Entered");
+    return m_id;
+}
+
+void CalendarTask::setId(const int value)
+{
+    LOGD("Entered");
+    m_is_set[CALENDAR_TASK_ATTRIBUTE_ID] = true;
+    m_id = value;
+}
+
+long long int CalendarTask::getCompletedDate() const
+{
+    LOGD("Entered");
+    return m_completedDate;
+}
+
+void CalendarTask::setCompletedDate(long long int value, const std::string& time_zone)
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE] || m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        if (m_time_zone != time_zone) {
+            LOGE("Completed Date should have the same timezone as start/due/end date");
+            throw InvalidValuesException(
+                    "Start date should have the same timezone as start/due/end date");
+        }
+    }
+
+    m_is_set[CALENDAR_TASK_ATTRIBUTE_COMPLETED_DATE] = true;
+    m_completedDate = value;
+    m_time_zone = time_zone;
+}
+
+unsigned int CalendarTask::getProgress() const
+{
+    LOGD("Entered");
+    return m_progress;
+}
+
+void CalendarTask::setProgress(unsigned int value)
+{
+    LOGD("Entered");
+    if (value <= 100) {
+        m_is_set[CALENDAR_TASK_ATTRIBUTE_PROGRESS] = true;
+        m_progress = value;
+    }
+}
+
+bool CalendarTask::isSet(CalendarTaskAttribute attribute) const
+{
+    LOGD("Entered");
+    return m_is_set[attribute];
+}
+
+void CalendarTask::setIsSet(CalendarTaskAttribute attribute, bool is_set)
+{
+    LOGD("Entered");
+    m_is_set[attribute] = is_set;
+}
+
+calendar_record_h CalendarTask::convertAbstractCalendarTaskToPlatformCalendarTask(
+        bool loadBeforeConvert)
+{
+    LOGD("Entered");
+    int ret;
+    freePlatformCalendarItem();
+    if (loadBeforeConvert) {
+        // Load the item for update operation to include the id.
+        ret = calendar_db_get_record(_calendar_todo._uri, getId(), &m_platform_item);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "calendar_db_get_record()");
+       }
+    }
+    else{
+        ret = calendar_record_create(_calendar_todo._uri, &m_platform_item);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "calendar_record_create()");
+        } else {
+            LOGD("Platform item created with dataType: %s", _calendar_todo._uri);
+        }
+    }
+    setCalendarIdToPlatformCalendarItem();
+    setDescriptionToPlatformCalendarItem();
+    setSummaryToPlatformCalendarItem();
+    setIsAllDayAndStartDateToPlatformCalendarItem();
+    setLocationToPlatformCalendarItem();
+    setGeolocationToPlatformCalendarItem();
+    setOrganizerToPlatformCalendarItem();
+    setVisibilityToPlatformCalendarItem();
+    setStatusToPlatformCalendarItem();
+    setPriorityToPlatformCalendarItem();
+    setAlarmsToPlatformCalendarItem();
+    setCategoriesToPlatformCalendarItem();
+    setAttendeesToPlatformCalendarItem();
+    setEndDateToPlatformCalendarItem();
+
+    setCompletedDateToPlatformCalendarTask();
+    setProgressToPlatformCalendarTask();
+    return getPlatformCalendarItem();
+}
+
+void CalendarTask::setCalendarIdToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_CALENDAR_ID])
+    {
+        ret = calendar_record_set_int(m_platform_item, _calendar_todo.calendar_book_id, m_calendar_id);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set calendarId : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setDescriptionToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_DESCRIPTION])
+    {
+        ret = calendar_record_set_str(m_platform_item, _calendar_todo.description, m_description.c_str());
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set item description : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setSummaryToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_SUMMARY])
+    {
+        ret = calendar_record_set_str(m_platform_item, _calendar_todo.summary, m_summary.c_str());
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set item subject : %d, %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setIsAllDayAndStartDateToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    long long int time = UNDEFINED_TIME;
+
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        time = m_start_date;
+        LOGD("use start date, time = %lld, Timezone = %s", time, m_time_zone.c_str());
+    }
+
+    if (UNDEFINED_TIME == time && m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE]) {
+        time = m_end_date;
+        LOGD("use end date, time = %lld, Timezone = %s", time, m_time_zone.c_str());
+    }
+
+    calendar_time_s cal;
+    if (getIsAllDay()) {
+        LOGD("all day item");
+        cal.type = CALENDAR_TIME_LOCALTIME;
+        cal.time.date = CalendarUtility::LLIToCalTime(m_time_zone.c_str(), time).time.date;
+    } else {
+        LOGD("not all day item");
+        cal.type = CALENDAR_TIME_UTIME;
+        cal.time.utime = time;
+    }
+
+    ret = calendar_record_set_caltime(m_platform_item, _calendar_todo.start_time, cal);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_set_caltime()");
+    }
+
+    ret = calendar_record_set_str(m_platform_item, _calendar_todo.start_tzid, m_time_zone.c_str());
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_set_str()");
+    }
+}
+
+void CalendarTask::setLocationToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_LOCATION])
+    {
+        ret = calendar_record_set_str(m_platform_item, _calendar_todo.location, m_location.c_str());
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set location : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setGeolocationToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_GEOLOCATION])
+    {
+        ret = calendar_record_set_double(m_platform_item, _calendar_todo.latitude, m_geolocation->getLatitude());
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set latitude : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+
+        ret = calendar_record_set_double(m_platform_item, _calendar_todo.longitude, m_geolocation->getLongitude());
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set longitude : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setOrganizerToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_ORGANIZER])
+    {
+        ret = calendar_record_set_str(m_platform_item, _calendar_todo.organizer_name, m_organizer.c_str());
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set item organizer : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setVisibilityToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_VISIBILITY])
+    {
+        calendar_sensitivity_e visibility = CALENDAR_SENSITIVITY_PUBLIC;
+        switch (getVisibility()) {
+            case CALENDAR_ITEM_VISIBILITY_PRIVATE:
+                visibility = CALENDAR_SENSITIVITY_PRIVATE;
+                break;
+            case CALENDAR_ITEM_VISIBILITY_CONFIDENTIAL:
+                visibility = CALENDAR_SENSITIVITY_CONFIDENTIAL;
+                break;
+            default:
+                LOGD("Use the default visibility CALENDAR_SENSITIVITY_PUBLIC");
+                break;
+        }
+
+        ret = calendar_record_set_int(m_platform_item, _calendar_todo.sensitivity, visibility);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set visibility : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setStatusToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_STATUS])
+    {
+        calendar_todo_status_e task_status = CALENDAR_TODO_STATUS_NONE;
+        switch (getStatus()) {
+            case TASK_STATUS_NEEDS_ACTION:
+                task_status = CALENDAR_TODO_STATUS_NEEDS_ACTION;
+                break;
+            case TASK_STATUS_COMPLETED:
+                task_status = CALENDAR_TODO_STATUS_COMPLETED;
+                break;
+            case TASK_STATUS_IN_PROCESS:
+                task_status = CALENDAR_TODO_STATUS_IN_PROCESS;
+                break;
+            case TASK_STATUS_CANCELLED:
+                task_status = CALENDAR_TODO_STATUS_CANCELED;
+                break;
+            default:
+                break;
+        }
+        ret = calendar_record_set_int(m_platform_item, _calendar_todo.todo_status, task_status);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set item status : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setPriorityToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_PRIORITY])
+    {
+        calendar_todo_priority_e todo_priority = CALENDAR_TODO_PRIORITY_NORMAL;
+        switch (getPriority()) {
+            case CALENDAR_ITEM_PRIORITY_HIGH:
+                todo_priority = CALENDAR_TODO_PRIORITY_HIGH;
+                break;
+            case CALENDAR_ITEM_PRIORITY_LOW:
+                todo_priority = CALENDAR_TODO_PRIORITY_LOW;
+                break;
+            default:
+                LOGD("Use the default priority CALENDAR_TODO_PRIORITY_NORMAL");
+                break;
+        }
+        ret = calendar_record_set_int(m_platform_item, _calendar_todo.priority, todo_priority);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't set event priority : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setAlarmsToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    // Remove the preset child alarms before adding new ones.
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_ALARMS])
+    {
+        unsigned int count = 0;
+
+        ret = calendar_record_get_child_record_count(m_platform_item, _calendar_todo.calendar_alarm, &count);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't get alarms count : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+
+        calendar_record_h alarm = NULL;
+        for (unsigned int i=0; i<count; ++i) {
+            alarm = NULL;
+            // Be careful about the index. We always insert 0 cause the child list is updated every time we remove one.
+            ret = calendar_record_get_child_record_at_p(m_platform_item, _calendar_todo.calendar_alarm, 0, &alarm);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Can't get the alarm : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                continue;
+            }
+
+            ret = calendar_record_remove_child_record(m_platform_item, _calendar_todo.calendar_alarm, alarm);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Can't remove the alarm : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                continue;
+            }
+        }
+        // Now add the new alarms.
+        std::size_t size = getAlarms().size();
+        if (size) {
+            for (unsigned int i=0; i<size; ++i)
+            {
+                LOGD("Set the alarms nr %d",i);
+                alarm = NULL;
+                ret = calendar_record_create(_calendar_alarm._uri, &alarm);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Alarm creation failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                    continue;
+                }
+
+                CalendarAlarmPtr the_alarm= getAlarms().at(i);
+                calendar_alarm_time_unit_type_e tick_unit = CALENDAR_ALARM_NONE;
+                int tick = 0;
+                if (UNDEFINED_TIME != the_alarm->getAbsoluteDate()) {
+                    tick_unit = CALENDAR_ALARM_TIME_UNIT_SPECIFIC;
+                } else {
+                    if (MSECS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_MINUTE; // minimum calendar time unit.
+                        tick = the_alarm->getBefore()->getLength() / 60000;
+                    } else if (SECS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
+                        tick = the_alarm->getBefore()->getLength() / 60;
+                    } else if (MINS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_MINUTE;
+                        tick = the_alarm->getBefore()->getLength();
+                    } else if (HOURS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_HOUR;
+                        tick = the_alarm->getBefore()->getLength();
+                    } else if (DAYS == the_alarm->getBefore()->getUnit()) {
+                        tick_unit = CALENDAR_ALARM_TIME_UNIT_DAY;
+                        tick = the_alarm->getBefore()->getLength();
+                    } else {
+                        LOGW("Wrong alarm time unit: %s",
+                                the_alarm->getBefore()->getUnit().c_str());
+                    }
+                }
+
+                if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC == tick_unit) {
+                    long long int time = the_alarm->getAbsoluteDate();
+
+                    calendar_time_s at;
+                    at.type = CALENDAR_TIME_UTIME;
+                    at.time.utime = time;
+
+                    LOGD("Save absolute date: %d", time);
+                    ret = calendar_record_set_caltime(alarm, _calendar_alarm.alarm_time, at);
+                    if (ret != CALENDAR_ERROR_NONE) {
+                        LOGW("Can't set alarm time : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                    }
+                } else {
+                    ret = calendar_record_set_int(alarm, _calendar_alarm.tick, tick);
+                    if (ret != CALENDAR_ERROR_NONE) {
+                        LOGW("Can't set alarm tick : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                    }
+                }
+
+                ret = calendar_record_set_int(alarm, _calendar_alarm.tick_unit, tick_unit);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Can't set alarm tick unit : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+
+                // Set the alarm type.
+                ret = calendar_record_set_int(alarm, _calendar_alarm.action, the_alarm->getAlarmMethod());
+                if (CALENDAR_ERROR_NONE !=  ret) {
+                    LOGW("Can't set alarm type : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+
+                // Set the display text
+                ret = calendar_record_set_str(alarm, _calendar_alarm.description, the_alarm->getDescription().c_str());
+                if (CALENDAR_ERROR_NONE !=  ret) {
+                    LOGW("Can't set alarm description : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+
+                ret = calendar_record_add_child_record(m_platform_item, _calendar_todo.calendar_alarm, alarm);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot add alarm child record : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                    if (alarm) {
+                        calendar_record_destroy(alarm, true);
+                    }
+                }
+            }
+        } else {
+            LOGD("No alarms to save.");
+        }
+    }
+}
+
+void CalendarTask::setCategoriesToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    std::string categories = "";
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_CATEGORIES])
+    {
+        // Need to concatenate all categories into one string separated by a comma.
+        auto cat_vec = getCategories();
+        size_t cat_vec_size = cat_vec.size();
+        for (size_t i = 0; i < cat_vec_size; ++i) {
+            if (0 == i) {
+                categories.append(cat_vec.at(i));
+            } else {
+                categories.append("," + cat_vec.at(i));
+            }
+        }
+
+        LOGD("Saving categories: %s", categories.c_str());
+        ret = calendar_record_set_str(m_platform_item, _calendar_todo.categories, categories.c_str());
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot save categories : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void CalendarTask::setAttendeesToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    // Remove the preset child attendees before adding new ones.
+    unsigned int count = 0, i;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_ATTENDEES])
+    {
+
+        ret = calendar_record_get_child_record_count(m_platform_item,
+                    _calendar_todo.calendar_attendee, &count);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't get attendees count : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        calendar_record_h attendee = NULL;
+        for ( i = 0; i < count; ++i) {
+            attendee = NULL;
+            // Be careful about the index. We always insert 0 cause the child
+            // list is updated every time we remove one=
+
+            ret = calendar_record_get_child_record_at_p(m_platform_item,
+                        _calendar_todo.calendar_attendee, 0, &attendee);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Can't get the attendee : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                continue;
+            }
+            ret = calendar_record_remove_child_record(m_platform_item,
+                        _calendar_todo.calendar_attendee, attendee);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Can't remove the attendee : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            }
+        }
+        // Now add the new attendees.
+        auto attendee_list = getAttendees();
+        const std::size_t size = attendee_list.size();
+
+        if (size) {
+            for (i = 0; i < size; ++i) {
+                attendee = NULL;
+                ret = calendar_record_create(_calendar_attendee._uri, &attendee);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Attendee creation failed : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                    continue;
+                }
+                CalendarAttendeePtr the_attendee = attendee_list.at(i);
+                // save name
+                ret = calendar_record_set_str(attendee, _calendar_attendee.name,
+                        the_attendee->getName().c_str());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot set attendee name : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                // save uri
+                ret = calendar_record_set_str(attendee, _calendar_attendee.email,
+                        the_attendee->getURI().c_str());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot set attendee URI : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                // save role
+                calendar_attendee_role_e role = CALENDAR_ATTENDEE_ROLE_CHAIR;
+                switch (the_attendee->getRole()) {
+                case CalendarAttendee::REQ_PARTICIPANT_ROLE:
+                    role = CALENDAR_ATTENDEE_ROLE_REQ_PARTICIPANT;
+                    break;
+                case CalendarAttendee::OPT_PARTICIPANT_ROLE:
+                    role = CALENDAR_ATTENDEE_ROLE_OPT_PARTICIPANT;
+                    break;
+                case CalendarAttendee::NON_PARTICIPANT_ROLE:
+                    role = CALENDAR_ATTENDEE_ROLE_NON_PARTICIPANT;
+                    break;
+                default:
+                    LOGD("Use the default role");
+                    break;
+                }
+                ret = calendar_record_set_int(attendee, _calendar_attendee.role, role);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot set attendee role : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                // save status
+                calendar_attendee_status_e status = CALENDAR_ATTENDEE_STATUS_PENDING;
+                switch (the_attendee->getStatus()) {
+                case CalendarAttendee::ACCEPTED_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_ACCEPTED;
+                    break;
+                case CalendarAttendee::DECLINED_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_DECLINED;
+                    break;
+                case CalendarAttendee::TENTATIVE_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_TENTATIVE;
+                    break;
+                case CalendarAttendee::DELEGATED_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_DELEGATED;
+                    break;
+                case CalendarAttendee::COMPLETED_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_COMPLETED;
+                    break;
+                case CalendarAttendee::IN_PROCESS_AT_STATUS:
+                    status = CALENDAR_ATTENDEE_STATUS_IN_PROCESS;
+                    break;
+                default:
+                    LOGD("Use the default status");
+                    break;
+                }
+                ret = calendar_record_set_int(attendee, _calendar_attendee.status, status);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot set attendee status : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                // save RSVP
+                ret = calendar_record_set_int(attendee, _calendar_attendee.rsvp,
+                        the_attendee->getRSVP());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot set attendee RSVP : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                // save type
+                ret = calendar_record_set_int(attendee, _calendar_attendee.cutype,
+                        the_attendee->getType());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot set attendee type : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                // save group
+                ret = calendar_record_set_str(attendee, _calendar_attendee.group,
+                        the_attendee->getGroup().c_str());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot set attendee group : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                // save delegatorURI
+                ret = calendar_record_set_str(attendee, _calendar_attendee.delegator_uri,
+                        the_attendee->getDelegatorURI().c_str());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot set attendee delegator uri : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                // save delegateURI
+                ret = calendar_record_set_str(attendee, _calendar_attendee.delegatee_uri,
+                        the_attendee->getDelegateURI().c_str());
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot set attendee delegate uri : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+                if (the_attendee->isContactRefSet()) {
+                    // save contactId
+                    ret = calendar_record_set_str(attendee, _calendar_attendee.uid,
+                            the_attendee->getContactRef()->getContactIdString().c_str());
+                    if (ret != CALENDAR_ERROR_NONE) {
+                        LOGW("Cannot set attendee uid : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                    }
+
+                    // save addressBookId
+                    std::stringstream ss(attendee_list.at(i)->getContactRef()->getAddressBookIdString().c_str());
+                    int addressBookId;
+                    ss >> addressBookId;
+                    LOGD("addressBookId: %d", addressBookId);
+                    ret = calendar_record_set_int(attendee, _calendar_attendee.person_id, addressBookId);
+                    if (ret != CALENDAR_ERROR_NONE) {
+                        LOGW("Cannot set attendee address book id : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                    }
+                }
+                else {
+                    LOGD("ContactRef not set");
+                }
+
+                ret = calendar_record_add_child_record(m_platform_item,
+                            _calendar_todo.calendar_attendee, attendee);
+                if (ret != CALENDAR_ERROR_NONE) {
+                    LOGW("Cannot add attendee child record : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                }
+            }
+        } else {
+           LOGD("No attendee to save.");
+       }
+    }
+}
+
+void CalendarTask::setEndDateToPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    long long int time = UNDEFINED_TIME;
+    if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE]) {
+        time = m_end_date;
+        LOGD("Use end/due date");
+    }
+    else if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_DURATION] &&
+            m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        if (0 < getDuration()->getLength()) {
+            LOGD("Set the end/due date from the duration: %d", time);
+            long long length = getDuration()->getLength();
+            std::string unit = getDuration()->getUnit();
+
+            bool correct_unit = true;
+
+            if ( MINS == unit ) {
+                length = length*60;
+            } else if (HOURS == unit) {
+                length = length*60*60;
+            } else if (DAYS == unit) {
+                length = length*24*60*60;
+            } else if (MSECS == unit) {
+                length = length/1000;
+            } else if(SECS != unit ){
+                LOGD("Wrong duration unit: %s", unit.c_str());
+                correct_unit = false;
+            }
+
+            if(getIsAllDay() && correct_unit) {
+                if(length > 24*60*60){
+                    length = length - length%(24*60*60);
+                    length = length - 24*60*60;
+                } else {
+                    length = 0;
+                }
+            }
+            if(correct_unit){
+                time = m_start_date + length;
+            }
+        }
+    }
+
+    if (UNDEFINED_TIME == time && m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        time = m_start_date;
+        LOGD("Set the end/due date from the start time: %d", time);
+    }
+
+    calendar_time_s cal;
+    if (getIsAllDay()) {
+        LOGD("all day case");
+        cal.type = CALENDAR_TIME_LOCALTIME;
+        cal.time.date = CalendarUtility::LLIToCalTime(
+                m_time_zone.c_str(), time).time.date;
+    } else {
+        LOGD("not all day case");
+        cal.type = CALENDAR_TIME_UTIME;
+        cal.time.utime = time;
+    }
+
+    ret = calendar_record_set_caltime(m_platform_item, _calendar_todo.due_time, cal);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_set_caltime()");
+    }
+    ret = calendar_record_set_str(m_platform_item,
+                _calendar_todo.due_tzid, m_time_zone.c_str());
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_set_str()");
+    }
+}
+
+void CalendarTask::setCompletedDateToPlatformCalendarTask()
+{
+    LOGD("Entered");
+    long long int time = UNDEFINED_TIME;
+    if (m_is_set[CALENDAR_TASK_ATTRIBUTE_COMPLETED_DATE]) {
+        time = m_completedDate;
+        LOGD("Use Completed Date");
+    }
+    else if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE]) {
+        time = m_end_date;
+        LOGD("Use Due Date");
+    }
+    else if (m_is_set[CALENDAR_ITEM_ATTRIBUTE_DURATION] &&
+            m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        if (0 < getDuration()->getLength()) {
+            long long length = getDuration()->getLength();
+            std::string unit = getDuration()->getUnit();
+
+            if (SECS == unit) {
+                time = m_start_date + length;
+            } else if (MINS == unit) {
+                time = m_start_date + length*60;
+            } else if (HOURS == unit) {
+                time = m_start_date + length*60*60;
+            } else if (DAYS == unit) {
+                time = m_start_date + length*24*60*60;
+            } else if (MSECS == unit) {
+                time = m_start_date + length/1000;
+            } else {
+                LOGD("Wrong duration unit: %s", unit.c_str());
+            }
+            LOGD("Set the end time from the duration: %d", time);
+        } else {
+            time = m_start_date;
+            LOGD("Set the end time from the start time: %d", time);
+        }
+    }
+
+    if (UNDEFINED_TIME == time && m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE]) {
+        time = m_start_date;
+        LOGD("Set the end/due date from the start date: %d", time);
+    }
+
+    int ret;
+    ret = calendar_record_set_lli(m_platform_item,
+            _calendar_todo.completed_time, time);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_set_lli()");
+    }
+}
+
+void CalendarTask::setProgressToPlatformCalendarTask()
+{
+    LOGD("Entered");
+    if (m_is_set[CALENDAR_TASK_ATTRIBUTE_PROGRESS])
+    {
+        int ret = calendar_record_set_int(m_platform_item,
+                _calendar_todo.progress, m_progress);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            CalendarUtility::throwCalendarException(ret, "calendar_record_set_int()");
+        }
+    }
+}
+
+void CalendarTask::convertPlatformTaskToAbstractCalendarTask(
+        calendar_record_h platform_task_tmp)
+{
+    LOGD("Entered");
+    if (NULL == platform_task_tmp) {
+        platform_task_tmp = m_platform_item;
+    }
+    else{
+        freePlatformCalendarItem();
+        int ret = calendar_record_clone(platform_task_tmp, &m_platform_item);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot clone the records : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+    }
+    setIdFromPlatformCalendarTask();
+
+    setCalendarIdFromPlatformCalendarItem();
+    setDescriptionFromPlatformCalendarItem();
+    setSummaryFromPlatformCalendarItem();
+    setIsAllDayAndStartDateFromPlatformCalendarItem();
+    setLastModifiedDateFromPlatformCalendarItem();
+    setLocationFromPlatformCalendarItem();
+    setGeolocationFromPlatformCalendarItem();
+    setOrganizerFromPlatformCalendarItem();
+    setVisibilityFromPlatformCalendarItem();
+    setStatusFromPlatformCalendarItem();
+    setPriorityFromPlatformCalendarItem();
+    setAlarmsFromPlatformCalendarItem();
+    setCategoriesFromPlatformCalendarItem();
+    setAttendeesFromPlatformCalendarItem();
+    setEndDateFromPlatformCalendarItem();
+
+    setIdFromPlatformCalendarTask();
+    setCompletedDateFromPlatformCalendarTask();
+    setProgressFromPlatformCalendarTask();
+
+    copyAceCheckAccessFunction(CalendarManager::getInstance());
+
+    return;
+}
+
+void CalendarTask::setCalendarIdFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int calendar_id;
+    int ret;
+    ret = calendar_record_get_int(m_platform_item,
+                _calendar_todo.calendar_book_id, &calendar_id);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get calenadrId : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+    setCalendarId(calendar_id);
+}
+
+void CalendarTask::setLastModifiedDateFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    long long int last_modified_date;
+    ret = calendar_record_get_lli(m_platform_item,
+               _calendar_todo.last_modified_time, &last_modified_date);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get last modification time : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+
+    setLastModificationDate(last_modified_date);
+
+    if (UNDEFINED_TIME == last_modified_date) {
+        m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE] = false;
+    }
+
+}
+
+void CalendarTask::setDescriptionFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    char *description = NULL;
+    ret = calendar_record_get_str_p(m_platform_item,
+                _calendar_todo.description, &description);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get description : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+    if (description) {
+        setDescription(std::string(description));
+    }
+}
+
+void CalendarTask::setSummaryFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    char *summary = NULL;
+    ret = calendar_record_get_str_p(m_platform_item,
+                _calendar_todo.summary, &summary);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get summary : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+    if (summary) {
+        setSummary(std::string(summary));
+    }
+}
+
+void CalendarTask::setIsAllDayAndStartDateFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    calendar_time_s cal;
+    // Retrive the time zone info only when the start time is loaded.
+    char *time_zone = NULL;
+    ret = calendar_record_get_str_p(m_platform_item,
+                _calendar_todo.start_tzid, &time_zone);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get Timezone : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    m_time_zone = std::string(time_zone);
+
+    ret = calendar_record_get_caltime(m_platform_item,
+                _calendar_todo.start_time, &cal);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get start time : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE] = true;
+    // Set the isAllDay flag also.
+    if (CALENDAR_TIME_LOCALTIME == cal.type) {
+        m_start_date = CalendarUtility::calTimeToLLI(time_zone, cal);
+        setIsAllDay(true);
+    } else {
+        LOGD("cal.time.utime = %lld", cal.time.utime);
+        if (UNDEFINED_TIME == cal.time.utime) {
+            m_is_set[CALENDAR_ITEM_ATTRIBUTE_START_DATE] = false;
+        }
+        m_start_date = cal.time.utime;
+        setIsAllDay(false);
+    }
+}
+
+void CalendarTask::setLocationFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    char *location = NULL;
+    ret = calendar_record_get_str_p(m_platform_item,
+                _calendar_todo.location, &location);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get location : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+    if (location) {
+        setLocation(std::string(location));
+    }
+}
+
+void CalendarTask::setGeolocationFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    double latitude = UNDEFINED_GEO;
+    ret = calendar_record_get_double(m_platform_item,
+                _calendar_todo.latitude, &latitude);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get item latitude : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+    //getGeolocation()->setLatitude(latitude);
+
+    double longitude = UNDEFINED_GEO;
+    ret = calendar_record_get_double(m_platform_item,
+                _calendar_todo.longitude, &longitude);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get item longitude : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+    //getGeolocation()->setLongitude(longitude);
+
+    m_geolocation = Tizen::SimpleCoordinatesPtr(new Tizen::SimpleCoordinates(latitude, longitude));
+
+    if (UNDEFINED_GEO != latitude && UNDEFINED_GEO != longitude) {
+        m_is_set[CALENDAR_ITEM_ATTRIBUTE_GEOLOCATION] = true;
+    } else {
+        m_is_set[CALENDAR_ITEM_ATTRIBUTE_GEOLOCATION] = false;
+    }
+}
+
+void CalendarTask::setOrganizerFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    char* organizer = NULL;
+
+    ret = calendar_record_get_str_p(m_platform_item,
+                    _calendar_todo.organizer_name, &organizer);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get organizer : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+    if (organizer) {
+        setOrganizer(std::string(organizer));
+    }
+}
+
+void CalendarTask::setVisibilityFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int visibility;
+    int ret;
+
+    ret = calendar_record_get_int(m_platform_item,
+                _calendar_todo.sensitivity, &visibility);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get visibility : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+    switch (visibility) {
+    case CALENDAR_SENSITIVITY_PUBLIC:
+        setVisibility(CALENDAR_ITEM_VISIBILITY_PUBLIC);
+        break;
+    case CALENDAR_SENSITIVITY_PRIVATE:
+        setVisibility(CALENDAR_ITEM_VISIBILITY_PRIVATE);
+        break;
+    case CALENDAR_SENSITIVITY_CONFIDENTIAL:
+        setVisibility(CALENDAR_ITEM_VISIBILITY_CONFIDENTIAL);
+        break;
+    default:
+        LOGD("Use the default visibility CALENDAR_ITEM_VISIBILITY_PUBLIC");
+        setVisibility(CALENDAR_ITEM_VISIBILITY_PUBLIC);
+        break;
+    }
+}
+
+void CalendarTask::setStatusFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int status;
+    int ret;
+    ret = calendar_record_get_int(m_platform_item,
+                _calendar_todo.todo_status, &status);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get status : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+
+    switch (status) {
+        case CALENDAR_EVENT_STATUS_TENTATIVE:
+            setStatus(EVENT_STATUS_TENTATIVE);
+            break;
+        case CALENDAR_EVENT_STATUS_CONFIRMED:
+            setStatus(EVENT_STATUS_CONFIRMED);
+            break;
+        case CALENDAR_EVENT_STATUS_CANCELLED:
+            setStatus(EVENT_STATUS_CANCELLED);
+            break;
+        case CALENDAR_TODO_STATUS_CANCELED:
+            setStatus(TASK_STATUS_CANCELLED);
+            break;
+        case CALENDAR_TODO_STATUS_NEEDS_ACTION:
+            setStatus(TASK_STATUS_NEEDS_ACTION);
+            break;
+        case CALENDAR_TODO_STATUS_COMPLETED:
+            setStatus(TASK_STATUS_COMPLETED);
+            break;
+        case CALENDAR_TODO_STATUS_IN_PROCESS:
+            setStatus(TASK_STATUS_IN_PROCESS);
+            break;
+        default:
+            setStatus(TASK_STATUS_UNDEFINED);
+            break;
+    }
+}
+
+void CalendarTask::setPriorityFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int priority;
+    int ret;
+    ret = calendar_record_get_int(m_platform_item,
+                _calendar_todo.priority, &priority);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get event priority : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+    //CALENDAR_TODO_PRIORITY_.... is equal CALENDAR_ITEM_PRIORITY_....
+    switch (priority) {
+        case CALENDAR_EVENT_PRIORITY_LOW:
+            setPriority(CALENDAR_ITEM_PRIORITY_LOW);
+            break;
+        case CALENDAR_EVENT_PRIORITY_NORMAL:
+            setPriority(CALENDAR_ITEM_PRIORITY_MEDIUM);
+            break;
+        case CALENDAR_EVENT_PRIORITY_HIGH:
+            setPriority(CALENDAR_ITEM_PRIORITY_HIGH);
+            break;
+        default:
+            setPriority(CALENDAR_ITEM_PRIORITY_MEDIUM);
+            break;
+    }
+}
+
+void CalendarTask::setAlarmsFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    unsigned int count = 0;
+    calendar_list_h list = NULL;
+
+    ret = calendar_record_get_child_record_count(m_platform_item,
+                _calendar_todo.calendar_alarm, &count);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get alarms count : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+    if (!count) {
+        LOGD("No alarms to set.");
+        return;
+    }
+    LOGD("Number of alarms: %d", count);
+
+    ret = calendar_record_clone_child_record_list(m_platform_item,
+                _calendar_todo.calendar_alarm, &list);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get alarms list : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+
+    int tick = 0, tick_unit = 0;
+    calendar_record_h alarm = NULL;
+    for (unsigned int i = 0; i < count; ++i)
+    {
+        LOGD("Processing the alarm %d", i);
+
+        ret = calendar_record_get_child_record_at_p(m_platform_item,
+                    _calendar_todo.calendar_alarm, i, &alarm);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't get the alarm : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            continue;
+        }
+        CalendarAlarmPtr the_alarm(new CalendarAlarm());
+
+        ret = calendar_record_get_int(alarm, _calendar_alarm.tick_unit, &tick_unit);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read alarm tick unit : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            continue;
+        }
+        if (CALENDAR_ALARM_TIME_UNIT_SPECIFIC==tick_unit) {
+            calendar_time_s at;
+            ret = calendar_record_get_caltime(alarm, _calendar_alarm.alarm_time, &at);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Can't get alarm tick : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                continue;
+            }
+            the_alarm->setAbsoluteDateResetBefore(at.time.utime);
+            the_alarm->setTimeZone(m_time_zone);
+            LOGD("Loaded absolute date");
+        } else {
+            ret = calendar_record_get_int(alarm, _calendar_alarm.tick, &tick);
+            if (ret != CALENDAR_ERROR_NONE) {
+                LOGW("Cannot read alarm tick. Stop processing alarms : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+                continue;
+            }
+            TimeDurationPtr duration_ptr(new TimeDuration());
+            if (CALENDAR_ALARM_TIME_UNIT_MINUTE==tick_unit) {
+                duration_ptr->setUnit(MINS);
+                duration_ptr->setLength(tick);
+            } else if (CALENDAR_ALARM_TIME_UNIT_HOUR==tick_unit) {
+                duration_ptr->setUnit(HOURS);
+                duration_ptr->setLength(tick);
+            } else if (CALENDAR_ALARM_TIME_UNIT_DAY==tick_unit) {
+                duration_ptr->setUnit(DAYS);
+                duration_ptr->setLength(tick);
+            } else if (CALENDAR_ALARM_TIME_UNIT_WEEK==tick_unit) {
+                duration_ptr->setUnit(DAYS);
+                duration_ptr->setLength(tick*7);
+            } else {
+                LOGW("Wrong tick unit: %d", tick_unit);
+            }
+            the_alarm->setBeforeResetAbsoluteDate(duration_ptr);
+        }
+
+        int type;
+        ret = calendar_record_get_int(alarm, _calendar_alarm.action, &type);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read alarm type : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            continue;
+        }
+        the_alarm->setAlarmMethod(static_cast<CalendarAlarmMethod>(type));
+        char* description = NULL;
+        ret = calendar_record_get_str_p(alarm, _calendar_alarm.description, &description);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read alarm description : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            the_alarm->setDescription("");
+        } else {
+            if (description) {
+                LOGD("Alarm description: %s", description);
+                the_alarm->setDescription(std::string(description));
+            }
+        }
+        // Save the alarm.
+        m_alarms.push_back(the_alarm);
+    }
+
+    if (list) {
+        calendar_list_destroy(list, true);
+        list = NULL;
+    }
+}
+
+void CalendarTask::setCategoriesFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    m_categories.clear();
+    char *categories = NULL;
+    int ret;
+
+    ret = calendar_record_get_str_p(m_platform_item,
+                _calendar_todo.categories, &categories);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get categories : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+    if (categories) {
+        LOGD("Loaded categories: %d", categories);
+        char *saveptr = NULL;
+        char* pch = strtok_r(categories, ",", &saveptr);
+        auto l_categories = getCategories();
+
+        while (pch) {
+            try{
+                l_categories.push_back(pch);
+                pch = strtok_r(NULL, ",", &saveptr);
+            }
+            catch (...) {
+                LOGE("Exception in push_back function");
+                throw UnknownException(
+                    "Exception in push_back in setCategoriesFromPlatformCalendarEvent");
+            }
+        }
+
+        setCategories(l_categories);
+    }
+}
+
+void CalendarTask::setAttendeesFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (!m_attendees.empty()) {
+        m_attendees.clear();
+    }
+    unsigned int count = 0, i;
+    calendar_record_h attendee = NULL;
+    calendar_list_h list = NULL;
+
+    ret = calendar_record_get_child_record_count(m_platform_item,
+                _calendar_todo.calendar_attendee, &count);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get attendee count : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+
+    if (!count) {
+        LOGD("No attendees to set.");
+        return;
+    }
+
+    ret = calendar_record_clone_child_record_list(m_platform_item,
+                _calendar_todo.calendar_attendee, &list);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get attendee list : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+
+    for (i = 0; i < count; ++i)
+    {
+        LOGD("Processing the attendee %d", i);
+        ret =  calendar_record_get_child_record_at_p(m_platform_item,
+                    _calendar_todo.calendar_attendee, i, &attendee);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Can't get attendee record : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            continue;
+        }
+
+        CalendarAttendeePtr attendee_ptr(new CalendarAttendee());
+        // load name
+        char* attendee_name = NULL;
+        ret = calendar_record_get_str_p(attendee, _calendar_attendee.name, &attendee_name);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee name. Setting an empty string : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            attendee_ptr->setName("");
+        } else {
+            if (attendee_name) {
+                attendee_ptr->setName(attendee_name);
+            }
+        }
+
+        // load URI
+        char* attendee_URI = NULL;
+        ret = calendar_record_get_str_p(attendee, _calendar_attendee.email, &attendee_URI);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee URI. Setting an empty string : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            attendee_ptr->setURI("");
+        } else {
+            if (attendee_URI) {
+                attendee_ptr->setURI(attendee_URI);
+            }
+        }
+
+        // load role
+        int attendee_role = CalendarAttendee::REQ_PARTICIPANT_ROLE;
+        ret = calendar_record_get_int(attendee, _calendar_attendee.role, &attendee_role);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee role. Setting the default value : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        switch (attendee_role) {
+            case CALENDAR_ATTENDEE_ROLE_OPT_PARTICIPANT:
+                attendee_ptr->setRole(CalendarAttendee::OPT_PARTICIPANT_ROLE);
+                break;
+            case CALENDAR_ATTENDEE_ROLE_NON_PARTICIPANT:
+                attendee_ptr->setRole(CalendarAttendee::NON_PARTICIPANT_ROLE);
+                break;
+            case CALENDAR_ATTENDEE_ROLE_CHAIR:
+                attendee_ptr->setRole(CalendarAttendee::CHAIR_ROLE);
+                break;
+            default:
+                attendee_ptr->setRole(CalendarAttendee::REQ_PARTICIPANT_ROLE);
+                break;
+        }
+
+        // load status
+        int attendee_status = CalendarAttendee::PENDING_AT_STATUS;
+        ret = calendar_record_get_int(attendee, _calendar_attendee.status, &attendee_status);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee status. Setting the default value : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        switch (attendee_status) {
+            case CALENDAR_ATTENDEE_STATUS_ACCEPTED:
+                attendee_ptr->setStatus(CalendarAttendee::ACCEPTED_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_DECLINED:
+                attendee_ptr->setStatus(CalendarAttendee::DECLINED_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_TENTATIVE:
+                attendee_ptr->setStatus(CalendarAttendee::TENTATIVE_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_DELEGATED:
+                attendee_ptr->setStatus(CalendarAttendee::DELEGATED_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_COMPLETED:
+                attendee_ptr->setStatus(CalendarAttendee::COMPLETED_AT_STATUS);
+                break;
+            case CALENDAR_ATTENDEE_STATUS_IN_PROCESS:
+                attendee_ptr->setStatus(CalendarAttendee::IN_PROCESS_AT_STATUS);
+                break;
+            default:
+                attendee_ptr->setStatus(CalendarAttendee::PENDING_AT_STATUS);
+                break;
+        }
+
+        // load RSVP
+        int attendee_RSVP = 0;
+        ret = calendar_record_get_int(attendee, _calendar_attendee.rsvp, &attendee_RSVP);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee RSVP. Setting the default value : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        attendee_ptr->setRSVP(attendee_RSVP>0 ? true : false);
+
+        // load type
+        int attendee_type;
+        ret = calendar_record_get_int(attendee, _calendar_attendee.cutype, &attendee_type);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee type. Setting the default value : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        }
+        attendee_ptr->setType(static_cast<CalendarAttendee::CalendarAttendeeType> (attendee_type));
+
+        // load group
+        char* attendee_group = NULL;
+        ret = calendar_record_get_str_p(attendee, _calendar_attendee.group, &attendee_group);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee group. Setting an empty string : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            attendee_ptr->setGroup("");
+        } else {
+            if (attendee_group) {
+                attendee_ptr->setGroup(attendee_group);
+            }
+        }
+
+        // load delegatorURI
+        char* attendee_delegator_URI = NULL;
+        ret = calendar_record_get_str_p(attendee, _calendar_attendee.delegator_uri,
+                &attendee_delegator_URI);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee delegatorURI. Setting an empty string : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            attendee_ptr->setDelegatorURI("");
+        } else {
+            if (attendee_delegator_URI) {
+                attendee_ptr->setDelegatorURI(std::string(attendee_delegator_URI));
+            }
+        }
+        // load delegateURI
+        char* attendee_delegate_URI = NULL;
+        ret = calendar_record_get_str_p(attendee, _calendar_attendee.delegatee_uri,
+                &attendee_delegate_URI);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee delegateURI. Setting an empty string : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            attendee_ptr->setDelegateURI("");
+        } else {
+            if (attendee_delegate_URI) {
+                attendee_ptr->setDelegateURI(std::string(attendee_delegate_URI));
+            }
+        }
+        // load contactId
+        char *attendee_contact_Id = NULL;
+        Contact::ContactRefPtr ref_ptr;
+        if (!attendee_ptr->isContactRefSet()) {
+            ref_ptr.reset(new Contact::ContactRef());
+            attendee_ptr->setContactRef(ref_ptr);
+        }
+        else {
+            ref_ptr = attendee_ptr->getContactRef();
+        }
+        ret = calendar_record_get_str_p(attendee, _calendar_attendee.uid, &attendee_contact_Id);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee UId. Setting an empty string : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            ref_ptr->setContactIdString("");
+        } else {
+            if (attendee_contact_Id) {
+                ref_ptr->setContactIdString(attendee_contact_Id);
+            }
+        }
+
+        // load addressBookId
+        int attendee_address_book_id;
+        ret = calendar_record_get_int(attendee, _calendar_attendee.person_id, &attendee_address_book_id);
+        if (ret != CALENDAR_ERROR_NONE) {
+            LOGW("Cannot read attendee address book id. Setting an empty string : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+            attendee_address_book_id = -1;
+        }
+        std::string id;
+        if (attendee_address_book_id >= 0) {
+            id = std::to_string(attendee_address_book_id);
+        } else {
+            id = "";
+        }
+        ref_ptr->setAddressBookIdString(id);
+
+        try {
+            m_attendees.push_back(attendee_ptr);
+        } catch (...) {
+            LOGE("Exception in push_back function");
+            throw UnknownException("Exception in push_back in setAttendeesFromPlatformCalendarEvent");
+        }
+    }
+    if (list) {
+        calendar_list_destroy(list, true);
+        list = NULL;
+    }
+}
+
+void CalendarTask::setEndDateFromPlatformCalendarItem()
+{
+    LOGD("Entered");
+    int ret;
+    if (NULL == m_platform_item) {
+        LOGE("m_platformEvent is not set");
+        throw UnknownException("m_platformEvent is not set");
+    }
+    calendar_time_s cal;
+    // Retrive the time zone info only when the start time is loaded.
+    char *time_zone = NULL;
+    ret = calendar_record_get_str_p(m_platform_item, _calendar_todo.due_tzid, &time_zone);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get Timezone : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    m_time_zone = std::string(time_zone);
+
+    ret = calendar_record_get_caltime(m_platform_item, _calendar_todo.due_time, &cal);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get due/end time : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+    // if the user use duration he should get the duration not end-date
+    // Set the isAllDay flag also.
+    m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE] = true;
+    if (CALENDAR_TIME_LOCALTIME==cal.type) {
+        m_end_date = CalendarUtility::calTimeToLLI(time_zone, cal);
+        setIsAllDay(true);
+    } else {
+        LOGD("cal.time.utime = %lld, time_zone = %s", cal.time.utime, time_zone);
+        m_end_date = cal.time.utime;
+        if (UNDEFINED_TIME == cal.time.utime) {
+            m_is_set[CALENDAR_ITEM_ATTRIBUTE_END_DATE] = false;
+        }
+        setIsAllDay(false);
+    }
+}
+
+void CalendarTask::setIdFromPlatformCalendarTask()
+{
+    LOGD("Entered");
+    int ret;
+    if (NULL == m_platform_item) {
+        LOGE("core object is not set");
+        throw UnknownException("core object is not set");
+    }
+    int id;
+    ret = calendar_record_get_int(m_platform_item, _calendar_todo.id, &id);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        CalendarUtility::throwCalendarException(ret, "calendar_record_get_int()");
+    }
+    setId(id);
+}
+
+void CalendarTask::setCompletedDateFromPlatformCalendarTask()
+{
+    LOGD("Entered");
+    int ret;
+    if (NULL == m_platform_item) {
+        LOGE("core object is not set");
+        throw UnknownException("core object is not set");
+    }
+
+    long long int completed_date;
+    ret = calendar_record_get_lli(m_platform_item,
+            _calendar_todo.completed_time, &completed_date);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get completed date : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+
+    char *time_zone = NULL;
+    ret = calendar_record_get_str_p(m_platform_item,
+            _calendar_todo.start_tzid, &time_zone);
+    if (ret != CALENDAR_ERROR_NONE) {
+         LOGW("Can't get timeZone : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+    }
+
+    setCompletedDate(completed_date, time_zone);
+}
+
+void CalendarTask::setProgressFromPlatformCalendarTask()
+{
+    LOGD("Entered");
+    int ret;
+    if (NULL == m_platform_item) {
+        LOGE("core object is not set");
+        throw UnknownException("core object is not set");
+    }
+
+    int progress = 0;
+    ret = calendar_record_get_int(m_platform_item,
+            _calendar_todo.progress, &progress);
+    if (ret != CALENDAR_ERROR_NONE) {
+        LOGW("Can't get progress : %d %s", ret, CalendarUtility::getCalendarErrorMessage(ret).c_str());
+        return;
+    }
+    setProgress(progress);
+}
+
+}
+}
+
diff --git a/src/Calendar/CalendarTask.h b/src/Calendar/CalendarTask.h
new file mode 100644 (file)
index 0000000..7b17a86
--- /dev/null
@@ -0,0 +1,116 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        CalendarTask.h
+*/
+
+#ifndef _TIZEN_CALENDAR_TASK_H_
+#define _TIZEN_CALENDAR_TASK_H_
+
+#include "CalendarItem.h"
+#include "CalendarEventId.h"
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class CalendarTask;
+typedef std::shared_ptr<CalendarTask> CalendarTaskPtr;
+typedef std::vector<CalendarTaskPtr> CalendarTaskPtrVector;
+
+enum CalendarTaskAttribute {
+    CALENDAR_TASK_ATTRIBUTE_ID = CalendarItemAttribute::CALENDAR_ITEM_NUMBER_OF_ATTRIBUTES,
+    CALENDAR_TASK_ATTRIBUTE_COMPLETED_DATE,
+    CALENDAR_TASK_ATTRIBUTE_PROGRESS,
+    CALENDAR_TASK_NUMBER_OF_ATTRIBUTES
+};
+
+
+class CalendarTask : public CalendarItem {
+public:
+    CalendarTask();
+    CalendarTask(const CalendarTask &calendar_task);
+    virtual ~CalendarTask();
+
+    int getId() const;
+    void setId(const int value);
+
+    // attribute setters/getters
+    long long int getCompletedDate() const;
+    void setCompletedDate(long long int value, const std::string& time_zone);
+
+    unsigned int getProgress() const;
+    void setProgress(unsigned int value);
+
+    bool isSet(CalendarTaskAttribute attribute) const;
+    void setIsSet(CalendarTaskAttribute attribute, bool is_set);
+
+    calendar_record_h convertAbstractCalendarTaskToPlatformCalendarTask(
+            bool loadBeforeConvert = false);
+    void convertPlatformTaskToAbstractCalendarTask(
+            calendar_record_h platform_task_tmp = NULL);
+
+private:
+    void setCalendarIdToPlatformCalendarItem();
+    void setDescriptionToPlatformCalendarItem();
+    void setSummaryToPlatformCalendarItem();
+    void setIsAllDayAndStartDateToPlatformCalendarItem();
+    void setLocationToPlatformCalendarItem();
+    void setGeolocationToPlatformCalendarItem();
+    void setOrganizerToPlatformCalendarItem();
+    void setVisibilityToPlatformCalendarItem();
+    void setStatusToPlatformCalendarItem();
+    void setPriorityToPlatformCalendarItem();
+    void setAlarmsToPlatformCalendarItem();
+    void setCategoriesToPlatformCalendarItem();
+    void setAttendeesToPlatformCalendarItem();
+    void setEndDateToPlatformCalendarItem();
+    void setCompletedDateToPlatformCalendarTask();
+    void setProgressToPlatformCalendarTask();
+
+    void setCalendarIdFromPlatformCalendarItem();
+    void setLastModifiedDateFromPlatformCalendarItem();
+    void setDescriptionFromPlatformCalendarItem();
+    void setSummaryFromPlatformCalendarItem();
+    void setIsAllDayAndStartDateFromPlatformCalendarItem();
+    void setLocationFromPlatformCalendarItem();
+    void setGeolocationFromPlatformCalendarItem();
+    void setOrganizerFromPlatformCalendarItem();
+    void setVisibilityFromPlatformCalendarItem();
+    void setStatusFromPlatformCalendarItem();
+    void setPriorityFromPlatformCalendarItem();
+    void setAlarmsFromPlatformCalendarItem();
+    void setCategoriesFromPlatformCalendarItem();
+    void setAttendeesFromPlatformCalendarItem();
+    void setEndDateFromPlatformCalendarItem();
+    void setIdFromPlatformCalendarTask();
+    void setCompletedDateFromPlatformCalendarTask();
+    void setProgressFromPlatformCalendarTask();
+
+    int m_id;
+    long long int m_completedDate; //this attribute is used in all date attributes
+    unsigned int m_progress;
+};
+
+}
+}
+
+#endif /* _TIZEN_CALENDAR_TASK_H_ */
diff --git a/src/Calendar/CalendarUtility.cpp b/src/Calendar/CalendarUtility.cpp
new file mode 100755 (executable)
index 0000000..f7ba840
--- /dev/null
@@ -0,0 +1,399 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "CalendarUtility.h"
+#include <unicode/ucal.h>
+#include <unicode/ustring.h>
+#include <unicode/ustdio.h>
+#include <unicode/udat.h>
+#include <Logger.h>
+#include <string>
+#include <map>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+#define ms2sec(ms) (long long int)((ms) / 1000.0)
+#define sec2ms(s) ((s) * 1000.0)
+#define UNDEFINED_TIME -1
+
+void recordDeleterDeep(calendar_record_h* calendar_record)
+{
+    if (*calendar_record) {
+        calendar_record_destroy(*calendar_record, true);
+        *calendar_record = NULL;
+    }
+}
+
+void recordDeleterShallow(calendar_record_h* calendar_record)
+{
+    if (*calendar_record) {
+        calendar_record_destroy(*calendar_record, false);
+        *calendar_record = NULL;
+    }
+}
+
+void queryDeleter(calendar_query_h* calendar_query)
+{
+    if (*calendar_query) {
+        calendar_query_destroy(*calendar_query);
+        *calendar_query = NULL;
+    }
+}
+
+void filterDeleter(calendar_filter_h* calendar_filter)
+{
+    LOGD("ENTERED");
+    if (*calendar_filter) {
+        calendar_filter_destroy(*calendar_filter);
+        *calendar_filter = NULL;
+    }
+}
+
+void listDeleterDeep(calendar_list_h* calendar_list)
+{
+    if (*calendar_list) {
+        calendar_list_destroy(*calendar_list, true);
+        *calendar_list = NULL;
+    }
+}
+
+void listDeleterShallow(calendar_list_h* calendar_list)
+{
+    if (*calendar_list) {
+        calendar_list_destroy(*calendar_list, false);
+        *calendar_list = NULL;
+    }
+}
+
+CalendarUtility::CalendarUtility()
+{
+}
+
+CalendarUtility::~CalendarUtility()
+{
+}
+
+calendar_time_s CalendarUtility::LLIToCalTime(const char* tzid, long long int lli)
+{
+    LOGD("Entered");
+    int y, mon, d;
+    UCalendar *ucal;
+    UErrorCode status = U_ZERO_ERROR;
+
+    calendar_time_s ct = { CALENDAR_TIME_LOCALTIME, { 0 } };
+
+    UChar *_tzid = NULL;
+
+    if (tzid == NULL) {
+        tzid = "Etc/Unknown";
+    }
+    _tzid = (UChar*) calloc(strlen(tzid) + 1, sizeof(UChar));
+    if (_tzid == NULL) {
+        LOGE("Failed to calloc");
+        return ct;
+    }
+    u_uastrcpy(_tzid, tzid);
+
+    LOGD("tzid: %s", tzid);
+
+    ucal = ucal_open(_tzid, u_strlen(_tzid), "en_US", UCAL_TRADITIONAL, &status);
+    if (U_FAILURE(status)) {
+        LOGE("ucal_open failed with %s", u_errorName(status));
+        if (_tzid) free(_tzid);
+        _tzid = NULL;
+        return ct;
+    }
+
+    ucal_setMillis(ucal, sec2ms(lli), &status);
+    if (U_FAILURE(status)) {
+        LOGE("ucal_setMillis failed with %s", u_errorName(status));
+        if (_tzid) free(_tzid);
+        _tzid = NULL;
+        return ct;
+    }
+
+    y = ucal_get(ucal, UCAL_YEAR, &status);
+    mon = ucal_get(ucal, UCAL_MONTH, &status) + 1;
+    d = ucal_get(ucal, UCAL_DATE, &status);
+
+    ct.time.date = {y, mon, d};
+
+    ucal_close(ucal);
+    if (_tzid) free(_tzid);
+    _tzid = NULL;
+
+    return ct;
+}
+
+long long int CalendarUtility::calTimeToLLI(const char* tzid, const calendar_time_s ct)
+{
+    long long int lli;
+    UCalendar *ucal;
+    UErrorCode status = U_ZERO_ERROR;
+
+    UChar *_tzid = NULL;
+
+    if (tzid == NULL) {
+        tzid = "Etc/GMT";
+    }
+    _tzid = (UChar*) calloc(strlen(tzid) + 1, sizeof(UChar));
+    if (_tzid == NULL) {
+        LOGE("Failed to calloc");
+        return -1;
+    }
+    u_uastrcpy(_tzid, tzid);
+
+    LOGD("tzid: %d", tzid);
+
+    ucal = ucal_open(_tzid, u_strlen(_tzid), "en_US", UCAL_TRADITIONAL, &status);
+    if (U_FAILURE(status)) {
+        LOGE("ucal_open failed with %s", u_errorName(status));
+        return -1;
+    }
+
+    ucal_set(ucal, UCAL_YEAR, ct.time.date.year);
+    ucal_set(ucal, UCAL_MONTH, ct.time.date.month - 1);
+    ucal_set(ucal, UCAL_DATE, ct.time.date.mday);
+    ucal_set(ucal, UCAL_HOUR_OF_DAY, 0);
+    ucal_set(ucal, UCAL_MINUTE, 0);
+    ucal_set(ucal, UCAL_SECOND, 0);
+
+    lli = ms2sec(ucal_getMillis(ucal, &status));
+    ucal_close(ucal);
+    if (_tzid) free(_tzid);
+    _tzid = NULL;
+
+    LOGD("converted time: %lld", lli);
+
+    return lli;
+}
+
+typedef std::shared_ptr<UCalendar> UCalendarPtr;
+typedef std::map<std::string, UCalendarPtr> UCalendarTimeZonesMap;
+
+static UCalendarTimeZonesMap s_ucal_timezone_map;
+
+void UCalendarPtrDeleter(UCalendar* ucal)
+{
+    ucal_close(ucal);
+}
+
+UCalendarPtr getUCalendarForTimeZone(const char* timezone)
+{
+    UCalendarTimeZonesMap::iterator it = s_ucal_timezone_map.find(timezone);
+    if (it != s_ucal_timezone_map.end()) {
+        return it->second;
+    }
+
+    UChar *_tzid = (UChar*) calloc(strlen(timezone) + 1, sizeof(UChar));
+    if (NULL == _tzid) {
+        return UCalendarPtr();
+    }
+
+    u_uastrcpy(_tzid, timezone);
+
+    UErrorCode status = U_ZERO_ERROR;
+    UCalendar* ucal = ucal_open(_tzid, u_strlen(_tzid), "en_US", UCAL_TRADITIONAL, &status);
+    if (U_FAILURE(status)) {
+        LOGE("ucal_open failed %s", u_errorName(status));
+        if (_tzid) free(_tzid);
+        return UCalendarPtr();
+    }
+
+    UCalendarPtr sharedUCalendar = UCalendarPtr(ucal, UCalendarPtrDeleter);
+    s_ucal_timezone_map[timezone] = sharedUCalendar;
+
+    if (_tzid) free(_tzid);
+    return sharedUCalendar;
+}
+
+long long int CalendarUtility::localTimeToUTCTime(const char *tzid, int y, int mon, int d, int h, int min, int s)
+{
+    long long int lli;
+    UCalendar* ucal = NULL;
+    UErrorCode status = U_ZERO_ERROR;
+
+    if (NULL == tzid) {
+        tzid = "Etc/GMT";
+    }
+
+    UCalendarPtr ucalendar_shared = getUCalendarForTimeZone(tzid);
+    if (!ucalendar_shared) {
+        LOGE("couldn't get UCalendar for timezone: %s", tzid);
+        return -1;
+    }
+    ucal = ucalendar_shared.get();
+
+    LOGD("year = %d, month = %d, day = %d, hours = %d, minutes = %d, seconds = %d, timezone = %s",
+                y, mon, d, h, min, s, tzid);
+    ucal_set(ucal, UCAL_YEAR, y);
+    ucal_set(ucal, UCAL_MONTH, mon);
+    ucal_set(ucal, UCAL_DATE, d);
+    ucal_set(ucal, UCAL_HOUR_OF_DAY, h);
+    ucal_set(ucal, UCAL_MINUTE, min);
+    ucal_set(ucal, UCAL_SECOND, s);
+
+    lli = ms2sec(ucal_getMillis(ucal, &status));
+    LOGD("UTC = %d", lli);
+
+    return lli;
+}
+
+long long int CalendarUtility::localTimeToUTCTime(DeviceAPI::Time::TZDatePtr tz_date)
+{
+    LOGD("Entered");
+    if (!tz_date) return UNDEFINED_TIME;
+    int y = tz_date->getFullYear();
+    int mon = tz_date->getMonth();
+    int d = tz_date->getDate();
+    int h = tz_date->getHours();
+    int min = tz_date->getMinutes();
+    int s = tz_date->getSeconds();
+
+    long long int lli = CalendarUtility::localTimeToUTCTime((tz_date->getTimezone()).c_str(), y, mon, d, h, min, s);
+    return lli;
+}
+
+DeviceAPI::Time::TZDatePtr CalendarUtility::utcTimeToTZDate(const char *tzid, long long int lli, bool timezone_is_certain)
+{
+    LOGD("Entered");
+    DeviceAPI::Time::TZDatePtr date_ptr(new DeviceAPI::Time::TZDate(0, 0, 0));
+    if (!date_ptr) {
+        LOGE("Memory allocation error");
+        throw DeviceAPI::Common::UnknownException("Memory allocation error");
+    }
+
+    if (UNDEFINED_TIME == lli) {
+        return date_ptr;
+    }
+
+    int year, month, day, hours, minutes, seconds, milliseconds;
+    UCalendar *ucal;
+    UErrorCode status = U_ZERO_ERROR;
+    UChar *_tzid = NULL;
+    std::string timezone;
+    if (NULL == tzid) {
+        tzid = "Etc/Unknown";
+        timezone = "";
+    } else {
+        timezone = std::string(tzid);
+    }
+    _tzid = (UChar*) calloc(strlen(tzid) + 1, sizeof(UChar));
+    if (NULL == _tzid) {
+        LOGE("Failed to calloc");
+        return date_ptr;
+    }
+    u_uastrcpy(_tzid, tzid);
+
+    LOGD("tzid: %s", tzid);
+    ucal = ucal_open(_tzid, u_strlen(_tzid), "en_US", UCAL_TRADITIONAL, &status);
+    if (U_FAILURE(status)) {
+        LOGE("ucal_open failed with %s", u_errorName(status));
+        return date_ptr;
+    }
+    ucal_setMillis(ucal, sec2ms(lli), &status);
+
+    if (U_FAILURE(status)) {
+        LOGE("ucal_setMillis failed with %s", u_errorName(status));
+        return date_ptr;
+    }
+
+    year = ucal_get(ucal, UCAL_YEAR, &status);
+    month = ucal_get(ucal, UCAL_MONTH, &status);
+    day = ucal_get(ucal, UCAL_DATE, &status);
+    hours = ucal_get(ucal, UCAL_HOUR_OF_DAY, &status);
+    minutes = ucal_get(ucal, UCAL_MINUTE, &status);
+    seconds = ucal_get(ucal, UCAL_SECOND, &status);
+    milliseconds = ucal_get(ucal, UCAL_MILLISECOND, &status);
+
+    date_ptr->setFullYear(year);
+    date_ptr->setMonth(month);
+    date_ptr->setDate(day);
+    date_ptr->setHours(hours);
+    date_ptr->setMinutes(minutes);
+    date_ptr->setSeconds(seconds);
+    date_ptr->setMilliseconds(milliseconds);
+    date_ptr->setTimezone(timezone, timezone_is_certain);
+
+    LOGD("year = %d, month = %d, day = %d, hours = %d, minutes = %d, seconds = %d, milliseconds = %d, timezone = %s",
+            year, month, day, hours, minutes, seconds, milliseconds, timezone.c_str());
+
+    ucal_close(ucal);
+    if (_tzid) free(_tzid);
+    _tzid = NULL;
+    return date_ptr;
+}
+
+int CalendarUtility::toIntId(const std::string& value)
+{
+    int result;
+    char *end;
+    result = std::strtol(value.c_str(), &end, 10);
+
+    if (value[0] == '\0' || *end != '\0' || result < 0) {
+        std::string msg = "Value " + value + " is invalid";
+        LOGE("Conversion failed");
+        throw Common::NotFoundException(msg.c_str());
+    }
+
+    return result;
+}
+
+std::string& CalendarUtility::getCalendarErrorMessage(const int errorCode) {
+    switch(errorCode) {
+        case CALENDAR_ERROR_OUT_OF_MEMORY:
+            return errOutOfMemory;
+        case CALENDAR_ERROR_INVALID_PARAMETER:
+            return errInvalidParameter;
+        case CALENDAR_ERROR_NO_DATA:
+            return errNoData;
+        case CALENDAR_ERROR_NOW_IN_PROGRESS:
+            return errNowInProgress;
+        case CALENDAR_ERROR_ALREADY_IN_PROGRESS:
+            return errAlreadyInProgress;
+        case CALENDAR_ERROR_NOT_PERMITTED:
+            return errNotPermitted;
+        case CALENDAR_ERROR_FILE_NO_SPACE:
+            return errFileNoSpace;
+        case CALENDAR_ERROR_PERMISSION_DENIED:
+            return errPermissionDenied;
+        case CALENDAR_ERROR_DB_FAILED:
+            return errDBFailed;
+        case CALENDAR_ERROR_ITERATOR_END:
+            return errIteratorEnd;
+        case CALENDAR_ERROR_DB_RECORD_NOT_FOUND:
+            return errDBRecordNotFound;
+        case CALENDAR_ERROR_IPC:
+            return errIPC;
+        case CALENDAR_ERROR_SYSTEM:
+            return errIteratorEnd;
+        default:
+            return errUnknown;
+    }
+}
+
+std::string CalendarUtility::getCalendarLogMessage(const int errorCode, const std::string &hint) {
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getCalendarErrorMessage(errorCode) << ", " << errorCode;
+    return std::string(ss.str());
+}
+
+
+} // Calendar
+} // DeviceAPI
diff --git a/src/Calendar/CalendarUtility.h b/src/Calendar/CalendarUtility.h
new file mode 100644 (file)
index 0000000..ccd3e14
--- /dev/null
@@ -0,0 +1,159 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _CALENDAR_UTILITY_H_
+#define _CALENDAR_UTILITY_H_
+
+#include <calendar.h>
+#include <TZDate.h>
+#include <PlatformException.h>
+#include <Logger.h>
+namespace DeviceAPI {
+namespace Calendar {
+
+void recordDeleterDeep(calendar_record_h* calendar_record);
+void recordDeleterShallow(calendar_record_h* calendar_record);
+typedef std::unique_ptr<calendar_record_h, void(*)(calendar_record_h *)> calendar_record_h_ptr;
+
+void queryDeleter(calendar_query_h* calendar_query);
+typedef std::unique_ptr<calendar_query_h, void(*)(calendar_query_h *)> calendar_query_h_ptr;
+
+void filterDeleter(calendar_filter_h* calendar_filter);
+typedef std::unique_ptr<calendar_filter_h, void(*)(calendar_filter_h*)> calendar_filter_h_ptr;
+typedef std::shared_ptr<calendar_filter_h> calendar_filter_shared_ptr;
+
+void listDeleterDeep(calendar_list_h* calendar_list);
+void listDeleterShallow(calendar_list_h* calendar_list);
+typedef std::unique_ptr<calendar_list_h, void(*)(calendar_list_h*)> calendar_list_h_ptr;
+
+static std::string errOutOfMemory = "Out of memory";
+static std::string errInvalidParameter = "Invalid parameter";
+static std::string errNoData = "Requested data does not exist";
+static std::string errNowInProgress = "Operation now in progress";
+static std::string errAlreadyInProgress = "Operation already in progress";
+static std::string errNotPermitted = "Operation not permitted";
+static std::string errFileNoSpace = "FS is full";
+static std::string errPermissionDenied = "Permission denied";
+static std::string errDBFailed = "No access to the database";
+static std::string errIteratorEnd = "Iterator is on the last position";
+static std::string errDBRecordNotFound = "Database not found";
+static std::string errIPC = "Unknown IPC error";
+static std::string errSystem = "Error from another modules";
+static std::string errUnknown = "Unknown error";
+
+class CalendarUtility
+{
+public:
+    enum CalendarType {
+        UNDEFINED = CALENDAR_BOOK_TYPE_NONE,
+        EVENT = CALENDAR_BOOK_TYPE_EVENT,
+        TASK = CALENDAR_BOOK_TYPE_TODO
+    };
+
+    CalendarUtility();
+    virtual ~CalendarUtility();
+
+    static calendar_time_s LLIToCalTime(const char* tzid, long long int lli);
+    static long long int calTimeToLLI(const char* tzid, const calendar_time_s ct);
+
+    static long long int localTimeToUTCTime(DeviceAPI::Time::TZDatePtr tz_date);
+    static long long int localTimeToUTCTime(const char *tzid,
+            int y,
+            int mon,
+            int d,
+            int h,
+            int min,
+            int s);
+    static DeviceAPI::Time::TZDatePtr utcTimeToTZDate(const char *tzid,
+            long long int lli, bool timezone_is_certain = false);
+
+    static int toIntId(const std::string& value);
+    /**
+     * Function converts vector of shared_pointers into JSArray
+     */
+    template<class T, class U>
+    static JSObjectRef vectorToJSObjectArray(JSContextRef context,
+            const std::vector<T> & vec) {
+        size_t count = vec.size();
+        JSObjectRef array[count];
+        for (size_t i = 0; i < count; ++i) {
+            array[i] = U::makeJSObject(context, vec[i]);
+        }
+
+        JSObjectRef result = JSObjectMakeArray(context, count,
+                count > 0 ? array : NULL, NULL);
+        if (!result) {
+            LOGW("Failed to create array");
+            throw Common::UnknownException("Failed to create array");
+        }
+        return result;
+    }
+
+    template<class BasePtr, class Child, class JSChild>
+    static JSObjectRef vectorToJSObjectArray(JSContextRef context,
+            const std::vector<BasePtr> & vec) {
+        size_t count = vec.size();
+
+        JSObjectRef array[count];
+        for (size_t i = 0; i < count; ++i) {
+            array[i] = JSChild::makeJSObject(context, std::dynamic_pointer_cast<Child>(vec[i]));
+        }
+
+        JSObjectRef result = JSObjectMakeArray(context, count,
+                count > 0 ? array : NULL, NULL);
+        if (!result) {
+            LOGW("Failed to create array");
+            throw Common::UnknownException("Failed to create array");
+        }
+        return result;
+    }
+
+    template<class T, class U>
+    static std::vector<T> cloneVector(const std::vector<T> &vec)
+    {
+        LOGE("Entered");
+        std::vector<T> cloned_vec;
+        const size_t vec_size = vec.size();
+        cloned_vec.reserve(vec_size);
+
+        for (size_t i = 0; i < vec_size; i++) {
+            T clone = T(new(std::nothrow) U());
+            if (!clone) {
+                LOGW("Clone is null");
+                throw Common::UnknownException("Clone is null");
+            }
+            *(clone) = *(vec[i]);
+            cloned_vec.push_back(clone);
+        }
+        return cloned_vec;
+    }
+
+    template<class T = DeviceAPI::Common::UnknownException>
+    static void throwCalendarException(const int errorCode, const std::string &hint)
+    {
+        std::string log = CalendarUtility::getCalendarLogMessage(errorCode, hint);
+        LOGE("%s", log.c_str());
+        throw T(log.c_str());
+    }
+    static std::string& getCalendarErrorMessage(const int errorCode);
+    static std::string getCalendarLogMessage(const int errorCode, const std::string &hint);
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif // _CALENDAR_UTILITY_H_
diff --git a/src/Calendar/ChangeListenerContainer.cpp b/src/Calendar/ChangeListenerContainer.cpp
new file mode 100755 (executable)
index 0000000..08e00f9
--- /dev/null
@@ -0,0 +1,174 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include "ChangeListenerContainer.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+
+ChangeListenerContainer::ChangeListenerContainer():
+        m_current_id_count(0)
+{
+    LOGD("Entered");
+}
+
+// --- Listeners registration functions ---
+long ChangeListenerContainer::addChangeListener(
+        std::shared_ptr<CalendarChangeCallback> callback)
+{
+    LOGD("Entered");
+    // Check type of service for which listener should be registered
+    long listener_id = ++m_current_id_count;
+
+    m_calendar_callbacks.insert(std::make_pair(listener_id, callback));
+    LOGD("Added callback for Calendar, watchId: %d", listener_id);
+    return listener_id;
+
+}
+
+void ChangeListenerContainer::callCalendarAdded(EventCalendar event)
+{
+    LOGD("Entered");
+
+    CCLmap calendar_callbacks;
+    {
+        calendar_callbacks = m_calendar_callbacks;
+    }
+    std::map<long,std::shared_ptr<CalendarChangeCallback>>::iterator itstart =
+            calendar_callbacks.begin();
+    std::map<long,std::shared_ptr<CalendarChangeCallback>>::iterator itend =
+            calendar_callbacks.end();
+    for (; itstart != itend; ++itstart) {
+            if ((*itstart).second->getCalendarId() == event.calendar_id) {
+                LOGD("Found callback for given calendar id (%d) ",
+                        event.calendar_id);
+                if (CalendarUtility::CalendarType::EVENT == event.type) {
+                    (*itstart).second->addedEvents(event.events);
+                } else {
+                    (*itstart).second->addedTasks(event.tasks);
+                }
+            }
+    }
+}
+
+void ChangeListenerContainer::callCalendarUpdated(EventCalendar event)
+{
+    LOGD("Entered");
+
+    CCLmap calendar_callbacks;
+    {
+        calendar_callbacks = m_calendar_callbacks;
+    }
+    std::map<long,std::shared_ptr<CalendarChangeCallback>>::iterator itstart =
+            calendar_callbacks.begin();
+    std::map<long,std::shared_ptr<CalendarChangeCallback>>::iterator itend =
+            calendar_callbacks.end();
+    for (; itstart != itend; ++itstart) {
+            if ((*itstart).second->getCalendarId() == event.calendar_id) {
+                LOGD("Found callback for given calendar id (%d) ",
+                        event.calendar_id);
+                if (CalendarUtility::CalendarType::EVENT == event.type) {
+                    (*itstart).second->updatedEvents(event.events);
+                } else {
+                    (*itstart).second->updatedTasks(event.tasks);
+                }
+            }
+    }
+}
+
+void ChangeListenerContainer::callCalendarRemoved(EventCalendarId event)
+{
+    LOGD("Entered");
+
+    CCLmap calendar_callbacks;
+    {
+        calendar_callbacks = m_calendar_callbacks;
+    }
+    std::map<long,std::shared_ptr<CalendarChangeCallback>>::iterator itstart =
+            calendar_callbacks.begin();
+    std::map<long,std::shared_ptr<CalendarChangeCallback>>::iterator itend =
+            calendar_callbacks.end();
+    for (; itstart != itend; ++itstart) {
+            if ((*itstart).second->getCalendarId() == event.calendar_id) {
+                if (CalendarUtility::CalendarType::EVENT == event.type) {
+                    (*itstart).second->removedEvent(event.event_id);
+                } else {
+                    (*itstart).second->removedTask(event.task_id);
+                }
+            }
+    }
+}
+// --- listeners removal ---
+void ChangeListenerContainer::removeChangeListener(const JSContextRef context, long id)
+{
+    LOGD("Entered");
+    if (id<0 || id > m_current_id_count) {
+        LOGE("Invalid id %d given.", id);
+        return;
+    }
+    auto callback_iterator = m_calendar_callbacks.find(id);
+    if (m_calendar_callbacks.end() != callback_iterator) {
+        JSContextRef local_context = callback_iterator->second->getContext();
+        if (GlobalContextManager::getInstance()->getGlobalContext(context) != local_context) {
+            LOGE("Listener is not in the correct context");
+            throw NotFoundException("No listener with such id in the correct context");
+        }
+        callback_iterator->second->setActive(false);
+        m_calendar_callbacks.erase(callback_iterator);
+        LOGD("Calendar listener with %d removed", id);
+    }
+    else {
+        LOGW("WatchId %d not found", id);
+    }
+}
+
+void ChangeListenerContainer::removeAllChangeListener(long calendar_id)
+{
+    LOGD("Entered");
+    std::vector<long> calendar_id_vector;
+    auto it = m_calendar_callbacks.begin();
+    auto it_end = m_calendar_callbacks.end();
+
+    for (; it != it_end; ++it) {
+        if (it->second->getCalendarId() == calendar_id) {
+            calendar_id_vector.push_back(it->first);
+        }
+    }
+    unsigned int calendar_id_vector_size = calendar_id_vector.size();;
+    for (unsigned int i = 0; i < calendar_id_vector_size; ++i) {
+        m_calendar_callbacks[calendar_id_vector[i]]->setActive(false);
+        if (m_calendar_callbacks.erase(calendar_id_vector[i]) > 0) {
+            LOGD("Calendar listener with %d removed", calendar_id_vector[i]);
+        }
+        else {
+            LOGW("WatchId %d not found", calendar_id_vector[i]);
+        }
+    }
+}
+
+bool ChangeListenerContainer::isEmpty()
+{
+    return m_calendar_callbacks.empty();
+}
+
+}
+}
diff --git a/src/Calendar/ChangeListenerContainer.h b/src/Calendar/ChangeListenerContainer.h
new file mode 100644 (file)
index 0000000..e440c62
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CHANGE_LISTENER_CONTAINER_H__
+#define __TIZEN_CHANGE_LISTENER_CONTAINER_H__
+
+#include <memory>
+#include <mutex>
+#include <vector>
+#include <map>
+#include <Logger.h>
+
+#include "CalendarChangeCallback.h"
+#include "CalendarUtility.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+struct EventCalendar {
+    int calendar_id;
+    CalendarUtility::CalendarType type;
+    CalendarEventPtrVector events;
+    CalendarTaskPtrVector tasks;
+};
+typedef std::vector<EventCalendar> EventCalendarVector;
+
+typedef std::vector<int> TaskIdVector;
+
+struct EventCalendarId {
+    CalendarEventIdPtrVector event_id;
+    TaskIdVector task_id;
+    int calendar_id;
+    CalendarUtility::CalendarType type;
+};
+
+typedef std::vector<EventCalendarId> EventCalendarIdVector;
+
+class CalendarChangeCallback;
+
+typedef std::map<long, std::shared_ptr<CalendarChangeCallback>> CCLmap;
+
+class ChangeListenerContainer {
+    public:
+        ChangeListenerContainer();
+        // Interface for listener's manipulation (registration and removal).
+        long addChangeListener(std::shared_ptr<CalendarChangeCallback> callback);
+        void removeChangeListener(const JSContextRef context, long id);
+        void removeAllChangeListener(long calendar_id);
+
+        void callCalendarAdded(EventCalendar event);
+        void callCalendarUpdated(EventCalendar event);
+        void callCalendarRemoved(EventCalendarId event);
+        bool isEmpty();
+
+    private:
+        //! Highest used id (in most cases id of last registered listener)
+        long m_current_id_count;
+
+        CCLmap m_calendar_callbacks;
+};
+
+}
+}
+
+#endif /* __TIZEN_CHANGE_LISTENER_CONTAINER_H__ */
diff --git a/src/Calendar/JSCalendar.cpp b/src/Calendar/JSCalendar.cpp
new file mode 100755 (executable)
index 0000000..07d885c
--- /dev/null
@@ -0,0 +1,818 @@
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <TimeTracer.h>
+#include <Logger.h>
+#include <Export.h>
+#include <SecurityExceptions.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <CommonsJavaScript/Converter.h>
+#include <GlobalContextManager.h>
+#include <JSSortMode.h>
+
+#include "JSCalendar.h"
+#include "JSCalendarManager.h"
+#include "JSCalendarEvent.h"
+#include "JSCalendarEventId.h"
+#include "JSCalendarTask.h"
+#include "JSCalendarItem.h"
+#include "JSCalendarEventId.h"
+#include "CalendarManager.h"
+#include "CalendarFindCallbackData.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace {
+const char* CALENDAR_ATTRIBUTENAME = "Calendar";
+
+const char* CALENDAR_PROPERTY_ID = "id";
+const char* CALENDAR_PROPERTY_NAME = "name";
+const char* CALENDAR_PROPERTY_ACCOUNT_ID = "accountId";
+}
+
+JSClassDefinition JSCalendar::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CALENDAR_ATTRIBUTENAME,
+        NULL,
+        m_property,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL //ConvertToType
+        };
+
+JSStaticFunction JSCalendar::m_function[] = {
+    { CALENDAR_FUNCTION_API_ADD, add, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_ADD_BATCH, addBatch, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_UPDATE, update, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_UPDATE_BATCH, updateBatch, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_REMOVE, remove, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_REMOVE_BATCH, removeBatch, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_FIND, find, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_ADD_CHANGE_LISTENER, addChangeListener, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_REMOVE_CHANGE_LISTENER, removeChangeListener, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_GET, get, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSStaticValue JSCalendar::m_property[] = {
+    { CALENDAR_PROPERTY_ID, getId, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CALENDAR_PROPERTY_NAME, getName, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CALENDAR_PROPERTY_ACCOUNT_ID, getAccountId, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { 0,0,0,0 }
+};
+
+
+JSClassRef JSCalendar::m_jsClassRef = JSClassCreate(JSCalendar::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSCalendar::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSCalendar::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+CalendarPtr JSCalendar::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    CalendarHolder* priv = static_cast<CalendarHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+    return priv->ptr;
+}
+
+JSObjectRef JSCalendar::makeJSObject(JSContextRef context, CalendarPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    CalendarHolder* priv = new (std::nothrow) CalendarHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+    priv->ptr->copyAceCheckAccessFunction(CalendarManager::getInstance());
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),static_cast<void*>(priv));
+    if (!obj) {
+        LOGE("Object creation failed");
+        throw UnknownException("Object creation failed");
+    }
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSCalendar::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObj = JSObjectMake(context, getClassRef(), NULL);
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObj, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum,
+        NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        // accountId
+        unsigned long accountId = validator.toULong(0);
+        if (validator.isOmitted(0)) {
+            throw TypeMismatchException("accountId parameter is missed");
+        }
+        if (!Calendar::isValidAccount(static_cast<long>(accountId))) {
+            throw InvalidValuesException("accountId is invalid");
+        }
+
+        // name
+        std::string name = validator.toString(1);
+        if (validator.isOmitted(1)) {
+            throw TypeMismatchException("calendar name parameter is missed");
+        }
+
+        // type
+        std::string type = validator.toString(2);
+        if (validator.isOmitted(2)) {
+            throw TypeMismatchException("calendar type parameter is missed");
+        }
+
+        CalendarPtr priv = CalendarPtr(new(std::nothrow) Calendar());
+        priv->setName(name);
+        priv->setAccountId(static_cast<long>(accountId));
+        priv->setType(Calendar::stringToCalendarType(type));
+
+        CalendarHolder *holder = new(std::nothrow) CalendarHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        holder->ptr->copyAceCheckAccessFunction(CalendarManager::getInstance());
+        JSObjectSetPrivate(jsObj, static_cast<void *>(holder));
+    } catch (const BasePlatformException& err) {
+        LOGE("Calendar creation failed %s, %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("Calendar creation failed");
+    }
+    return jsObj;
+}
+
+void JSCalendar::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSCalendar::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    CalendarHolder* priv = static_cast<CalendarHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSCalendar::add(JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try {
+
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), CALENDAR_FUNCTION_API_ADD);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        if (CalendarUtility::EVENT == priv->getType()) {
+            CalendarEventPtr event = JSCalendarEvent::getPrivateObject(context,
+                validator.toObject(0, JSCalendarEvent::getClassRef()));
+            priv->addEvent(event);
+        } else if (CalendarUtility::TASK == priv->getType()) {
+            CalendarTaskPtr task = JSCalendarTask::getPrivateObject(context,
+                validator.toObject(0, JSCalendarTask::getClassRef()));
+            priv->addTask(task);
+        }
+        else {
+            LOGE("Wrong item type");
+            throw TypeMismatchException("Wrong item type");
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("add failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("add failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::get(JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try {
+
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), CALENDAR_FUNCTION_API_GET);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        if (CalendarUtility::EVENT == priv->getType()) {
+            CalendarEventIdPtr eventIdPtr = JSCalendarEventId::getPrivateObject(
+                    context, validator.toObject(0));
+            return JSCalendarEvent::makeJSObject(context, priv->getEvent(eventIdPtr));
+        } else if (CalendarUtility::TASK == priv->getType()) {
+            std::string s_id = validator.toString(0);
+            long id = CalendarUtility::toIntId(s_id);
+            CalendarTaskPtr taskPtr = priv->getTask(id);
+            if (!taskPtr) {
+                LOGE("taskId is null.");
+                throw UnknownException("taskId is null.");
+            }
+            return JSCalendarTask::makeJSObject(context, taskPtr);
+        }
+        else {
+            LOGE("Wrong item type");
+            throw TypeMismatchException("Wrong item type");
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("get failed caught: name: %s, msg: %s",
+            err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("get failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+JSValueRef JSCalendar::addBatch(JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGE("Entered");
+    CalendarCallbackUserData *cbdata = NULL;
+    try {
+
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CALENDAR_FUNCTION_API_ADD_BATCH);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::vector<JSValueRef> items = validator.toJSValueRefVector(0);
+
+        std::vector<CalendarEventPtr> eventPtrVector;
+        std::vector<CalendarTaskPtr> tasksPtrVector;
+        const size_t size = items.size();
+        if (CalendarUtility::EVENT == priv->getType()) {
+            eventPtrVector.reserve(size);
+            for (unsigned int i = 0; i < size; ++i) {
+                eventPtrVector.push_back(JSCalendarEvent::getPrivateObject(context,items[i]));
+            }
+        } else if (CalendarUtility::TASK == priv->getType()) {
+            tasksPtrVector.reserve(size);
+            for (unsigned int i = 0; i < size; ++i) {
+                tasksPtrVector.push_back(JSCalendarTask::getPrivateObject(context,items[i]));
+            }
+        } else {
+            LOGE("Wrong item type");
+            throw TypeMismatchException("Wrong item type");
+        }
+        cbdata = new CalendarCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context), eventPtrVector, tasksPtrVector, priv);
+        if (!cbdata) {
+            LOGE("Failed to create callback data.");
+            throw UnknownException("Failed to create callback data.");
+        }
+        cbdata->setSuccessCallback(validator.toFunction(1, true));
+        cbdata->setErrorCallback(validator.toFunction(2, true));
+        priv->addBatch(cbdata);
+    } catch (const BasePlatformException &error) {
+        delete cbdata;
+        cbdata = NULL;
+        LOGE("add failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("addBatch failed - Unknown Error");
+        delete cbdata;
+        cbdata = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::update(JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try {
+
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), CALENDAR_FUNCTION_API_UPDATE);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        bool updateAll = validator.toBool(1, true, true);
+        if (CalendarUtility::EVENT == priv->getType()) {
+            CalendarEventPtr event = JSCalendarEvent::getPrivateObject(context,
+                    validator.toObject(0, JSCalendarEvent::getClassRef()));
+            priv->updateEvent(event, updateAll);
+        } else if (CalendarUtility::TASK == priv->getType()) {
+            CalendarTaskPtr task = JSCalendarTask::getPrivateObject(context,
+                    validator.toObject(0, JSCalendarTask::getClassRef()));
+            priv->updateTask(task);
+        }
+        else {
+            LOGE("Wrong item type");
+            throw TypeMismatchException("Wrong item type");
+        }
+    } catch (const BasePlatformException &error) {
+        LOGE("add failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("Update failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::updateBatch(JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    CalendarCallbackUserData *cbdata = NULL;
+    try {
+
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CALENDAR_FUNCTION_API_UPDATE_BATCH);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::vector<JSValueRef> items = validator.toJSValueRefVector(0);
+
+        std::vector<CalendarEventPtr> eventPtrVector;
+        std::vector<CalendarTaskPtr> tasksPtrVector;
+        const size_t size = items.size();
+
+        if (CalendarUtility::EVENT == priv->getType()) {
+            eventPtrVector.reserve(size);
+            for (unsigned int i = 0; i < size; ++i) {
+                eventPtrVector.push_back(JSCalendarEvent::getPrivateObject(context,items[i]));
+            }
+
+        } else if (CalendarUtility::TASK == priv->getType()) {
+            tasksPtrVector.reserve(size);
+            for (unsigned int i = 0; i < size; ++i) {
+                tasksPtrVector.push_back(JSCalendarTask::getPrivateObject(context,items[i]));
+            }
+        } else {
+            LOGE("Wrong item type");
+            throw TypeMismatchException("Wrong item type");
+        }
+
+        cbdata = new CalendarCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context), eventPtrVector, tasksPtrVector, priv);
+        if (!cbdata) {
+            LOGE("Failed to create callback data.");
+            throw UnknownException("Failed to create callback data.");
+        }
+
+        cbdata->setSuccessCallback(validator.toFunction(1, true));
+        cbdata->setErrorCallback(validator.toFunction(2, true));
+        cbdata->setAllInstances(validator.toBool(3, true));
+
+        priv->updateBatch(cbdata);
+
+    } catch (const BasePlatformException &error) {
+        delete cbdata;
+        cbdata = NULL;
+        LOGE("add failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("updateBatch failed - Unknown Error");
+        delete cbdata;
+        cbdata = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::remove(JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+
+    try {
+
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), CALENDAR_FUNCTION_API_REMOVE);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        if (CalendarUtility::EVENT == priv->getType()) {
+            CalendarEventIdPtr eventIdPtr = JSCalendarEventId::getPrivateObject(
+                context, validator.toObject(0));
+            priv->removeEvent(eventIdPtr);
+        } else if (CalendarUtility::TASK == priv->getType()) {
+            std::string s_id = validator.toString(0);
+            long id = CalendarUtility::toIntId(s_id);
+            priv->removeTask(id);
+       } else {
+           throw TypeMismatchException("Wrong item type");
+       }
+    } catch (const BasePlatformException &error) {
+        LOGE("remove failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("remowe failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::removeBatch(JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    CalendarCallbackUserData *cbdata = NULL;
+    try {
+
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CALENDAR_FUNCTION_API_REMOVE_BATCH);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::vector<JSValueRef> itemsId = validator.toJSValueRefVector(0);
+        if (0 == itemsId.size()) {
+            LOGE("List of items is empty");
+            throw UnknownException("List of items is empty");
+        }
+        std::vector<CalendarEventIdPtr> eventIdPtrVector;
+        std::vector<int> tasksLongIdVector;
+        const size_t size = itemsId.size();
+
+        if (CalendarUtility::EVENT == priv->getType()) {
+            eventIdPtrVector.reserve(size);
+            for (unsigned int i = 0; i< size; ++i) {
+                eventIdPtrVector.push_back(JSCalendarEventId::
+                        getPrivateObject(context,itemsId[i]));
+            }
+        } else if (CalendarUtility::TASK == priv->getType()) {
+            tasksLongIdVector.reserve(size);
+            for (unsigned int i = 0; i< size; ++i) {
+                tasksLongIdVector.push_back(JSUtil::JSValueToLong(context, itemsId[i]));
+            }
+        } else {
+            LOGE("Wrong item type");
+            throw TypeMismatchException("Wrong item type");
+        }
+
+        cbdata = new CalendarCallbackUserData(GlobalContextManager::getInstance()->
+                getGlobalContext(context), eventIdPtrVector, tasksLongIdVector, priv);
+
+        if (!cbdata) {
+            LOGE("Failed to create callback data.");
+            throw UnknownException("Failed to create callback data.");
+        }
+        if (cbdata->m_events_ids.size() > 0 || cbdata->m_tasks_ids.size() > 0) {
+            cbdata->setSuccessCallback(validator.toFunction(1, true));
+            cbdata->setErrorCallback(validator.toFunction(2, true));
+            priv->removeBatch(cbdata);
+        }
+        else{
+            LOGE("That could not happen.");
+            delete cbdata;
+            cbdata = NULL;
+            throw UnknownException("Unknown Exception");
+        }
+
+    } catch (const BasePlatformException &error) {
+        delete cbdata;
+        cbdata = NULL;
+        LOGE("add failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("updateBatch failed - Unknown Error");
+        delete cbdata;
+        cbdata = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::find(JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    CalendarFindCallbackData *callback = NULL;;
+    try {
+
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), CALENDAR_FUNCTION_API_FIND);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        callback = new CalendarFindCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(0, false));
+        callback->setErrorCallback(validator.toFunction(1, true));
+
+        JSObjectRef filter = validator.toObject(2, true);
+        JSObjectRef sort_mode = validator.toObject(3, true);
+
+        if (filter) {
+            callback->setFilter(Tizen::AbstractFilter::getPrivateObject(
+                    context, filter));
+        }
+        if (sort_mode) {
+            callback->setSortMode(Tizen::JSSortMode::getPrivateObject(
+                    context, sort_mode));
+        }
+
+        callback->setCalendarId(priv->getId());
+        callback->setType(priv->getType());
+
+        priv->find(callback);
+    }
+    catch (const WrtDeviceApis::Commons::Exception& exc) {
+        delete callback;
+        callback = NULL;
+        LOGE("Wrong filer/sort mode: %s", exc.GetMessage().c_str());
+        Common::TypeMismatchException err(exc.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (const BasePlatformException &err) {
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        delete callback;
+        callback = NULL;
+        DeviceAPI::Common::UnknownException err("find failed - Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::addChangeListener(JSContextRef context,
+        JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try{
+
+        CalendarPtr priv = getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CALENDAR_FUNCTION_API_ADD_CHANGE_LISTENER);
+
+        // long addChangeListener(
+        //         CalendarChangeCallback calendarChangeCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef js_callbacks_obj = validator.toCallbackObject(0, false,
+                CALENDARADDED, CALENDARUPDATED, CALENDARREMOVED, NULL);
+
+        JSObjectRef on_added_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, CALENDARADDED);
+        JSObjectRef on_updateded_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, CALENDARUPDATED);
+        JSObjectRef on_removed_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, CALENDARREMOVED);
+
+        JSContextRef global_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        auto callback = std::make_shared<CalendarChangeCallback>(global_ctx,
+                on_added_obj, on_updateded_obj, on_removed_obj, priv->getId());
+
+        return JSValueMakeNumber(context, priv->addChangeListener(callback));
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Cannot add listener for messages");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSCalendar::removeChangeListener(JSContextRef context,
+        JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+        const JSValueRef arguments[], JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try{
+
+        CalendarPtr priv = getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CALENDAR_FUNCTION_API_REMOVE_CHANGE_LISTENER);
+
+        // void removeChangeListener(long watchId);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        long watchId = validator.toLong(0);
+
+        priv->removeChangeListener(context, watchId);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Cannot add listener for Calendar");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::getName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, object);
+
+        if (CalendarManager::UNIFIED_CALENDAR_ID == priv->getId()) {
+            return JSValueMakeNull(context);
+        }
+
+        return JSUtil::toJSValueRef(context, priv->getName());
+    } catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    } catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, object);
+
+        if (!priv->isCalendarIdSet()) {
+            return JSValueMakeNull(context);
+        }
+        std::string string_value = std::to_string(priv->getId());
+        return JSUtil::toJSValueRef(context, string_value);
+
+    } catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    } catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendar::getAccountId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarPtr priv = JSCalendar::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getAccountId());
+
+    } catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    } catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSObjectRef JSCalendar::getFunctionFromCallbackObj(JSContextRef context,
+        JSObjectRef obj,
+        const char* name)
+{
+    JSObjectRef function_obj = NULL;
+    JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
+    bool has = JSObjectHasProperty(context, obj, propertyName);
+    JSStringRelease(propertyName);
+    if (has) {
+        JSValueRef value = JSUtil::getProperty(context, obj, name);
+        function_obj = JSUtil::JSValueToObject(context, value);
+    }
+    return function_obj;
+}
+
+} // Calendar
+} // DeviceAPI
diff --git a/src/Calendar/JSCalendar.h b/src/Calendar/JSCalendar.h
new file mode 100644 (file)
index 0000000..13cca31
--- /dev/null
@@ -0,0 +1,202 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_TIZEN_CALENDAR_H_
+#define _JS_TIZEN_CALENDAR_H_
+#include <JSUtil.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "Calendar.h"
+
+
+
+namespace DeviceAPI {
+namespace Calendar {
+
+struct CalendarHolder {
+    CalendarPtr ptr;
+};
+
+class JSCalendar
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static CalendarPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static JSObjectRef makeJSObject(JSContextRef context, CalendarPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    static JSStaticValue m_property[];
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAccountId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+    * Get an item from id
+    */
+    static JSValueRef get(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Add a calendar item.
+     */
+    static JSValueRef add(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Add calendar items.
+     */
+    static JSValueRef addBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Update an item.
+     */
+    static JSValueRef update(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Update items.
+     */
+    static JSValueRef updateBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Remove a calendar item.
+     */
+    static JSValueRef remove(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Remove calendar items.
+     */
+    static JSValueRef removeBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Search for calendar items using tizen generic filter.
+     */
+    static JSValueRef find(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Watch changes
+     */
+    static JSValueRef addChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Clear watch
+     */
+    static JSValueRef removeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSObjectRef getFunctionFromCallbackObj(JSContextRef context,
+            JSObjectRef obj,
+            const char* name);
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif // _JS_TIZEN_CALENDAR_H_
+
diff --git a/src/Calendar/JSCalendarAlarm.cpp b/src/Calendar/JSCalendarAlarm.cpp
new file mode 100755 (executable)
index 0000000..204228d
--- /dev/null
@@ -0,0 +1,430 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "JSCalendarAlarm.h"
+#include "JSTZDate.h"
+#include "JSTimeDuration.h"
+#include "plugin_config.h"
+#include "CalendarUtility.h"
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+struct CalendarAlarmHolder {
+    CalendarAlarmPtr ptr;
+};
+
+namespace {
+
+const char* CALENDAR_ALARM_ABSOLUTE_DATE = "absoluteDate";
+const char* CALENDAR_ALARM_BEFORE = "before";
+const char* CALENDAR_ALARM_METHOD = "method";
+const char* CALENDAR_ALARM_DESCRIPTION = "description";
+}
+
+JSClassDefinition JSCalendarAlarm::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_CALENDAR_CALENDAR_ALARM_INTERFACE,
+    0,
+    m_property,
+    NULL, //m_function,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //constructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSCalendarAlarm::m_property[] = {
+    {CALENDAR_ALARM_ABSOLUTE_DATE, getAbsoluteDate, setAbsoluteDate, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ALARM_BEFORE, getBefore, setBefore, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ALARM_METHOD, getMethod, setMethod,kJSPropertyAttributeDontDelete},
+    {CALENDAR_ALARM_DESCRIPTION, getDescription, setDescription, kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSCalendarAlarm::m_jsClassRef = JSClassCreate(JSCalendarAlarm::getClassInfo());
+
+const JSClassDefinition* JSCalendarAlarm::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+JSClassRef DLL_EXPORT JSCalendarAlarm::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+CalendarAlarmPtr JSCalendarAlarm::getPrivateObject(JSContextRef context, JSValueRef value) {
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    CalendarAlarmHolder* priv = static_cast<CalendarAlarmHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+void JSCalendarAlarm::setPrivateObject(JSObjectRef object, CalendarAlarmPtr native) {
+    LOGD("Entered");
+    CalendarAlarmHolder* priv = static_cast<CalendarAlarmHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSCalendarAlarm::makeJSObject(JSContextRef context, CalendarAlarmPtr native) {
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    CalendarAlarmHolder* priv = new(std::nothrow) CalendarAlarmHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSCalendarAlarm::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef jsObjRef = JSObjectMake(context, JSCalendarAlarm::getClassRef(), NULL);
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        CalendarAlarmPtr priv = CalendarAlarmPtr(new(std::nothrow) CalendarAlarm());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Can not allocate memory");
+        }
+
+        std::string calendar_alarm_method = validator.toString(1);
+
+        if (TYPE_DISPLAY == calendar_alarm_method) {
+            priv->setDescription(validator.toString(2));
+        } else if (!validator.isOmitted(2) && !validator.isNull(2)) {
+            std::string calendarDescription = validator.toString(2);
+            priv->setDescription(calendarDescription);
+        }
+
+        priv->setAlarmMethod(CalendarAlarm::stringToAlarmMethod(calendar_alarm_method));
+
+        if (JSValueIsObjectOfClass(context, arguments[0], JSTZDate::getClassRef())) {
+                LOGD("JSTZDate case");
+                JSObjectRef JSTZDateObj = validator.toObject(0, JSTZDate::getClassRef());
+                if (!JSTZDateObj) {
+                    LOGE("JSTZDateObj is null");
+                    throw TypeMismatchException("Failed to get JSTZDateObj");
+                }
+                TZDatePtr ptr_absolute_date = JSTZDate::getPrivateObject(context, JSTZDateObj);
+                priv->setAbsoluteDateResetBefore(CalendarUtility::localTimeToUTCTime(ptr_absolute_date));
+                priv->setTimeZone(ptr_absolute_date->getTimezone());
+        }
+        else if (JSValueIsObjectOfClass(context, arguments[0], JSTimeDuration::getClassRef())) {
+                LOGD("JSTimeDuration case");
+                JSObjectRef JSTimeDurationObj = validator.toObject(0, JSTimeDuration::getClassRef());
+                if (!JSTimeDurationObj) {
+                   LOGE("JSTimeDurationObj is null");
+                   throw TypeMismatchException("Failed to get JSTimeDurationObj");
+                 }
+
+                TimeDurationPtr ptr_timeDuration = JSTimeDuration::getPrivateObject(context, JSTimeDurationObj);
+                priv->setBeforeResetAbsoluteDate(ptr_timeDuration);
+        }
+        else{
+            throw TypeMismatchException("First argument mismatch type exception");
+        }
+
+        CalendarAlarmHolder* holder = new(std::nothrow) CalendarAlarmHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+
+    } catch (const BasePlatformException &e) {
+        LOGE("CalendarAlarm creation failed: %s", e.getMessage().c_str());
+    } catch (...) {
+        LOGE("CalendarAlarm creation failed");
+    }
+    return jsObjRef;
+}
+
+void JSCalendarAlarm::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSCalendarAlarm::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    CalendarAlarmHolder *priv = static_cast<CalendarAlarmHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSCalendarAlarm::getAbsoluteDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarAlarmPtr priv = JSCalendarAlarm::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_ALARM_ATTRIBUTE_ABSOLUTE_DATE))) {
+            return JSValueMakeNull(context);
+        }
+        return JSTZDate::makeJSObject(context, CalendarUtility::utcTimeToTZDate(
+                priv->getTimeZone().c_str(), priv->getAbsoluteDate()));
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("absoluteDate get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting absoluteDate");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSCalendarAlarm::setAbsoluteDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarAlarmPtr priv = JSCalendarAlarm::getPrivateObject(context, object);
+
+        if (JSValueIsNull(context, value)) {
+            if (!(priv->isSet(CALENDAR_ALARM_ATTRIBUTE_ABSOLUTE_DATE))) {
+                return true;
+            }
+            else{
+                throw TypeMismatchException("The TimeDurationPtr m_before is NULL");
+            }
+        }
+        TZDatePtr ptr_absolute_date = JSTZDate::getPrivateObject(context, value);
+        priv->setAbsoluteDateResetBefore(CalendarUtility::localTimeToUTCTime(ptr_absolute_date));
+        priv->setTimeZone(ptr_absolute_date->getTimezone());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("absoluteDate set failed: %s  : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting absoluteDate");
+    }
+    return true;
+}
+
+JSValueRef JSCalendarAlarm::getBefore(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarAlarmPtr priv = JSCalendarAlarm::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_ALARM_ATTRIBUTE_BEFORE))) {
+            return JSValueMakeNull(context);
+        }
+        return JSTimeDuration::makeJSObject(context, priv->getBefore());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("before get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting before");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSCalendarAlarm::setBefore(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarAlarmPtr priv = JSCalendarAlarm::getPrivateObject(context, object);
+
+        if (JSValueIsNull(context, value)) {
+            if (!(priv->isSet(CALENDAR_ALARM_ATTRIBUTE_BEFORE))) {
+                return true;
+            }
+            else{
+                throw TypeMismatchException("The TZDatePtr m_absoluteDate is NULL");
+            }
+        }
+        TimeDurationPtr ptr_before = JSTimeDuration::getPrivateObject(context, value);
+        priv->setBeforeResetAbsoluteDate(ptr_before);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("before set failed: %s  : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting before");
+    }
+    return true;
+}
+
+JSValueRef JSCalendarAlarm::getMethod(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarAlarmPtr priv = JSCalendarAlarm::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_ALARM_ATTRIBUTE_ALARM_METHOD))) {
+            return JSValueMakeUndefined(context);
+        }
+        return JSUtil::toJSValueRef(context, CalendarAlarm::alarmMethodToString(priv->getAlarmMethod()));
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("method get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting method");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSCalendarAlarm::setMethod(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarAlarmPtr priv = JSCalendarAlarm::getPrivateObject(context, object);
+
+        priv->setAlarmMethod(CalendarAlarm::stringToAlarmMethod(JSUtil::JSValueToString(context, value)));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("method set failed: %s  : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting method");
+    }
+    return true;
+}
+
+JSValueRef JSCalendarAlarm::getDescription(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarAlarmPtr priv = JSCalendarAlarm::getPrivateObject(context, object);
+
+        if (!priv->isSet(CALENDAR_ALARM_ATTRIBUTE_DESCRIPTION)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getDescription());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("description get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting description");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSCalendarAlarm::setDescription(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarAlarmPtr priv = JSCalendarAlarm::getPrivateObject(context, object);
+
+        priv->setDescription(JSUtil::JSValueToString(context, value));
+        return true;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("description set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting description");
+    }
+    return true;
+}
+
+} //Calendar
+} //DeviceAPI
diff --git a/src/Calendar/JSCalendarAlarm.h b/src/Calendar/JSCalendarAlarm.h
new file mode 100755 (executable)
index 0000000..728a565
--- /dev/null
@@ -0,0 +1,116 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_TIZEN_CALENDAR_ALARM_H_
+#define _JS_TIZEN_CALENDAR_ALARM_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "CalendarAlarm.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class JSCalendarAlarm
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static CalendarAlarmPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, CalendarAlarmPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, CalendarAlarmPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /*
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_jsClassRef;
+
+    static JSStaticValue m_property[];
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+
+    static JSValueRef getAbsoluteDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setAbsoluteDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getBefore(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setBefore(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getMethod(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setMethod(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getDescription(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setDescription(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+}; // JSCalendarAlarm
+
+} // Calendar
+} // DeviceAPI
+
+#endif //_JS_TIZEN_CALENDAR_ALARM_H_
diff --git a/src/Calendar/JSCalendarAttendee.cpp b/src/Calendar/JSCalendarAttendee.cpp
new file mode 100755 (executable)
index 0000000..bdae2ed
--- /dev/null
@@ -0,0 +1,797 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSCalendarAttendee.h"
+#include <JSContactRef.h>
+
+#include <JSUtil.h>
+#include <Logger.h>
+#include <Export.h>
+#include <PlatformException.h>
+#include <ArgumentValidator.h>
+
+#include "plugin_config.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+struct CalendarAttendeeHolder {
+    CalendarAttendeePtr ptr;
+};
+
+namespace {
+const char *CALENDAR_ATTENDEE_NAME = "name";
+const char *CALENDAR_ATTENDEE_URI = "uri";
+const char *CALENDAR_ATTENDEE_ROLE = "role";
+const char *CALENDAR_ATTENDEE_STATUS = "status";
+const char *CALENDAR_ATTENDEE_RSVP = "RSVP";
+const char *CALENDAR_ATTENDEE_TYPE = "type";
+const char *CALENDAR_ATTENDEE_GROUP = "group";
+const char *CALENDAR_ATTENDEE_DELEGATORURI = "delegatorURI";
+const char *CALENDAR_ATTENDEE_DELEGATEURI = "delegateURI";
+const char *CALENDAR_ATTENDEE_CONTACT_REF = "contactRef";
+}
+
+JSClassDefinition JSCalendarAttendee::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_CALENDAR_CALENDAR_ATTENDEE_INTERFACE,
+        0,
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //callAsFunction,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSCalendarAttendee::m_property[] = {
+    { CALENDAR_ATTENDEE_NAME, getCalendarAttendeeName, setCalendarAttendeeName,
+        kJSPropertyAttributeDontDelete },
+    { CALENDAR_ATTENDEE_URI, getCalendarAttendeeURI, setCalendarAttendeeURI,
+        kJSPropertyAttributeDontDelete },
+    { CALENDAR_ATTENDEE_ROLE, getCalendarAttendeeRole, setCalendarAttendeeRole,
+        kJSPropertyAttributeDontDelete },
+    { CALENDAR_ATTENDEE_STATUS, getCalendarAttendeeStatus, setCalendarAttendeeStatus,
+        kJSPropertyAttributeDontDelete },
+    { CALENDAR_ATTENDEE_RSVP, getCalendarAttendeeRSVP, setCalendarAttendeeRSVP,
+        kJSPropertyAttributeDontDelete },
+    { CALENDAR_ATTENDEE_TYPE, getCalendarAttendeeType, setCalendarAttendeeType,
+        kJSPropertyAttributeDontDelete },
+    { CALENDAR_ATTENDEE_GROUP, getCalendarAttendeeGroup, setCalendarAttendeeGroup,
+        kJSPropertyAttributeDontDelete },
+    { CALENDAR_ATTENDEE_DELEGATORURI, getCalendarAttendeeDelegatorURI, setCalendarAttendeeDelegatorURI,
+        kJSPropertyAttributeDontDelete },
+    { CALENDAR_ATTENDEE_DELEGATEURI, getCalendarAttendeeDelegateURI, setCalendarAttendeeDelegateURI,
+        kJSPropertyAttributeDontDelete },
+    { CALENDAR_ATTENDEE_CONTACT_REF, getCalendarAttendeeContactRef, setCalendarAttendeeContactRef,
+        kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+
+JSClassRef JSCalendarAttendee::m_jsClassRef = JSClassCreate(JSCalendarAttendee::getClassInfo());
+
+const JSClassDefinition* JSCalendarAttendee::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+JSClassRef DLL_EXPORT JSCalendarAttendee::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSCalendarAttendee::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSCalendarAttendee::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+
+    CalendarAttendeeHolder *holder = static_cast<CalendarAttendeeHolder*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete holder;
+}
+
+CalendarAttendeePtr JSCalendarAttendee::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    CalendarAttendeeHolder *holder = static_cast<CalendarAttendeeHolder*>(JSObjectGetPrivate(object));
+    if (!holder) {
+        LOGE("Private object could not be accessed");
+        throw UnknownException("Private object could not be accessed");
+    }
+    if (!(holder->ptr)) {
+        LOGW("Private object is NULL");
+        throw UnknownException("Private object is NULL");
+    }
+    return holder->ptr;
+}
+
+JSObjectRef JSCalendarAttendee::makeJSObject(JSContextRef context,
+        CalendarAttendeePtr priv)
+{
+    if (!priv) {
+        LOGW("Private object is NULL");
+        throw UnknownException("Private object is NULL");
+    }
+
+    CalendarAttendeeHolder *holder = new (std::nothrow) CalendarAttendeeHolder();
+    if (!holder) {
+        LOGE("Memory allocation error");
+        throw UnknownException("Memory allocation error");
+    }
+
+    holder->ptr = priv;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSCalendarAttendee::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, JSCalendarAttendee::getClassRef(), NULL);
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        CalendarAttendeePtr priv;
+        CalendarAttendeeHolder *holder = NULL;
+
+        // default values are set here
+        priv = CalendarAttendeePtr(new (std::nothrow) CalendarAttendee());
+        if (!priv) {
+            LOGE("Memory allocation error");
+            throw UnknownException("Memory allocation error");
+        }
+
+        std::string uri = validator.toString(0, false);
+        JSObjectRef dictionary = validator.toObject(1, true);
+
+        priv->setURI(uri);
+        if (dictionary != NULL) {
+            JSValueRef nameData = JSUtil::getProperty(context, dictionary, CALENDAR_ATTENDEE_NAME);
+            JSValueRef roleData = JSUtil::getProperty(context, dictionary, CALENDAR_ATTENDEE_ROLE);
+            JSValueRef statusData = JSUtil::getProperty(context, dictionary, CALENDAR_ATTENDEE_STATUS);
+            JSValueRef rsvpData = JSUtil::getProperty(context, dictionary, CALENDAR_ATTENDEE_RSVP);
+            JSValueRef typeData = JSUtil::getProperty(context, dictionary, CALENDAR_ATTENDEE_TYPE);
+            JSValueRef groupData = JSUtil::getProperty(context, dictionary, CALENDAR_ATTENDEE_GROUP);
+            JSValueRef delegatorURIData = JSUtil::getProperty(context, dictionary,
+                CALENDAR_ATTENDEE_DELEGATORURI);
+            JSValueRef delegateURIData = JSUtil::getProperty(context, dictionary,
+                CALENDAR_ATTENDEE_DELEGATEURI);
+            JSValueRef contactRefData = JSUtil::getProperty(context, dictionary,
+                CALENDAR_ATTENDEE_CONTACT_REF);
+
+            if (!JSValueIsUndefined(context, nameData)) {
+                priv->setName(JSUtil::JSValueToString(context, nameData));
+            }
+            if (!JSValueIsUndefined(context, roleData)) {
+                CalendarAttendee::CalendarAttendeeRole role =
+                    CalendarAttendee::stringToAttendeeRole(
+                        JSUtil::JSValueToString(context, roleData));
+
+                priv->setRole(role);
+            }
+            if (!JSValueIsUndefined(context, statusData)) {
+                CalendarAttendee::CalendarAttendeeStatus status =
+                    CalendarAttendee::stringToAttendeeStatus(
+                        JSUtil::JSValueToString(context, statusData));
+
+                priv->setStatus(status);
+            }
+            if (!JSValueIsUndefined(context, rsvpData)) {
+                priv->setRSVP(JSUtil::JSValueToBoolean(context, rsvpData));
+            }
+            if (!JSValueIsUndefined(context, typeData)) {
+                CalendarAttendee::CalendarAttendeeType type =
+                    CalendarAttendee::stringToAttendeeType(
+                        JSUtil::JSValueToString(context, typeData));
+
+                priv->setType(type);
+            }
+            if (!JSValueIsUndefined(context, groupData)) {
+                if (!JSValueIsNull(context, groupData)) {
+                    priv->setGroup(JSUtil::JSValueToString(context, groupData));
+                }
+                // otherwise leave as default (not set),
+                // resulting in null when accessed
+            }
+            if (!JSValueIsUndefined(context, delegatorURIData)) {
+                priv->setDelegatorURI(JSUtil::JSValueToString(context, delegatorURIData));
+            }
+            if (!JSValueIsUndefined(context, delegateURIData)) {
+                priv->setDelegateURI(JSUtil::JSValueToString(context, delegateURIData));
+            }
+            if (!JSValueIsUndefined(context, contactRefData)) {
+                Contact::ContactRefPtr contactRefPtr =
+                        Contact::JSContactRef::getPrivateObject(context, contactRefData);
+                if (!contactRefPtr) {
+                    LOGE("priv is null");
+                    throw UnknownException("Priv is null");
+                }
+                priv->setContactRef(contactRefPtr);
+            }
+        }
+
+        holder = new (std::nothrow) CalendarAttendeeHolder();
+        if (!holder) {
+            LOGE("Memory allocation error");
+            throw UnknownException("Memory allocation error");
+        }
+        holder->ptr = priv;
+
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Attendee creation failed: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attendee creation failed - unsupported error");
+    }
+
+    return jsObjRef;
+}
+
+/*
+ * Getters
+ */
+JSValueRef JSCalendarAttendee::getCalendarAttendeeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (!priv->isNameSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getName());
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarAttendee::getCalendarAttendeeURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getURI());
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarAttendee::getCalendarAttendeeRole(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        std::string role = CalendarAttendee::attendeeRoleToString(priv->getRole());
+        return JSUtil::toJSValueRef(context, role);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarAttendee::getCalendarAttendeeStatus(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        std::string status = CalendarAttendee::attendeeStatusToString(priv->getStatus());
+        return JSUtil::toJSValueRef(context, status);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarAttendee::getCalendarAttendeeRSVP(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getRSVP());
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarAttendee::getCalendarAttendeeType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        std::string type = CalendarAttendee::attendeeTypeToString(priv->getType());
+        return JSUtil::toJSValueRef(context, type);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarAttendee::getCalendarAttendeeGroup(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (!priv->isGroupSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getGroup());
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarAttendee::getCalendarAttendeeDelegatorURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (!priv->isDelegatorURISet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getDelegatorURI());
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarAttendee::getCalendarAttendeeDelegateURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (!priv->isDelegateURISet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getDelegateURI());
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarAttendee::getCalendarAttendeeContactRef(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (!priv->isContactRefSet()) {
+            return JSValueMakeNull(context);
+        }
+        return Contact::JSContactRef::makeJSObject(context, priv->getContactRef());
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+/*
+ * Setters
+ */
+bool JSCalendarAttendee::setCalendarAttendeeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (JSValueIsNull(context, value)) {
+            priv->unsetName();
+            return true;
+        }
+        priv->setName(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarAttendee::setCalendarAttendeeURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        priv->setURI(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarAttendee::setCalendarAttendeeRole(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        CalendarAttendee::CalendarAttendeeRole role =
+            CalendarAttendee::stringToAttendeeRole(
+                JSUtil::JSValueToString(context, value));
+
+        priv->setRole(role);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarAttendee::setCalendarAttendeeStatus(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        CalendarAttendee::CalendarAttendeeStatus status =
+            CalendarAttendee::stringToAttendeeStatus(
+                    JSUtil::JSValueToString(context, value));
+
+        priv->setStatus(status);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarAttendee::setCalendarAttendeeRSVP(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        priv->setRSVP(JSUtil::JSValueToBoolean(context, value));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarAttendee::setCalendarAttendeeType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        CalendarAttendee::CalendarAttendeeType type =
+            CalendarAttendee::stringToAttendeeType(
+                JSUtil::JSValueToString(context, value));
+
+        priv->setType(type);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarAttendee::setCalendarAttendeeGroup(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (JSValueIsNull(context, value)) {
+            priv->unsetGroup();
+            return true;
+        }
+        priv->setGroup(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarAttendee::setCalendarAttendeeDelegatorURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (JSValueIsNull(context, value)) {
+            priv->unsetDelegatorURI();
+            return true;
+        }
+        priv->setDelegatorURI(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarAttendee::setCalendarAttendeeDelegateURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (JSValueIsNull(context, value)) {
+            priv->unsetDelegateURI();
+            return true;
+        }
+        priv->setDelegateURI(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarAttendee::setCalendarAttendeeContactRef(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarAttendeePtr priv = JSCalendarAttendee::getPrivateObject(context, object);
+
+        if (JSValueIsNull(context, value)) {
+            priv->unsetContactRef();
+            return true;
+        }
+        Contact::ContactRefPtr contactRefPtr =
+                Contact::JSContactRef::getPrivateObject(context, value);
+        if (!contactRefPtr) {
+            LOGE("priv is null");
+            throw UnknownException("Priv is null");
+        }
+        priv->setContactRef(contactRefPtr);
+
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+}  // Calendar
+}  // DeviceAPI
+
diff --git a/src/Calendar/JSCalendarAttendee.h b/src/Calendar/JSCalendarAttendee.h
new file mode 100755 (executable)
index 0000000..ac0ddbd
--- /dev/null
@@ -0,0 +1,200 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _JS_TIZEN_CALENDAR_ATTENDEE_H_
+#define _JS_TIZEN_CALENDAR_ATTENDEE_H_
+
+#include "CalendarAttendee.h"
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class JSCalendarAttendee {
+
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static CalendarAttendeePtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            CalendarAttendeePtr native);
+
+private:
+
+    /*
+     * Getters
+     */
+    static JSValueRef getCalendarAttendeeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarAttendeeURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarAttendeeRole(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarAttendeeStatus(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarAttendeeRSVP(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarAttendeeType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarAttendeeGroup(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarAttendeeDelegatorURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarAttendeeDelegateURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarAttendeeContactRef(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /*
+     * Setters
+     */
+    static bool setCalendarAttendeeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarAttendeeURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarAttendeeRole(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarAttendeeStatus(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarAttendeeRSVP(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarAttendeeType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarAttendeeGroup(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarAttendeeDelegatorURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarAttendeeDelegateURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarAttendeeContactRef(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /*
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec.
+     */
+    static JSStaticValue m_property[];
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif // _JS_TIZEN_CALENDAR_ATTENDEE_H_
diff --git a/src/Calendar/JSCalendarEvent.cpp b/src/Calendar/JSCalendarEvent.cpp
new file mode 100755 (executable)
index 0000000..04b1ea6
--- /dev/null
@@ -0,0 +1,751 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        JSCalendarEvent.cpp
+*/
+#include "CalendarManager.h"
+#include "CalendarUtility.h"
+#include "JSCalendarEvent.h"
+#include "JSCalendarItem.h"
+#include "JSCalendarEventId.h"
+#include "JSCalendarRecurrenceRule.h"
+#include "JSCalendarAlarm.h"
+#include "JSCalendarAttendee.h"
+#include "plugin_config.h"
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+#include <SecurityExceptions.h>
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <JSTZDate.h>
+#include <JSTimeDuration.h>
+#include <JSSimpleCoordinates.h>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+struct CalendarEventHolder{
+    CalendarEventPtr ptr;
+};
+
+namespace {
+const char* CALENDAR_EVENT_ID = "id";
+const char* CALENDAR_EVENT_IS_DETACHED = "isDetached";
+const char* CALENDAR_EVENT_END_DATE  = "endDate";
+const char* CALENDAR_EVENT_AVAILABILITY = "availability";
+const char* CALENDAR_EVENT_RECURRENCE_RULE = "recurrenceRule";
+}
+
+JSClassDefinition JSCalendarEvent::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_CALENDAR_CALENDAR_EVENT_INTERFACE,
+    JSCalendarItem::getClassRef(),
+    m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //constructor,
+    NULL, //HasInstance,
+    NULL  //ConvertToType
+};
+
+JSStaticValue JSCalendarEvent::m_property[] = {
+    {CALENDAR_EVENT_ID, getId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {CALENDAR_EVENT_IS_DETACHED, getIsDetached, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {CALENDAR_EVENT_END_DATE, getEndDate, setEndDate, kJSPropertyAttributeDontDelete},
+    {CALENDAR_EVENT_AVAILABILITY, getAvailability, setAvailability, kJSPropertyAttributeDontDelete},
+    {CALENDAR_EVENT_RECURRENCE_RULE, getRecurrenceRule, setRecurrenceRule, kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSCalendarEvent::m_function[] = {
+    {CALENDAR_FUNCTION_API_CONVERT_TO_STRING, convertToString, kJSPropertyAttributeNone},
+    {CALENDAR_FUNCTION_API_CLONE, clone, kJSPropertyAttributeNone},
+    {CALENDAR_FUNCTION_API_EXPAND_RECURRENCE, expandRecurrence, kJSPropertyAttributeNone},
+    { 0, 0, 0 }
+};
+
+JSClassRef JSCalendarEvent::m_jsClassRef = JSClassCreate(JSCalendarEvent::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSCalendarEvent::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSCalendarEvent::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+CalendarEventPtr JSCalendarEvent::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    CalendarEventHolder* priv = static_cast<CalendarEventHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw DeviceAPI::Common::UnknownException("Priv is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv ptr is null");
+        throw DeviceAPI::Common::UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+void JSCalendarEvent::setPrivateObject(JSObjectRef object, CalendarEventPtr native)
+{
+    LOGD("Entered");
+    CalendarEventHolder* priv = static_cast<CalendarEventHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw DeviceAPI::Common::UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSCalendarEvent::makeJSObject(JSContextRef context, CalendarEventPtr native)
+{
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw DeviceAPI::Common::UnknownException("Native is null");
+    }
+    CalendarEventHolder* priv = new(std::nothrow) CalendarEventHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw DeviceAPI::Common::UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+    priv->ptr->copyAceCheckAccessFunction(CalendarManager::getInstance());
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (!obj) {
+        LOGE("Object creation failed");
+        throw DeviceAPI::Common::UnknownException("Object creation failed");
+    }
+
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSCalendarEvent::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef jsObjRef = JSObjectMake(context, JSCalendarEvent::getClassRef(), NULL);
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    enum JSCalendarEventConstructorType {
+        CALENDAR_EVENT_CONSTRUCTOR_TYPE_NO_PARAMS,
+        CALENDAR_EVENT_CONSTRUCTOR_TYPE_OBJECT,
+        CALENDAR_EVENT_CONSTRUCTOR_TYPE_STRING
+    };
+
+    JSCalendarEventConstructorType constructor_type = CALENDAR_EVENT_CONSTRUCTOR_TYPE_NO_PARAMS;
+    try {
+        if (validator.isOmitted(0) || validator.isNull(0) || validator.isUndefined(0)) {
+            constructor_type = CALENDAR_EVENT_CONSTRUCTOR_TYPE_NO_PARAMS;
+        }
+        else if (JSValueIsObject(context, arguments[0])) {
+            constructor_type = CALENDAR_EVENT_CONSTRUCTOR_TYPE_OBJECT;
+        }
+        else if (JSValueIsString(context, arguments[0]) && !validator.isOmitted(1) &&
+                JSValueIsString(context, arguments[1])) {
+            constructor_type = CALENDAR_EVENT_CONSTRUCTOR_TYPE_STRING;
+        }
+
+        CalendarEventPtr priv = CalendarEventPtr(new(std::nothrow) CalendarEvent());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw DeviceAPI::Common::UnknownException("Can not allocate memory");
+        }
+        switch (constructor_type) {
+            case CALENDAR_EVENT_CONSTRUCTOR_TYPE_NO_PARAMS:
+                // nothing to be done
+                break;
+
+            case CALENDAR_EVENT_CONSTRUCTOR_TYPE_OBJECT:
+            {
+                JSObjectRef dictionary = validator.toObject(0, true);
+
+                JSValueRef js_description = JSUtil::getProperty(context,
+                        dictionary,CALENDAR_ITEM_DESCRIPTION);
+                JSValueRef js_summary = JSUtil::getProperty(context,
+                        dictionary,CALENDAR_ITEM_SUMMARY);
+                JSValueRef js_is_all_day = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_IS_ALL_DAY);
+                JSValueRef js_start_date = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_START_DATE);
+                JSValueRef js_duration = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_DURATION);
+                JSValueRef js_location = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_LOCATION);
+                JSValueRef js_geolocation = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_GEOLOCATION);
+                JSValueRef js_organizer = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_ORGANIZER);
+                JSValueRef js_visibility = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_VISIBILITY);
+                JSValueRef js_status = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_STATUS);
+                JSValueRef js_priority = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_PRIORITY);
+                JSValueRef js_alarms = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_ALARMS);
+                JSValueRef js_categories = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_CATEGORIES);
+                JSValueRef js_attendees = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_ITEM_ATTENDEES);
+
+                //CalendarEvent related dictionary values
+                JSValueRef js_end_date = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_EVENT_END_DATE);
+                JSValueRef js_availability = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_EVENT_AVAILABILITY);
+                JSValueRef js_recurrence_rule = JSUtil::getProperty(context,
+                         dictionary,CALENDAR_EVENT_RECURRENCE_RULE);
+
+                if (!JSValueIsUndefined(context, js_description)
+                        && !JSValueIsNull(context, js_description)) {
+                    priv->setDescription(JSUtil::JSValueToString(context, js_description));
+                }
+
+                if (!JSValueIsUndefined(context, js_summary)
+                        && !JSValueIsNull(context, js_summary)) {
+                    priv->setSummary(JSUtil::JSValueToString(context, js_summary));
+                }
+
+                if (!JSValueIsUndefined(context, js_is_all_day)
+                        && !JSValueIsNull(context, js_is_all_day)) {
+                    priv->setIsAllDay(JSUtil::JSValueToBoolean(context, js_is_all_day));
+                }
+
+                if (!JSValueIsUndefined(context, js_start_date)
+                        && !JSValueIsNull(context, js_start_date)) {
+                    TZDatePtr date = JSTZDate::getPrivateObject(context, js_start_date);
+                    priv->setStartDate(CalendarUtility::localTimeToUTCTime(date), date->getTimezone());
+                }
+
+                if (!JSValueIsUndefined(context, js_duration)
+                        && !JSValueIsNull(context, js_duration)) {
+                    TimeDurationPtr duration = JSTimeDuration::getPrivateObject(
+                            context,  js_duration);
+                    priv->setDuration(duration);
+                }
+
+                if (!JSValueIsUndefined(context, js_location)
+                        && !JSValueIsNull(context, js_location)) {
+                    priv->setLocation(JSUtil::JSValueToString(context, js_location));
+                }
+
+                if (!JSValueIsUndefined(context, js_geolocation)
+                        && !JSValueIsNull(context, js_geolocation)) {
+                    Tizen::SimpleCoordinatesPtr geolocation =
+                            Tizen::JSSimpleCoordinates::getPrivateObject(
+                                    context, js_geolocation);
+                    priv->setGeolocation(geolocation);
+                }
+
+                if (!JSValueIsUndefined(context, js_organizer)
+                        && !JSValueIsNull(context, js_organizer)) {
+                    priv->setOrganizer(JSUtil::JSValueToString(context, js_organizer));
+                }
+
+                if (!JSValueIsUndefined(context, js_visibility)
+                        && !JSValueIsNull(context, js_visibility)) {
+                    priv->setVisibility(CalendarItem::stringToCalendarItemVisibility(
+                        JSUtil::JSValueToString(context, js_visibility)));
+                }
+
+                if (!JSValueIsUndefined(context, js_status)
+                        && !JSValueIsNull(context, js_status)) {
+                    priv->setStatus(CalendarItem::stringToCalendarItemStatus(
+                        JSUtil::JSValueToString(context, js_status), priv->getType()));
+                }
+
+                if (!JSValueIsUndefined(context, js_priority)
+                       && !JSValueIsNull(context, js_priority)) {
+                    priv->setPriority(CalendarItem::stringToCalendarItemPriority(
+                        JSUtil::JSValueToString(context, js_priority)));
+                }
+
+                if (!JSValueIsUndefined(context, js_alarms)) {
+                    std::vector<CalendarAlarmPtr> alarms =
+                            JSUtil::JSArrayToType_<CalendarAlarmPtr>(context,
+                                    js_alarms, JSCalendarAlarm::getPrivateObject);
+                    priv->setAlarms(alarms);
+                }
+
+                if (!JSValueIsUndefined(context, js_categories)) {
+                    priv->setCategories(JSUtil::JSArrayToStringVector(
+                            context, js_categories));
+                }
+
+                if (!JSValueIsUndefined(context, js_attendees)) {
+                    priv->setAttendees(JSUtil::JSArrayToType_<CalendarAttendeePtr>(context,
+                            js_attendees, JSCalendarAttendee::getPrivateObject));
+                }
+
+                // set CalendarEvent attributes
+                if (!JSValueIsUndefined(context, js_end_date)
+                        && !JSValueIsNull(context, js_end_date)) {
+                    TZDatePtr ptr_end_date = JSTZDate::getPrivateObject(context,
+                            js_end_date);
+                    priv->setEndDate(CalendarUtility::localTimeToUTCTime(ptr_end_date), ptr_end_date->getTimezone());
+                }
+
+                if (!JSValueIsUndefined(context, js_availability)
+                        && !JSValueIsNull(context, js_availability)) {
+                    priv->setAvailability(CalendarEvent::stringToCalendarEventAvailability(
+                        JSUtil::JSValueToString(context, js_availability)));
+                }
+                if (!JSValueIsUndefined(context, js_recurrence_rule)
+                        && !JSValueIsNull(context, js_recurrence_rule)){
+                    CalendarRecurrenceRulePtr ptr_recurrence_rule =
+                        JSCalendarRecurrenceRule::getPrivateObject(context, js_recurrence_rule);
+                    priv->setRecurrenceRule(ptr_recurrence_rule);
+                }
+
+            }
+            break;
+            case CALENDAR_EVENT_CONSTRUCTOR_TYPE_STRING:
+            {
+                std::string calendar_event_string = validator.toString(0);
+                std::string format = validator.toString(1);
+                if (TYPE_ICALENDAR_20 == format || TYPE_VCALENDAR_10 == format) {
+                    priv->setFormat(format);
+                }
+                else{
+                    throw DeviceAPI::Common::TypeMismatchException("Invalid VCALENDAR format");
+                }
+                priv->createPlatformCalendarItemFromString(calendar_event_string);
+                priv->convertPlatFormEventToAbstractCalendarEvent();
+            }
+            break;
+        }
+
+        CalendarEventHolder* holder = new(std::nothrow) CalendarEventHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw DeviceAPI::Common::UnknownException("Holder is null");
+        }
+
+        holder->ptr = priv;
+        holder->ptr->copyAceCheckAccessFunction(CalendarManager::getInstance());
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+
+    } catch (const BasePlatformException &e) {
+        LOGE("CalendarEvent creation failed: %s", e.getMessage().c_str());
+    } catch (...) {
+        LOGE("CalendarEvent creation failed");
+    }
+    return jsObjRef;
+}
+
+void JSCalendarEvent::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSCalendarEvent::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+
+    CalendarEventHolder *holder = static_cast<CalendarEventHolder*>(
+            JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete holder;
+    holder = NULL;
+}
+
+JSValueRef JSCalendarEvent::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_EVENT_ATTRIBUTE_ID))) {
+            return JSValueMakeNull(context);
+        }
+        return JSCalendarEventId::makeJSObject(context,priv->getId());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("id get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting id");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarEvent::getIsDetached(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_EVENT_ATTRIBUTE_IS_DETACHED))) {
+            return JSValueMakeUndefined(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getIsDetached());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("isDetached get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting isDetached");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarEvent::getEndDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, object);
+
+        if (!(priv->CalendarItem::isSet(CALENDAR_ITEM_ATTRIBUTE_END_DATE))) {
+            return JSValueMakeNull(context);
+        }
+        return JSTZDate::makeJSObject(context, CalendarUtility::utcTimeToTZDate(
+                priv->getTimezone().c_str(), priv->getEndDate()));
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("endDate get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting endDate");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarEvent::getAvailability(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_EVENT_ATTRIBUTE_AVAILABILITY))) {
+            return JSValueMakeUndefined(context);
+        }
+        return JSUtil::toJSValueRef(context,
+                CalendarEvent::calendarEventAvailabilityToString(priv->getAvailability()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("availability get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting availability");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarEvent::getRecurrenceRule(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_EVENT_ATTRIBUTE_RECURRENCE_RULE))) {
+            return JSValueMakeNull(context);
+        }
+        return JSCalendarRecurrenceRule::makeJSObject(context, priv->getRecurrenceRule());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("recurrenceRule get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting recurrenceRule");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSCalendarEvent::setEndDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, object);
+
+        TZDatePtr ptr_end_date = JSTZDate::getPrivateObject(context, value);
+        priv->setEndDate(CalendarUtility::localTimeToUTCTime(ptr_end_date), ptr_end_date->getTimezone());
+        return true;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("endDate set failed: %s : %s", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting endDate");
+    }
+    return true;
+}
+
+bool JSCalendarEvent::setAvailability(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, object);
+
+        priv->setAvailability(CalendarEvent::stringToCalendarEventAvailability(
+                JSUtil::JSValueToString(context, value)));
+        return true;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("availability set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting availability");
+    }
+    return true;
+}
+
+bool JSCalendarEvent::setRecurrenceRule(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unsetRecurrenceRule();
+        }
+        else{
+            CalendarRecurrenceRulePtr ptr_recurrence_rule =
+                    JSCalendarRecurrenceRule::getPrivateObject(context, value);
+            priv->setRecurrenceRule(ptr_recurrence_rule);
+        }
+        return true;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("recurrenceRule set failed: %s : %s", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting recurrenceRule");
+    }
+    return true;
+}
+
+JSValueRef JSCalendarEvent::convertToString(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try{
+
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CALENDAR_FUNCTION_API_CONVERT_TO_STRING);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        if (!validator.isOmitted(0) && JSValueIsString(context, arguments[0])) {
+            std::string format = validator.toString(0);
+            if (TYPE_ICALENDAR_20 == format || TYPE_VCALENDAR_10 == format) {
+                priv->setFormat(format);
+                priv->convertAbstractCalendarEventToPlatformCalendarEvent();
+                std::string calendar = priv->exportCalendarItemToString();
+                return JSUtil::toJSValueRef(context, calendar);
+            }
+            else{
+                LOGE("Input parameter is not compatible with the expected value "
+                        "for that parameter");
+                throw TypeMismatchException(
+                        "Input parameter is not compatible with the expected value "
+                        "for that parameter");
+            }
+        }
+        else{
+            LOGE("Input parameter is not compatible with the expected type "
+                    "for that parameter");
+            throw TypeMismatchException(
+                    "Input parameter is not compatible with the expected type "
+                    "for that parameter");
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("convertToString failed", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("convertToString failed, Unknown Exception");
+        return JSWebAPIErrorFactory::postException(context, exception, "UnknownError");
+    }
+}
+
+JSValueRef JSCalendarEvent::clone(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+
+    JSObjectRef jsObjRef = JSObjectMake(context, JSCalendarEvent::getClassRef(), NULL);
+
+    try{
+        CalendarEventPtr priv_orgin = JSCalendarEvent::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv_orgin.get(), CALENDAR_FUNCTION_API_CLONE);
+
+        CalendarEventPtr priv_new(new CalendarEvent(*priv_orgin));
+
+        CalendarEventHolder* holder = new(std::nothrow) CalendarEventHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw DeviceAPI::Common::UnknownException("Holder is null");
+        }
+
+        holder->ptr = priv_new;
+        priv_new->setId(CalendarEventIdPtr(new CalendarEventId()));
+        priv_new->setIsSet(CALENDAR_EVENT_ATTRIBUTE_ID, false);
+        priv_new->setCalendarId(UNDEFINED_CALENDAR_ID);
+        priv_new->CalendarItem::setIsSet(CALENDAR_ITEM_ATTRIBUTE_CALENDAR_ID,false);
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    } catch (const BasePlatformException &err) {
+        LOGE("clone failed", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("clone function failed, Unknown Exception");
+        return JSWebAPIErrorFactory::postException(context, exception, "UnknownError");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSCalendarEvent::expandRecurrence(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    CalendarEventCallbackUserData *callback = NULL;
+    try {
+
+        CalendarEventPtr priv = JSCalendarEvent::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CALENDAR_FUNCTION_API_EXPAND_RECURRENCE);
+
+        callback = new CalendarEventCallbackUserData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef js_start_date = validator.toObject(0, JSTZDate::getClassRef());
+        TZDatePtr start_date_ptr = JSTZDate::getPrivateObject(context, js_start_date);
+        callback->setStartDate(CalendarUtility::localTimeToUTCTime(start_date_ptr),
+                start_date_ptr->getTimezone());
+
+        JSObjectRef js_end_date = validator.toObject(1, JSTZDate::getClassRef());
+        TZDatePtr end_date_ptr = JSTZDate::getPrivateObject(context, js_end_date);
+        callback->setEndDate(CalendarUtility::localTimeToUTCTime(end_date_ptr),
+                end_date_ptr->getTimezone());
+
+        callback->setEvent(priv);
+
+        callback->setSuccessCallback(validator.toFunction(2));
+        callback->setErrorCallback(validator.toFunction(3, true));
+
+        priv->expandRecurrence(callback);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("expandRecurrence BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("expandRecurrence fails");
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "expandRecurrence fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // Calendar
+} // DeviceAPI
diff --git a/src/Calendar/JSCalendarEvent.h b/src/Calendar/JSCalendarEvent.h
new file mode 100755 (executable)
index 0000000..5666463
--- /dev/null
@@ -0,0 +1,135 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        JSCalendarEvent.h
+*/
+
+#ifndef _JS_CALENDAR_EVENT_H_
+#define _JS_CALENDAR_EVENT_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "CalendarEvent.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class JSCalendarEvent
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static CalendarEventPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, CalendarEventPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, CalendarEventPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_jsClassRef;
+
+    static JSStaticValue m_property[];
+
+    static JSStaticFunction m_function[];
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsDetached(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getEndDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAvailability(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getRecurrenceRule(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setEndDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setAvailability(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setRecurrenceRule(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef convertToString(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef clone(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+    /**
+     * Expand event instances from a recurring event
+     */
+    static JSValueRef expandRecurrence(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif /* _JS_CALENDAR_EVENT_H_ */
diff --git a/src/Calendar/JSCalendarEventId.cpp b/src/Calendar/JSCalendarEventId.cpp
new file mode 100755 (executable)
index 0000000..fcfc729
--- /dev/null
@@ -0,0 +1,299 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSCalendarEventId.h"
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include "plugin_config.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+struct CalendarEventIdHolder {
+    CalendarEventIdPtr ptr;
+};
+
+struct CalendarEventIntIdHolder {
+    int ptr;
+};
+
+namespace {
+const char* CALENDAR_EVENT_ID_UID = "uid";
+const char* CALENDAR_EVENT_ID_RECURRENCEID = "rid";
+}
+
+JSClassDefinition JSCalendarEventId::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_CALENDAR_CALENDAR_EVENT_ID_INTERFACE,
+    0,
+    m_property,
+    NULL, //m_function,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //constructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSCalendarEventId::m_property[] = {
+    {CALENDAR_EVENT_ID_UID, getUid, setUid, kJSPropertyAttributeDontDelete},
+    {CALENDAR_EVENT_ID_RECURRENCEID, getRid, setRid, kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSCalendarEventId::m_jsClassRef = JSClassCreate(JSCalendarEventId::getClassInfo());
+
+JSClassRef DLL_EXPORT JSCalendarEventId::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSCalendarEventId::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+CalendarEventIdPtr JSCalendarEventId::getPrivateObject(JSContextRef context, JSValueRef value) {
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    CalendarEventIdHolder* priv = static_cast<CalendarEventIdHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+void JSCalendarEventId::setPrivateObject(JSObjectRef object, CalendarEventIdPtr native) {
+    LOGD("Entered");
+    CalendarEventIdHolder* priv = static_cast<CalendarEventIdHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSCalendarEventId::makeJSObject(JSContextRef context, CalendarEventIdPtr native) {
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    CalendarEventIdHolder* priv = new(std::nothrow) CalendarEventIdHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+JSObjectRef JSCalendarEventId::makeJSObject(JSContextRef context, int native) {
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    CalendarEventIntIdHolder* priv = new(std::nothrow) CalendarEventIntIdHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSCalendarEventId::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSCalendarEventId::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    CalendarEventIdHolder* priv = static_cast<CalendarEventIdHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSCalendarEventId::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef jsObjRef = JSObjectMake(context, JSCalendarEventId::getClassRef(), NULL);
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+    try {
+        CalendarEventIdPtr priv =  CalendarEventIdPtr(new (std::nothrow) CalendarEventId());
+        if (!priv) {
+            throw UnknownException("Priv is null");
+        }
+
+        int uid = 0;
+        std::string rid = "";
+
+        uid = validator.toLong(0);
+        priv->setUid(uid);
+
+        if (!validator.isOmitted(1) && !validator.isNull(1)) {
+            rid = validator.toString(1);
+            priv->setRid(rid);
+        }
+
+        CalendarEventIdHolder* holder = new(std::nothrow) CalendarEventIdHolder();
+        if (!holder) {
+            LOGW("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (BasePlatformException &e) {
+        LOGE("CalendarEventId creation failed: %s", e.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("CalendarEventId creation failed");
+    }
+    return jsObjRef;
+}
+
+JSValueRef JSCalendarEventId::getUid(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventIdPtr priv = JSCalendarEventId::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_EVENT_ID_ATTRIBUTE_UID))) {
+            return JSValueMakeUndefined(context);
+        }
+        return JSUtil::toJSValueRef(context, std::to_string(priv->getUid()));
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("uid get failed: %s : %s", e.getName().c_str(), e.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting uid");
+    }
+    return JSValueMakeUndefined(context);;
+}
+
+bool JSCalendarEventId::setUid(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventIdPtr priv = JSCalendarEventId::getPrivateObject(context, object);
+
+        priv->setUid(JSUtil::JSValueToLong(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("uid set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting uid");
+    }
+    return true;
+}
+
+JSValueRef JSCalendarEventId::getRid(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventIdPtr priv = JSCalendarEventId::getPrivateObject(context, object);
+
+        if (false == (priv->isSet(CALENDAR_EVENT_ID_ATTRIBUTE_RID))) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getRid());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("rid get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting rid");
+    }
+    return JSValueMakeUndefined(context);;
+}
+
+bool JSCalendarEventId::setRid(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarEventIdPtr priv = JSCalendarEventId::getPrivateObject(context, object);
+
+        priv->setRid(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("rid set failed: %s  : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting rid");
+    }
+    return true;
+}
+
+} // Calendar
+} // DeviceAPI
diff --git a/src/Calendar/JSCalendarEventId.h b/src/Calendar/JSCalendarEventId.h
new file mode 100755 (executable)
index 0000000..4d0b61f
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_CALEMDAR_EVENT_ID_H_
+#define _JS_CALEMDAR_EVENT_ID_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "CalendarEventId.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class JSCalendarEventId
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static CalendarEventIdPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, CalendarEventIdPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, CalendarEventIdPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, int native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+    * This member variable contains the values which has to be passed when
+    * the this class is embedded into JS Engine.
+    */
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_jsClassRef;
+
+    static JSStaticValue m_property[];
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getUid(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setUid(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getRid(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setRid(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif // _JS_CALEMDAR_EVENT_ID_H_
diff --git a/src/Calendar/JSCalendarItem.cpp b/src/Calendar/JSCalendarItem.cpp
new file mode 100755 (executable)
index 0000000..6530fa6
--- /dev/null
@@ -0,0 +1,858 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        JSCalendarItem.cpp
+*/
+
+#include "CalendarUtility.h"
+#include "JSCalendarItem.h"
+#include "JSCalendarEventId.h"
+#include "JSCalendarAlarm.h"
+#include "JSCalendarAttendee.h"
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+#include <JSSimpleCoordinates.h>
+#include <JSTZDate.h>
+#include <JSTimeDuration.h>
+#include <vector>
+#include <GlobalContextManager.h>
+#include "plugin_config.h"
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+struct CalendarItemHolder {
+    CalendarItemPtr ptr;
+};
+
+JSClassDefinition JSCalendarItem::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    CALENDAR_ITEM,
+    0,
+    m_property,
+    NULL,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL  //ConvertToType
+};
+
+JSStaticValue JSCalendarItem::m_property[] = {
+    {CALENDAR_ITEM_CALENDAR_ID, getCalendarId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {CALENDAR_ITEM_LAST_MODIFICATION_DATE, getLastModificationDate, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {CALENDAR_ITEM_DESCRIPTION, getDescription, setDescription, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_SUMMARY, getSummary, setSummary, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_IS_ALL_DAY, getIsAllDay, setIsAllDay, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_START_DATE, getStartDate, setStartDate, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_DURATION, getDuration, setDuration, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_LOCATION, getLocation, setLocation, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_GEOLOCATION, getGeolocation, setGeolocation, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_ORGANIZER, getOrganizer, setOrganizer, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_VISIBILITY, getVisibility, setVisibility, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_STATUS, getStatus, setStatus, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_PRIORITY, getPriority, setPriority, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_ALARMS, getAlarms, setAlarms, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_CATEGORIES, getCategories, setCategories, kJSPropertyAttributeDontDelete},
+    {CALENDAR_ITEM_ATTENDEES, getAttendees, setAttendees, kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSCalendarItem::m_jsClassRef = JSClassCreate(JSCalendarItem::getClassInfo());
+
+const JSClassDefinition* JSCalendarItem::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+const JSClassRef DLL_EXPORT JSCalendarItem::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+CalendarItemPtr JSCalendarItem::getPrivateObject(JSContextRef context, JSValueRef value) {
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    CalendarItemHolder* priv = static_cast<CalendarItemHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+void JSCalendarItem::setPrivateObject(JSObjectRef object, CalendarItemPtr native) {
+    LOGD("Entered");
+    CalendarItemHolder* priv = static_cast<CalendarItemHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSCalendarItem::makeJSObject(JSContextRef context, CalendarItemPtr native) {
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    CalendarItemHolder* priv = new(std::nothrow) CalendarItemHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSCalendarItem::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSCalendarItem::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+JSValueRef JSCalendarItem::convertToString(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGW("JSCalendarItem::convertToString - This function should never be invoked");
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarItem::clone(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGW("JSCalendarItem::clone - This function should never be invoked");
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarItem::getCalendarId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_ITEM_ATTRIBUTE_CALENDAR_ID))) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, std::to_string(priv->getCalendarId()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("calendarId get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting calendarId");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarItem::getLastModificationDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_LAST_MODIFICATION_DATE)) {
+            return JSTZDate::makeJSObject(context, CalendarUtility::utcTimeToTZDate(
+                    priv->getTimezone().c_str(), priv->getLastModificationDate()));
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("lastModificationDate get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting lastModificationDate");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarItem::getDescription(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_ITEM_ATTRIBUTE_DESCRIPTION))) {
+            return JSUtil::toJSValueRef(context, "");
+        }
+        return JSUtil::toJSValueRef(context, priv->getDescription());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("description get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting description");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarItem::getSummary(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_SUMMARY)) {
+            return JSUtil::toJSValueRef(context, priv->getSummary());
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("summary get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting summary");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarItem::getIsAllDay(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_IS_ALL_DAY)) {
+            return JSUtil::toJSValueRef(context, priv->getIsAllDay());
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("isAllDay get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting isAllDay");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarItem::getStartDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_START_DATE)) {
+            return JSTZDate::makeJSObject(context, CalendarUtility::utcTimeToTZDate(
+                    priv->getTimezone().c_str(), priv->getStartDate()));
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("startDate get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting startDate");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarItem::getDuration(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_DURATION)) {
+            return JSTimeDuration::makeJSObject(context,priv->getDuration());
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("duration get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting duration");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarItem::getLocation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_LOCATION)) {
+            return JSUtil::toJSValueRef(context, priv->getLocation());
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("location get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting location");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarItem::getGeolocation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_GEOLOCATION)) {
+            return Tizen::JSSimpleCoordinates::makeJSObject(context, priv->getGeolocation());
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("geolocation get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting geolocation");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarItem::getOrganizer(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_ORGANIZER)) {
+            return JSUtil::toJSValueRef(context, priv->getOrganizer());
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("organizer get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting organizer");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarItem::getVisibility(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_VISIBILITY)) {
+            return JSUtil::toJSValueRef(context,
+                CalendarItem::calendarItemVisibilityToString(priv->getVisibility()));
+        }
+
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("visibility get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting visibility");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarItem::getStatus(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_ITEM_ATTRIBUTE_STATUS))) {
+            return JSValueMakeUndefined(context);
+        }
+        return JSUtil::toJSValueRef(context, CalendarItem::calendarItemStatusToString(
+                priv->getStatus(), priv->getType()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("status get failed: %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting status");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarItem::getPriority(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (priv->isSet(CALENDAR_ITEM_ATTRIBUTE_PRIORITY)) {
+            return JSUtil::toJSValueRef(context,
+                CalendarItem::calendarItemPriorityToString(priv->getPriority()));
+        }
+
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("priority get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting priority");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarItem::getAlarms(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_ITEM_ATTRIBUTE_ALARMS))) {
+            return JSObjectMakeArray(context, 0, NULL, NULL);
+        }
+
+        return priv->getJSAlarms(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("alarms get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting alarms");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarItem::getCategories(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        // TODO check this: if isSet() == false then js user gets meaningless
+        // array (without connection to actual CalendarItem object).
+        if (!(priv->isSet(CALENDAR_ITEM_ATTRIBUTE_CATEGORIES))) {
+            return JSObjectMakeArray(context, 0, NULL, NULL);
+        }
+
+        return priv->getJSCategories(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("categories get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting categories");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarItem::getAttendees(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_ITEM_ATTRIBUTE_ATTENDEES))) {
+            return JSObjectMakeArray(context, 0, NULL, NULL);
+        }
+
+        return priv->getJSAttendees(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("attendees get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting attendees");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSCalendarItem::setDescription(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        priv->setDescription(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("description set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting description");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setSummary(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        priv->setSummary(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("summary set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting summary");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setIsAllDay(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        priv->setIsAllDay(JSUtil::JSValueToBoolean(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("isAllDay set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting isAllDay");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setStartDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        TZDatePtr ptr_absolute_date = JSTZDate::getPrivateObject(context, value);
+        priv->setStartDate(CalendarUtility::localTimeToUTCTime(ptr_absolute_date), ptr_absolute_date->getTimezone());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("startDate set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting startDate");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setDuration(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        TimeDurationPtr ptr_time_duration = JSTimeDuration::getPrivateObject(context, value);
+        priv->setDuration(ptr_time_duration);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("duration set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting duration");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setLocation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        priv->setLocation(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("location set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting location");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setGeolocation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        Tizen::SimpleCoordinatesPtr ptr_geo_location =
+                Tizen::JSSimpleCoordinates::getPrivateObject(context, value);
+        priv->setGeolocation(ptr_geo_location);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("geolocation set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting geolocation");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setOrganizer(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        priv->setOrganizer(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("organizer set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting organizer");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setVisibility(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        priv->setVisibility(CalendarItem::stringToCalendarItemVisibility(JSUtil::JSValueToString(context, value)));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("visibilit set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting visibilit");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setStatus(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = getPrivateObject(context, object);
+
+        priv->setStatus(CalendarItem::stringToCalendarItemStatus(
+                JSUtil::JSValueToString(context, value), priv->getType()));
+        return true;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("status set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting status");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setPriority(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        priv->setPriority(CalendarItem::stringToCalendarItemPriority(JSUtil::JSValueToString(context, value)));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("priority set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting priority");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setAlarms(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        std::vector<CalendarAlarmPtr> alarms = JSUtil::JSArrayToType_<CalendarAlarmPtr>(context, value, JSCalendarAlarm::getPrivateObject);
+        priv->setAlarms(alarms);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("alarms set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting alarms");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setCategories(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+        priv->setCategories(JSUtil::JSArrayToStringVector(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("categories set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting categories");
+    }
+    return true;
+}
+
+bool JSCalendarItem::setAttendees(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarItemPtr priv = JSCalendarItem::getPrivateObject(context, object);
+
+        std::vector<CalendarAttendeePtr> attendees = JSUtil::JSArrayToType_<CalendarAttendeePtr>(context,
+                value, JSCalendarAttendee::getPrivateObject);
+        priv->setAttendees(attendees);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("attendees set failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting attendees");
+    }
+    return true;
+}
+
+} // Calendar
+} // DeviceAPI
diff --git a/src/Calendar/JSCalendarItem.h b/src/Calendar/JSCalendarItem.h
new file mode 100755 (executable)
index 0000000..88e022f
--- /dev/null
@@ -0,0 +1,257 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        JSCalendarItem.h
+*/
+
+#ifndef _JS_CALENDAR_ITEM_H_
+#define _JS_CALENDAR_ITEM_H_
+
+#include "CalendarItem.h"
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class JSCalendarItem
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static CalendarItemPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, CalendarItemPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, CalendarItemPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed when
+     * the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_jsClassRef;
+
+    static JSStaticValue m_property[];
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Export a string from item
+     */
+
+    static JSValueRef convertToString(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Copy item object contents except id
+     */
+    static JSValueRef clone(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLastModificationDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDescription(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getSummary(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsAllDay(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getStartDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDuration(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLocation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getGeolocation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getOrganizer(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getVisibility(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getStatus(JSContextRef context,
+             JSObjectRef object,
+             JSStringRef propertyName,
+             JSValueRef* exception);
+
+    static JSValueRef getPriority(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAlarms(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCategories(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAttendees(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setDescription(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setSummary(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setIsAllDay(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setStartDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setDuration(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setLocation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setGeolocation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setOrganizer(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setVisibility(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setStatus(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setPriority(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setAlarms(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCategories(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setAttendees(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif // _JS_CALENDAR_ITEM_H_
diff --git a/src/Calendar/JSCalendarManager.cpp b/src/Calendar/JSCalendarManager.cpp
new file mode 100755 (executable)
index 0000000..e690856
--- /dev/null
@@ -0,0 +1,318 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <SecurityExceptions.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+#include "JSCalendarManager.h"
+#include "CalendarManager.h"
+#include "JSCalendar.h"
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+JSClassDefinition JSCalendarManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    CALENDAR_MANAGER_ATTRIBUTENAME,
+    0,
+    NULL,
+    m_function,
+    initialize,
+    finalize,
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL  //ConvertToType
+};
+
+JSStaticFunction JSCalendarManager::m_function[] = {
+    { CALENDAR_FUNCTION_API_GET_CALENDARS, getCalendars, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_GET_DEFAULT_CALENDAR, getDefaultCalendar, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_GET_UNIFIED_CALENDAR, getUnifiedCalendar, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_ADD_CALENDAR, addCalendar, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_REMOVE_CALENDAR, removeCalendar, kJSPropertyAttributeNone },
+    { CALENDAR_FUNCTION_API_GET_CALENDAR, getCalendar, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSCalendarManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+JSClassRef JSCalendarManager::m_jsClassRef = JSClassCreate(JSCalendarManager::getClassInfo());
+
+const JSClassDefinition* JSCalendarManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSCalendarManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+    JSObjectSetPrivate(object, static_cast<void*>(&CalendarManager::getInstance()));
+}
+
+void JSCalendarManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+JSValueRef JSCalendarManager::getCalendars(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    CalendarManagerCallbackUserData *callback = NULL;
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &CalendarManager::getInstance(),
+                CALENDAR_FUNCTION_API_GET_CALENDARS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string type = validator.toString(0);
+
+        callback = new CalendarManagerCallbackUserData(
+                GlobalContextManager::getInstance()->getGlobalContext(context),
+                Calendar::stringToCalendarType(type));
+
+        callback->setSuccessCallback(validator.toFunction(1, false));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        CalendarManager::getInstance().getCalendars(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("getCalendars BasePlatformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("getCalendar fails");
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getCalendars fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarManager::getDefaultCalendar(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &CalendarManager::getInstance(),
+                CALENDAR_FUNCTION_API_GET_DEFAULT_CALENDAR);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::string type = validator.toString(0, false);
+
+        JSObjectRef jsObject = JSCalendar::makeJSObject(context,
+                CalendarManager::getInstance().getDefaultCalendar(
+                Calendar::stringToCalendarType(type)));
+
+        return jsObject;
+
+    } catch (const BasePlatformException &err) {
+        LOGE("getDefaultCalendar BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getDefaultCalendar fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getDefaultCalendar fails");
+    }
+}
+
+JSValueRef JSCalendarManager::getUnifiedCalendar(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &CalendarManager::getInstance(),
+                CALENDAR_FUNCTION_API_GET_UNIFIED_CALENDAR);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::string type = validator.toString(0, false);
+
+        return JSCalendar::makeJSObject(context,
+                CalendarManager::getInstance().getUnifiedCalendar(
+                Calendar::stringToCalendarType(type)));
+    } catch (const BasePlatformException &err) {
+        LOGE("getUnifiedCalendar BasePlarformException caught: name: %s, msg: %s",
+        err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getUnifiedCalendar fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getUnifiedCalendar fails");
+    }
+}
+
+JSValueRef JSCalendarManager::addCalendar(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &CalendarManager::getInstance(),
+            CALENDAR_FUNCTION_API_ADD_CALENDAR);
+
+        auto &priv = CalendarManager::getInstance();
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // calendar
+        JSObjectRef calendarObj = validator.toObject(0, JSCalendar::getClassRef());
+        CalendarPtr calendar = JSCalendar::getPrivateObject(context, calendarObj);
+        if (!calendar) {
+            throw TypeMismatchException("Calendar's private object is NULL");
+        }
+
+        priv.addCalendar(calendar);
+    } catch (const BasePlatformException &err) {
+        LOGE("addCalendar BasePlatformException caught: name: %s, msg: %s",
+            err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("addCalendar fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "addCalendar fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarManager::removeCalendar(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &CalendarManager::getInstance(),
+            CALENDAR_FUNCTION_API_REMOVE_CALENDAR);
+
+        auto &priv = CalendarManager::getInstance();
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // type
+        std::string type = validator.toString(0);
+        if (validator.isOmitted(0)) {
+            throw TypeMismatchException("Calendar type parameter is missed");
+        }
+
+        // calendar_id
+        long calendar_id = validator.toLong(1);
+        if (validator.isOmitted(1)) {
+            throw TypeMismatchException("Calendar id parameter is missed.");
+        }
+
+        priv.removeCalendar(Calendar::stringToCalendarType(type), calendar_id);
+    } catch (const BasePlatformException &err) {
+        LOGE("removeCalendar BasePlatformException caught: name: %s, msg: %s",
+            err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("removeCalendar fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "removeCalendar fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarManager::getCalendar(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    SET_TIME_TRACER_ITEM(0);
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &CalendarManager::getInstance(),
+                CALENDAR_FUNCTION_API_GET_CALENDAR);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::string type = validator.toString(0, false);
+        long calendar_id = validator.toLong(1);
+
+        return JSCalendar::makeJSObject(context,
+                CalendarManager::getInstance().getCalendar(
+                        Calendar::stringToCalendarType(type), calendar_id));
+    } catch (const BasePlatformException &err) {
+        LOGE("getCalendar BasePlarformException caught: name: %s, msg: %s",
+        err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getCalendar fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getCalendar fails");
+    }
+}
+
+} // Calendar
+} // DeviceAPI
diff --git a/src/Calendar/JSCalendarManager.h b/src/Calendar/JSCalendarManager.h
new file mode 100755 (executable)
index 0000000..c88bec5
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_TIZEN_CALENDAR_MANAGER_H_
+#define _JS_TIZEN_CALENDAR_MANAGER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+
+class JSCalendarManager
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+    /**
+     * This structure contains properties and callbacks
+     * that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+    * This structure describes a statically declared function property.
+    */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getCalendars(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getUnifiedCalendar(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getDefaultCalendar(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addCalendar(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeCalendar(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getCalendar(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif // _JS_TIZEN_CALENDAR_MANAGER_H_
diff --git a/src/Calendar/JSCalendarRecurrenceRule.cpp b/src/Calendar/JSCalendarRecurrenceRule.cpp
new file mode 100755 (executable)
index 0000000..5831b31
--- /dev/null
@@ -0,0 +1,614 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSCalendarRecurrenceRule.h"
+#include "CalendarRecurrenceRule.h"
+#include "JSTZDate.h"
+#include "CalendarUtility.h"
+#include <JSUtil.h>
+#include <Logger.h>
+#include <Export.h>
+#include <PlatformException.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include "plugin_config.h"
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+struct CalendarRecurrenceRuleHolder {
+    CalendarRecurrenceRulePtr ptr;
+};
+
+namespace {
+
+const char *RECURRENCE_RULE_FREQUENCY = "frequency";
+const char *RECURRENCE_RULE_INTERVAL = "interval";
+const char *RECURRENCE_RULE_UNTIL_DATE = "untilDate";
+const char *RECURRENCE_RULE_OCCURRENCE_COUNT = "occurrenceCount";
+const char *RECURRENCE_RULE_DAYS_OF_THE_WEEK = "daysOfTheWeek";
+const char *RECURRENCE_RULE_SET_POSITIONS = "setPositions";
+const char *RECURRENCE_RULE_EXCEPTIONS = "exceptions";
+}
+
+JSClassDefinition JSCalendarRecurrenceRule::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_CALENDAR_CALENDAR_RECURRENCE_RULE_INTERFACE,
+    NULL,
+    m_property,
+    NULL, //m_function,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //constructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSCalendarRecurrenceRule::m_property[] = {
+    { RECURRENCE_RULE_FREQUENCY, getCalendarRecurrenceRuleFrequency, setCalendarRecurrenceRuleFrequency,
+        kJSPropertyAttributeDontDelete },
+    { RECURRENCE_RULE_INTERVAL, getCalendarRecurrenceRuleInterval, setCalendarRecurrenceRuleInterval,
+        kJSPropertyAttributeDontDelete },
+    { RECURRENCE_RULE_UNTIL_DATE, getCalendarRecurrenceRuleUntilDate, setCalendarRecurrenceRuleUntilDate,
+        kJSPropertyAttributeDontDelete },
+    { RECURRENCE_RULE_OCCURRENCE_COUNT, getCalendarRecurrenceRuleOccurrenceCount, setCalendarRecurrenceRuleOccurrenceCount,
+        kJSPropertyAttributeDontDelete },
+    { RECURRENCE_RULE_DAYS_OF_THE_WEEK, getCalendarRecurrenceRuleDaysOfTheWeek, setCalendarRecurrenceRuleDaysOfTheWeek,
+        kJSPropertyAttributeDontDelete },
+    { RECURRENCE_RULE_SET_POSITIONS, getCalendarRecurrenceRuleSetPositions, setCalendarRecurrenceRuleSetPositions,
+        kJSPropertyAttributeDontDelete },
+    { RECURRENCE_RULE_EXCEPTIONS, getCalendarRecurrenceRuleExceptions, setCalendarRecurrenceRuleExceptions,
+        kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+
+JSClassRef JSCalendarRecurrenceRule::m_jsClassRef = JSClassCreate(JSCalendarRecurrenceRule::getClassInfo());
+
+const JSClassDefinition* JSCalendarRecurrenceRule::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+JSClassRef DLL_EXPORT JSCalendarRecurrenceRule::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSCalendarRecurrenceRule::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("CalendarRecurrenceRule initizlize entered");
+}
+
+void JSCalendarRecurrenceRule::finalize(JSObjectRef object)
+{
+    LOGD("CalendarRecurrenceRule finalize entered");
+    CalendarRecurrenceRuleHolder *holder = static_cast<CalendarRecurrenceRuleHolder*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete holder;
+    holder = NULL;
+}
+
+CalendarRecurrenceRulePtr JSCalendarRecurrenceRule::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    CalendarRecurrenceRuleHolder *holder = static_cast<CalendarRecurrenceRuleHolder*>(JSObjectGetPrivate(object));
+    if (!holder) {
+        LOGE("Private object could not be accessed");
+        throw UnknownException("Private object could not be accessed");
+    }
+    if (!(holder->ptr)) {
+        LOGE("Holder prt is null");
+        throw UnknownException("Holder ptr is null");
+    }
+    return holder->ptr;
+}
+
+JSObjectRef JSCalendarRecurrenceRule::makeJSObject(JSContextRef context,
+        CalendarRecurrenceRulePtr priv)
+{
+    if (!priv) {
+        LOGW("Private object is NULL");
+        throw UnknownException("Private object is NULL");
+    }
+
+    CalendarRecurrenceRuleHolder *holder = new (std::nothrow) CalendarRecurrenceRuleHolder();
+    if (!holder) {
+        LOGE("Memory allocation error");
+        throw UnknownException("Memory allocation error");
+    }
+
+    holder->ptr = priv;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSCalendarRecurrenceRule::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("CalendarRecurrenceRule constructor entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+             | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    CalendarRecurrenceRulePtr priv;
+    CalendarRecurrenceRuleHolder *holder = NULL;
+
+    try {
+
+        priv = CalendarRecurrenceRulePtr(new (std::nothrow) CalendarRecurrenceRule());
+        if (!priv) {
+            LOGE("Priv in null");
+            throw TypeMismatchException("Priv is null");
+        }
+
+        std::string frequencyData = validator.toString(0, false);
+        JSObjectRef dictionary = validator.toObject(1, true);
+
+        CalendarRecurrenceRule::RecurrenceRuleFrequency frequency =
+                CalendarRecurrenceRule::stringToRecurrenceRuleFrequency(
+                frequencyData);
+        priv->setFrequency(frequency);
+
+        if (dictionary != NULL) {
+            JSValueRef intervalData = JSUtil::getProperty(context, dictionary, RECURRENCE_RULE_INTERVAL);
+            JSValueRef untilDateData = JSUtil::getProperty(context, dictionary, RECURRENCE_RULE_UNTIL_DATE);
+            JSValueRef occurrenceCountData = JSUtil::getProperty(context, dictionary, RECURRENCE_RULE_OCCURRENCE_COUNT);
+            JSValueRef daysOfTheWeekData = JSUtil::getProperty(context, dictionary, RECURRENCE_RULE_DAYS_OF_THE_WEEK);
+            JSValueRef setPositionsData = JSUtil::getProperty(context, dictionary, RECURRENCE_RULE_SET_POSITIONS);
+            JSValueRef ruleExceptionsData = JSUtil::getProperty(context, dictionary, RECURRENCE_RULE_EXCEPTIONS);
+
+            if (!JSValueIsUndefined(context, intervalData)) {
+                priv->setInterval(JSUtil::JSValueToLong(context, intervalData));
+            }
+
+            if (!JSValueIsUndefined(context, untilDateData)) {
+                TZDatePtr untilDate = JSTZDate::getPrivateObject(context, untilDateData);
+                priv->setUntilDate(CalendarUtility::localTimeToUTCTime(untilDate));
+                priv->setTimezone(untilDate->getTimezone());
+            }
+
+            if (!JSValueIsUndefined(context, occurrenceCountData)) {
+                priv->setOccurrenceCount(JSUtil::JSValueToLong(context, occurrenceCountData));
+            }
+
+            if (!JSValueIsUndefined(context, daysOfTheWeekData)) {
+                std::vector<std::string> str_vector_ = JSUtil::JSArrayToStringVector(context, daysOfTheWeekData);
+                std::vector<CalendarRecurrenceRule::RecurrenceRuleByDayValue> days_vector_;
+                const size_t size = str_vector_.size();
+                days_vector_.reserve(size);
+                for (size_t i = 0; i < size; i++) {
+                   days_vector_.push_back(CalendarRecurrenceRule::stringToRecurrenceRuleByDayValue(str_vector_[i]));
+                }
+                priv->setDaysOfTheWeek(days_vector_);
+            }
+
+            if (!JSValueIsUndefined(context, setPositionsData)) {
+                priv->setSetPositions(JSUtil::JSArrayToType_<long long int>(
+                        context, setPositionsData, JSUtil::JSValueToLongLong));
+            }
+
+            if (!JSValueIsUndefined(context, ruleExceptionsData)) {
+                priv->setExceptions(JSUtil::JSArrayToType_<TZDatePtr>(context,
+                        ruleExceptionsData, JSTZDate::getPrivateObject));
+            }
+       }
+    holder = new (std::nothrow) CalendarRecurrenceRuleHolder();
+        if (!holder) {
+            LOGE("Memory allocation error");
+            throw UnknownException("Memory allocation error");
+        }
+        holder->ptr = priv;
+
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("CalendarRecurrenceRule creation failed: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("CalendarRecurrenceRule creation failed - unsupported error");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSCalendarRecurrenceRule::getCalendarRecurrenceRuleFrequency(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        std::string frequency = CalendarRecurrenceRule::recurrenceRuleFrequencyToString(priv->getFrequency());
+        return JSUtil::toJSValueRef(context, frequency);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarRecurrenceRule::getCalendarRecurrenceRuleInterval(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        // Note that getIntervals() returns an int, we're casting it to long int
+        // before returning to JS.
+        // When setting the value, it has to be cast from long int back to int.
+        return JSUtil::toJSValueRef(context, static_cast<long int>(priv->getInterval()));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarRecurrenceRule::getCalendarRecurrenceRuleUntilDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        if (!priv->isUntilDateSet()) {
+            return JSValueMakeNull(context);
+        }
+
+        return JSTZDate::makeJSObject(context, CalendarUtility::utcTimeToTZDate(
+                priv->getTimezone().c_str(), priv->getUntilDate()));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarRecurrenceRule::getCalendarRecurrenceRuleOccurrenceCount(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getOccurrenceCount());
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarRecurrenceRule::getCalendarRecurrenceRuleDaysOfTheWeek(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv =
+                JSCalendarRecurrenceRule::getPrivateObject(context, object);
+        return priv->getJSDaysOfTheWeek(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarRecurrenceRule::getCalendarRecurrenceRuleSetPositions(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv =
+                JSCalendarRecurrenceRule::getPrivateObject(context, object);
+        return priv->getJSSetPositions(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCalendarRecurrenceRule::getCalendarRecurrenceRuleExceptions(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        return priv->getJSExceptions(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+bool JSCalendarRecurrenceRule::setCalendarRecurrenceRuleFrequency(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        CalendarRecurrenceRule::RecurrenceRuleFrequency frequency =
+            CalendarRecurrenceRule::stringToRecurrenceRuleFrequency(
+                JSUtil::JSValueToString(context, value));
+
+        priv->setFrequency(frequency);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarRecurrenceRule::setCalendarRecurrenceRuleInterval(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        priv->setInterval(static_cast<unsigned short>(JSUtil::JSValueToULong(context, value)));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarRecurrenceRule::setCalendarRecurrenceRuleUntilDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        if (JSValueIsNull(context, value)) {
+            if (!priv->isUntilDateSet()) {
+                return true;
+            }
+            else {
+                throw TypeMismatchException("The UntilDate  m_untilDate is NULL");
+            }
+        }
+
+        TZDatePtr ptr_until_date = JSTZDate::getPrivateObject(context, value);
+        priv->setUntilDate(CalendarUtility::localTimeToUTCTime(ptr_until_date));
+        priv->setTimezone(ptr_until_date->getTimezone());
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarRecurrenceRule::setCalendarRecurrenceRuleOccurrenceCount(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        priv->setOccurrenceCount(JSUtil::JSValueToNumber(context, value));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarRecurrenceRule::setCalendarRecurrenceRuleDaysOfTheWeek(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        std::vector<std::string> str_vector_ = JSUtil::JSArrayToStringVector(context, value);
+        std::vector<CalendarRecurrenceRule::RecurrenceRuleByDayValue> days_vector_;
+        const size_t size = str_vector_.size();
+        days_vector_.reserve(size);
+        for (size_t i = 0; i < size; i++) {
+            days_vector_.push_back(CalendarRecurrenceRule::stringToRecurrenceRuleByDayValue(str_vector_[i]));
+        }
+        priv->setDaysOfTheWeek(days_vector_);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarRecurrenceRule::setCalendarRecurrenceRuleSetPositions(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(
+            context, object);
+
+        std::vector<long long int> _value = JSUtil::JSArrayToType_<long long int>(
+            context, value, JSUtil::JSValueToLongLong);
+        priv->setSetPositions(_value);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+bool JSCalendarRecurrenceRule::setCalendarRecurrenceRuleExceptions(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        CalendarRecurrenceRulePtr priv = JSCalendarRecurrenceRule::getPrivateObject(context, object);
+
+        std::vector<TZDatePtr> exceptions = JSUtil::JSArrayToType_<TZDatePtr>(context, value, JSTZDate::getPrivateObject);
+        priv->setExceptions(exceptions);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+} // Calendar
+} // DeviceAPI
+
diff --git a/src/Calendar/JSCalendarRecurrenceRule.h b/src/Calendar/JSCalendarRecurrenceRule.h
new file mode 100755 (executable)
index 0000000..9f19665
--- /dev/null
@@ -0,0 +1,140 @@
+#ifndef _JS_CALENDAR_RECURRENCE_RULE_H_
+#define _JS_CALENDAR_RECURRENCE_RULE_H_
+
+#include "CalendarRecurrenceRule.h"
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class JSCalendarRecurrenceRule
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static CalendarRecurrenceRulePtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            CalendarRecurrenceRulePtr native);
+
+private:
+    static JSValueRef getCalendarRecurrenceRuleFrequency(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarRecurrenceRuleInterval(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarRecurrenceRuleUntilDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarRecurrenceRuleOccurrenceCount(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarRecurrenceRuleDaysOfTheWeek(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarRecurrenceRuleSetPositions(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCalendarRecurrenceRuleExceptions(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setCalendarRecurrenceRuleFrequency(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarRecurrenceRuleInterval(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarRecurrenceRuleUntilDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarRecurrenceRuleOccurrenceCount(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarRecurrenceRuleDaysOfTheWeek(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarRecurrenceRuleSetPositions(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCalendarRecurrenceRuleExceptions(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+
+    /**
+    * This member variable contains the values which has to be passed
+    * when the this class is embedded into JS Engine.
+    */
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec.
+     */
+    static JSStaticValue m_property[];
+
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif // _JS_CALENDAR_RECURRENCE_RULE_H_
+
diff --git a/src/Calendar/JSCalendarTask.cpp b/src/Calendar/JSCalendarTask.cpp
new file mode 100755 (executable)
index 0000000..a2ee533
--- /dev/null
@@ -0,0 +1,681 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        JSCalendarTask.cpp
+*/
+#include "CalendarManager.h"
+#include "CalendarUtility.h"
+#include "JSCalendarTask.h"
+#include "JSCalendarItem.h"
+#include "CalendarItem.h"
+#include "JSCalendarAlarm.h"
+#include "JSCalendarAttendee.h"
+#include "plugin_config.h"
+#include <JSTZDate.h>
+#include <JSTimeDuration.h>
+#include <JSSimpleCoordinates.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <Export.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <TimeTracer.h>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+struct CalendarTaskHolder {
+    CalendarTaskPtr ptr;
+};
+
+namespace {
+const char *CALENDAR_TASK_ID = "id";
+const char *CALENDAR_TASK_DUE_DATE = "dueDate";
+const char *CALENDAR_TASK_COMPLETED_DATE = "completedDate";
+const char *CALENDAR_TASK_PROGRESS = "progress";
+}
+
+JSClassDefinition JSCalendarTask::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_CALENDAR_CALENDAR_TASK_INTERFACE,
+        JSCalendarItem::getClassRef(),
+        m_property,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //callAsFunction,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSCalendarTask::m_property[] = {
+    { CALENDAR_TASK_ID, getId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { CALENDAR_TASK_DUE_DATE, getDueDate, setDueDate, kJSPropertyAttributeDontDelete },
+    { CALENDAR_TASK_COMPLETED_DATE, getCompletedDate, setCompletedDate, kJSPropertyAttributeDontDelete },
+    { CALENDAR_TASK_PROGRESS, getProgress, setProgress, kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSCalendarTask::m_function[] = {
+    {CALENDAR_FUNCTION_API_CONVERT_TO_STRING, convertToString, kJSPropertyAttributeNone},
+    {CALENDAR_FUNCTION_API_CLONE, clone, kJSPropertyAttributeNone},
+    //{CALENDAR_FUNCTION_API_EXPAND_RECURRENCE, expandRecurrence, kJSPropertyAttributeNone},
+    { 0, 0, 0 }
+};
+
+JSClassRef JSCalendarTask::m_jsClassRef = JSClassCreate(JSCalendarTask::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSCalendarTask::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSCalendarTask::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+CalendarTaskPtr JSCalendarTask::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    CalendarTaskHolder *holder = static_cast<CalendarTaskHolder*>(JSObjectGetPrivate(object));
+    if (!holder) {
+        LOGE("holder is null");
+        throw DeviceAPI::Common::UnknownException("Priv is null");
+    }
+    if (!holder->ptr) {
+        LOGE("Private object could not be accessed");
+        throw DeviceAPI::Common::UnknownException("Private object could not be accessed");
+    }
+
+    return holder->ptr;
+}
+
+void JSCalendarTask::setPrivateObject(JSObjectRef object, CalendarTaskPtr native)
+{
+    LOGD("Entered");
+    CalendarTaskHolder* priv = static_cast<CalendarTaskHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw DeviceAPI::Common::UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSCalendarTask::makeJSObject(JSContextRef context,
+        CalendarTaskPtr priv)
+{
+    if (!priv) {
+        LOGW("Private object is NULL");
+        throw DeviceAPI::Common::UnknownException("Private object is NULL");
+    }
+
+    CalendarTaskHolder *holder = new (std::nothrow) CalendarTaskHolder();
+    if (!holder) {
+        LOGE("Memory allocation error");
+        throw DeviceAPI::Common::UnknownException("Memory allocation error");
+    }
+
+    holder->ptr = priv;
+    holder->ptr->copyAceCheckAccessFunction(CalendarManager::getInstance());
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSCalendarTask::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef jsObjRef = JSObjectMake(context, JSCalendarTask::getClassRef(), NULL);
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+    enum JSCalendarTaskConstructorType {
+        CALENDAR_TASK_CONSTRUCTOR_TYPE_NO_PARAMS,
+        CALENDAR_TASK_CONSTRUCTOR_TYPE_OBJECT,
+        CALENDAR_TASK_CONSTRUCTOR_TYPE_STRING
+    };
+
+    JSCalendarTaskConstructorType constructor_type = CALENDAR_TASK_CONSTRUCTOR_TYPE_NO_PARAMS;
+
+    try{
+        if (validator.isOmitted(0) || validator.isNull(0) || validator.isUndefined(0)) {
+            constructor_type = CALENDAR_TASK_CONSTRUCTOR_TYPE_NO_PARAMS;
+        }
+        else if (JSValueIsObject(context, arguments[0])) {
+            constructor_type = CALENDAR_TASK_CONSTRUCTOR_TYPE_OBJECT;
+        }
+        else if (JSValueIsString(context, arguments[0]) && !validator.isOmitted(1)
+                && JSValueIsString(context, arguments[1])) {
+            constructor_type = CALENDAR_TASK_CONSTRUCTOR_TYPE_STRING;
+        }
+
+        CalendarTaskPtr priv = CalendarTaskPtr(new (std::nothrow) CalendarTask());
+        if (!priv) {
+            LOGE("Memory allocation error");
+            return jsObjRef;
+        }
+        switch (constructor_type) {
+            case CALENDAR_TASK_CONSTRUCTOR_TYPE_NO_PARAMS:
+                // nothing to be done
+                break;
+            case CALENDAR_TASK_CONSTRUCTOR_TYPE_OBJECT:
+            {
+                JSObjectRef dictionary = validator.toObject(0, true);
+
+                // CalendarItem related dictionary values
+                JSValueRef js_description = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_DESCRIPTION);
+                JSValueRef js_summary = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_SUMMARY);
+                JSValueRef js_is_all_day = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_IS_ALL_DAY);
+                JSValueRef js_start_date = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_START_DATE);
+                JSValueRef js_duration = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_DURATION);
+                JSValueRef js_location = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_LOCATION);
+                JSValueRef js_geolocation = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_GEOLOCATION);
+                JSValueRef js_organizer = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_ORGANIZER);
+                JSValueRef js_visibility = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_VISIBILITY);
+                JSValueRef js_status = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_STATUS);
+                JSValueRef js_priority = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_PRIORITY);
+                JSValueRef js_alarms = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_ALARMS);
+                JSValueRef js_categories = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_CATEGORIES);
+                JSValueRef js_attendees = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_ITEM_ATTENDEES);
+
+                //CalendarTask related dictionary values
+                JSValueRef dueDateData = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_TASK_DUE_DATE);
+                JSValueRef completedDateData = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_TASK_COMPLETED_DATE);
+                JSValueRef progressData = JSUtil::getProperty(context, dictionary,
+                    CALENDAR_TASK_PROGRESS);
+
+
+                // set CalendarItem attributes
+                if (!JSValueIsUndefined(context, js_description)
+                        && !JSValueIsNull(context, js_description)) {
+                    priv->setDescription(JSUtil::JSValueToString(context,
+                            js_description));
+                }
+
+                if (!JSValueIsUndefined(context, js_summary)
+                        && !JSValueIsNull(context, js_summary)) {
+                    priv->setSummary(JSUtil::JSValueToString(context, js_summary));
+                }
+
+                if (!JSValueIsUndefined(context, js_is_all_day)
+                        && !JSValueIsNull(context, js_is_all_day)) {
+                    priv->setIsAllDay(JSUtil::JSValueToBoolean(context, js_is_all_day));
+                }
+
+                if (!JSValueIsUndefined(context, js_start_date)
+                        && !JSValueIsNull(context, js_start_date)) {
+                    TZDatePtr date = JSTZDate::getPrivateObject(context, js_start_date);
+                    priv->setStartDate(CalendarUtility::localTimeToUTCTime(date), date->getTimezone());
+                }
+
+                if (!JSValueIsUndefined(context, js_duration)
+                        && !JSValueIsNull(context, js_duration)) {
+                    TimeDurationPtr duration = JSTimeDuration::getPrivateObject(context,
+                            js_duration);
+                    priv->setDuration(duration);
+                }
+
+                if (!JSValueIsUndefined(context, js_location)
+                        && !JSValueIsNull(context, js_location)) {
+                    priv->setLocation(JSUtil::JSValueToString(context, js_location));
+                }
+
+                if (!JSValueIsUndefined(context, js_geolocation)
+                        && !JSValueIsNull(context, js_geolocation)) {
+                    Tizen::SimpleCoordinatesPtr geolocation =
+                            Tizen::JSSimpleCoordinates::getPrivateObject(
+                                    context,js_geolocation);
+                    priv->setGeolocation(geolocation);
+                }
+
+                if (!JSValueIsUndefined(context, js_organizer)
+                        && !JSValueIsNull(context, js_organizer)) {
+                    priv->setOrganizer(JSUtil::JSValueToString(context, js_organizer));
+                }
+
+                if (!JSValueIsUndefined(context, js_visibility)
+                       && !JSValueIsNull(context, js_visibility)) {
+                    priv->setVisibility(CalendarItem::stringToCalendarItemVisibility(
+                        JSUtil::JSValueToString(context, js_visibility)));
+                }
+
+                if (!JSValueIsUndefined(context, js_status)
+                       && !JSValueIsNull(context, js_status)) {
+                    priv->setStatus(CalendarItem::stringToCalendarItemStatus(
+                        JSUtil::JSValueToString(context, js_status),priv->getType()));
+                }
+
+                if (!JSValueIsUndefined(context, js_priority)
+                       && !JSValueIsNull(context, js_priority)) {
+                    priv->setPriority(CalendarItem::stringToCalendarItemPriority(
+                        JSUtil::JSValueToString(context, js_priority)));
+                }
+
+                if (!JSValueIsUndefined(context, js_alarms)) {
+                    std::vector<CalendarAlarmPtr> alarms =
+                        JSUtil::JSArrayToType_<CalendarAlarmPtr>(
+                            context, js_alarms, JSCalendarAlarm::getPrivateObject);
+                    priv->setAlarms(alarms);
+                }
+
+                if (!JSValueIsUndefined(context, js_categories)) {
+                    priv->setCategories(JSUtil::JSArrayToStringVector(context,
+                            js_categories));
+                }
+
+                if (!JSValueIsUndefined(context, js_attendees)) {
+                    priv->setAttendees(JSUtil::JSArrayToType_<CalendarAttendeePtr>(context,
+                            js_attendees, JSCalendarAttendee::getPrivateObject));
+                }
+
+                //set CalendarTask attributes
+                if (!JSValueIsUndefined(context, dueDateData)
+                        && !JSValueIsNull(context, dueDateData)) {
+                    TZDatePtr date = JSTZDate::getPrivateObject(context, dueDateData);
+                    priv->setEndDate(CalendarUtility::localTimeToUTCTime(date), date->getTimezone());
+                }
+
+                if (!JSValueIsUndefined(context, completedDateData)
+                        && !JSValueIsNull(context, completedDateData)) {
+                    TZDatePtr date = JSTZDate::getPrivateObject(context,
+                            completedDateData);
+                    priv->setCompletedDate(CalendarUtility::localTimeToUTCTime(date), date->getTimezone());
+                }
+
+                if (!JSValueIsUndefined(context, progressData)) {
+                    long int progress = JSUtil::JSValueToLong(context, progressData);
+                    priv->setProgress(progress);
+                }
+
+            }
+            break;
+            case CALENDAR_TASK_CONSTRUCTOR_TYPE_STRING:
+            {
+                // expecting DOMString stringRepresentation, CalendarTextFormat format
+                std::string calendar_event_string = validator.toString(0, false);
+                std::string format = validator.toString(1, false);
+                if (TYPE_ICALENDAR_20 == format || TYPE_VCALENDAR_10 == format) {
+                    priv->setFormat(format);
+                }
+                else{
+                    LOGE("Invalid VCALENDAR format");
+                    throw TypeMismatchException("Invalid VCALENDAR format");
+                }
+                // second argument is ignored
+                priv->createPlatformCalendarItemFromString(calendar_event_string);
+                priv->convertPlatformTaskToAbstractCalendarTask();
+            }
+            break;
+        }
+
+        CalendarTaskHolder* holder = new(std::nothrow) CalendarTaskHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw DeviceAPI::Common::UnknownException("Holder is null");
+        }
+
+        holder->ptr = priv;
+        holder->ptr->copyAceCheckAccessFunction(CalendarManager::getInstance());
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+
+    } catch (const BasePlatformException &e) {
+        LOGE("CalendarTask creation failed: %s", e.getMessage().c_str());
+    } catch (...) {
+        LOGE("CalendarTask creation failed");
+    }
+    return jsObjRef;
+}
+
+void JSCalendarTask::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSCalendarTask::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+
+    CalendarTaskHolder *holder = static_cast<CalendarTaskHolder*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete holder;
+}
+
+JSValueRef JSCalendarTask::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CalendarTaskPtr priv = JSCalendarTask::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            throw DeviceAPI::Common::UnknownException("Private object is NULL");
+        }
+
+        if (priv->isSet(CALENDAR_TASK_ATTRIBUTE_ID)) {
+            return JSUtil::toJSValueRef(context, std::to_string(priv->getId()));
+        }
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("id get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting id");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarTask::getDueDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarTaskPtr priv = JSCalendarTask::getPrivateObject(context, object);
+
+        if (!(priv->CalendarItem::isSet(CALENDAR_ITEM_ATTRIBUTE_END_DATE))) {
+            return JSValueMakeNull(context);
+        }
+        return JSTZDate::makeJSObject(context, CalendarUtility::utcTimeToTZDate(
+                priv->getTimezone().c_str(), priv->getEndDate()));
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("dueDate get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting dueDate");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarTask::getCompletedDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarTaskPtr priv = JSCalendarTask::getPrivateObject(context, object);
+
+        if (!(priv->isSet(CALENDAR_TASK_ATTRIBUTE_COMPLETED_DATE))) {
+            return JSValueMakeNull(context);
+        }
+        return JSTZDate::makeJSObject(context, CalendarUtility::utcTimeToTZDate(
+                priv->getTimezone().c_str(), priv->getCompletedDate()));
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("completedDate get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting completedDate");
+    }
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSCalendarTask::getProgress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarTaskPtr priv = JSCalendarTask::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            throw DeviceAPI::Common::UnknownException("Private object is NULL");
+        }
+        return JSUtil::toJSValueRef(context, static_cast<unsigned long>(priv->getProgress()));
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("id get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting id");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSCalendarTask::setDueDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarTaskPtr priv = JSCalendarTask::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            return true;
+        }
+        TZDatePtr dueDate = JSTZDate::getPrivateObject(context, value);
+        priv->setEndDate(CalendarUtility::localTimeToUTCTime(dueDate), dueDate->getTimezone());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("endDate set failed: %s : %s", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting dueDate");
+    }
+    return true;
+}
+
+bool JSCalendarTask::setCompletedDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarTaskPtr priv = JSCalendarTask::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            return true;
+        }
+        TZDatePtr completedDate = JSTZDate::getPrivateObject(context, value);
+        priv->setCompletedDate(CalendarUtility::localTimeToUTCTime(completedDate), completedDate->getTimezone());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("endDate set failed: %s : %s", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting completedDate");
+    }
+    return true;
+}
+
+bool JSCalendarTask::setProgress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        CalendarTaskPtr priv = JSCalendarTask::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            return true;
+        }
+        unsigned int progress = JSUtil::JSValueToULong(context, value);
+        priv->setProgress(progress);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("endDate set failed: %s : %s", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting endDate");
+    }
+    return true;
+
+}
+
+
+JSValueRef JSCalendarTask::convertToString(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    try{
+
+        CalendarTaskPtr priv = JSCalendarTask::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CALENDAR_FUNCTION_API_CONVERT_TO_STRING);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        if (!validator.isOmitted(0) && JSValueIsString(context, arguments[0])) {
+            std::string format = validator.toString(0);
+            if (TYPE_ICALENDAR_20 == format || TYPE_VCALENDAR_10 == format) {
+                priv->setFormat(format);
+                priv->convertAbstractCalendarTaskToPlatformCalendarTask();
+                std::string calendar = priv->exportCalendarItemToString();
+                return JSUtil::toJSValueRef(context, calendar);
+            }
+            else{
+                LOGE("Input parameter is not compatible with the expected value"
+                        " for that parameter");
+                throw TypeMismatchException("input parameter is not compatible"
+                        " with the expected value for that parameter");
+            }
+        }
+        else{
+            LOGE("Input parameter is not compatible with the expected type "
+                    "for that parameter");
+            throw TypeMismatchException(
+                    "Input parameter is not compatible with the expected type "
+                    "for that parameter");
+            }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("convertToString function failed", (err.getName()).c_str(),
+                (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("convertToString function failed, Unknown Exception");
+        return JSWebAPIErrorFactory::postException(context, exception, "UnknownError");
+    }
+}
+
+JSValueRef JSCalendarTask::clone(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+    JSObjectRef jsObjRef = JSObjectMake(context, JSCalendarTask::getClassRef(), NULL);
+
+    try{
+
+        CalendarTaskPtr priv_orgin = JSCalendarTask::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv_orgin.get(), CALENDAR_FUNCTION_API_CLONE);
+
+        CalendarTaskPtr priv_new(new CalendarTask(*priv_orgin));
+
+        if (!priv_new) {
+            LOGE("Priv is null");
+            throw DeviceAPI::Common::UnknownException("Can not allocate memory");
+        }
+
+        CalendarTaskHolder* holder = new(std::nothrow) CalendarTaskHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw DeviceAPI::Common::UnknownException("Holder is null");
+        }
+        holder->ptr = priv_new;
+        priv_new->setId(0);
+        priv_new->setIsSet(CALENDAR_TASK_ATTRIBUTE_ID, false);
+        priv_new->setCalendarId(UNDEFINED_CALENDAR_ID);
+        priv_new->CalendarItem::setIsSet(CALENDAR_ITEM_ATTRIBUTE_CALENDAR_ID,false);
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("clone function failed", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("clone function failed, Unknown Exception");
+        return JSWebAPIErrorFactory::postException(context, exception, "UnknownError");
+    }
+
+    return jsObjRef;
+}
+
+
+
+}  // Calendar
+}  // DeviceAPI
+
diff --git a/src/Calendar/JSCalendarTask.h b/src/Calendar/JSCalendarTask.h
new file mode 100755 (executable)
index 0000000..76d6610
--- /dev/null
@@ -0,0 +1,124 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        JSCalendarTask.h
+*/
+
+#ifndef _JS_TIZEN_CALENDAR_TASK_H_
+#define _JS_TIZEN_CALENDAR_TASK_H_
+
+#include "CalendarTask.h"
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Calendar {
+
+class JSCalendarTask {
+
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static CalendarTaskPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, CalendarTaskPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            CalendarTaskPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+                JSObjectRef constructor,
+                size_t argumentCount,
+                const JSValueRef arguments[],
+                JSValueRef* exception);
+
+private:
+
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_jsClassRef;
+
+    static JSStaticValue m_property[];
+
+    static JSStaticFunction m_function[];
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDueDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCompletedDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getProgress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setDueDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCompletedDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setProgress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef convertToString(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef clone(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+};
+
+} // Calendar
+} // DeviceAPI
+
+#endif // _JS_TIZEN_CALENDAR_TASK_H_
diff --git a/src/Calendar/config.xml b/src/Calendar/config.xml
new file mode 100755 (executable)
index 0000000..ac89feb
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-calendar.so</library-name>
+    <feature-install-uri>calendar.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/calendar.read</name>
+        <device-capability>calendar.read</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/calendar.write</name>
+        <device-capability>calendar.write</device-capability>
+    </api-feature>
+
+</plugin-properties>
\ No newline at end of file
diff --git a/src/Calendar/plugin_config.cpp b/src/Calendar/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..155c93c
--- /dev/null
@@ -0,0 +1,292 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <iostream>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define CALENDAR_FEATURE_API_READ  "http://tizen.org/privilege/calendar.read"
+#define CALENDAR_FEATURE_API_WRITE "http://tizen.org/privilege/calendar.write"
+
+#define CALENDAR_DEVICE_CAP_READ "calendar.read"
+#define CALENDAR_DEVICE_CAP_WRITE "calendar.write"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Calendar {
+
+static FunctionMapping createCalendarFunctions();
+
+static FunctionMapping CalendarFunctions = createCalendarFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(Calendar, CalendarFunctions);
+
+#pragma GCC visibility pop
+
+static FunctionMapping createCalendarFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_CALENDAR_READ, CALENDAR_DEVICE_CAP_READ);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_CALENDAR_WRITE, CALENDAR_DEVICE_CAP_WRITE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_CALENDAR_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_CALENDAR_READ, DEVICE_CAP_CALENDAR_READ);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_CALENDAR_WRITE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_CALENDAR_WRITE, DEVICE_CAP_CALENDAR_WRITE);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_CALENDAR_READ, CALENDAR_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_CALENDAR_WRITE, CALENDAR_FEATURE_API_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(CALENDAR_FEATURES_CALENDAR_READ);
+    ACE_ADD_API_FEATURE(CALENDAR_FEATURES_CALENDAR_READ, FEATURE_CALENDAR_READ);
+
+    ACE_CREATE_FEATURE_LIST(CALENDAR_FEATURES_CALENDAR_WRITE);
+    ACE_ADD_API_FEATURE(CALENDAR_FEATURES_CALENDAR_WRITE, FEATURE_CALENDAR_WRITE);
+
+    /**
+     * Functions
+     */
+    FunctionMapping calendarMapping;
+
+    //getCalendars
+    AceFunction getCalendarsFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_CALENDARS,
+            CALENDAR_FUNCTION_API_GET_CALENDARS,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_GET_CALENDARS,
+                               getCalendarsFunc));
+
+    //getDefaultCalendar
+    AceFunction getDefaultCalendarFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_DEFAULT_CALENDAR,
+            CALENDAR_FUNCTION_API_GET_DEFAULT_CALENDAR,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_GET_DEFAULT_CALENDAR,
+                               getDefaultCalendarFunc));
+
+    //getUnifiedCalendar
+    AceFunction getUnifiedCalendarFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_UNIFIED_CALENDAR,
+            CALENDAR_FUNCTION_API_GET_UNIFIED_CALENDAR,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_GET_UNIFIED_CALENDAR,
+                               getUnifiedCalendarFunc));
+
+    //getCalendar
+    AceFunction getCalendarFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_CALENDAR,
+            CALENDAR_FUNCTION_API_GET_CALENDAR,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_GET_CALENDAR,
+                               getCalendarFunc));
+
+    //addCalendar
+    AceFunction addCalendarFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD_CALENDAR,
+            CALENDAR_FUNCTION_API_ADD_CALENDAR,
+            CALENDAR_FEATURES_CALENDAR_WRITE,
+            DEVICE_LIST_CALENDAR_WRITE);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_ADD_CALENDAR,
+                               addCalendarFunc));
+
+    //removeCalendar
+    AceFunction removeCalendarFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_CALENDAR,
+            CALENDAR_FUNCTION_API_REMOVE_CALENDAR,
+            CALENDAR_FEATURES_CALENDAR_WRITE,
+            DEVICE_LIST_CALENDAR_WRITE);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_REMOVE_CALENDAR,
+                               removeCalendarFunc));
+
+    //find
+    AceFunction findFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_FIND,
+            CALENDAR_FUNCTION_API_FIND,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_FIND,
+                               findFunc));
+
+    //add
+    AceFunction addFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD,
+            CALENDAR_FUNCTION_API_ADD,
+            CALENDAR_FEATURES_CALENDAR_WRITE,
+            DEVICE_LIST_CALENDAR_WRITE);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_ADD,
+                               addFunc));
+
+    //addBatch
+    AceFunction addBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD_BATCH,
+            CALENDAR_FUNCTION_API_ADD_BATCH,
+            CALENDAR_FEATURES_CALENDAR_WRITE,
+            DEVICE_LIST_CALENDAR_WRITE);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_ADD_BATCH,
+                               addBatchFunc));
+
+    //update
+    AceFunction updateFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UPDATE,
+            CALENDAR_FUNCTION_API_UPDATE,
+            CALENDAR_FEATURES_CALENDAR_WRITE,
+            DEVICE_LIST_CALENDAR_WRITE);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_UPDATE,
+                               updateFunc));
+
+    //updateBatch
+    AceFunction updateBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UPDATE_BATCH,
+            CALENDAR_FUNCTION_API_UPDATE_BATCH,
+            CALENDAR_FEATURES_CALENDAR_WRITE,
+            DEVICE_LIST_CALENDAR_WRITE);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_UPDATE_BATCH,
+                               updateBatchFunc));
+
+    //remove
+    AceFunction removeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE,
+            CALENDAR_FUNCTION_API_REMOVE,
+            CALENDAR_FEATURES_CALENDAR_WRITE,
+            DEVICE_LIST_CALENDAR_WRITE);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_REMOVE,
+                               removeFunc));
+
+    //removeBatch
+    AceFunction removeBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_BATCH,
+            CALENDAR_FUNCTION_API_REMOVE_BATCH,
+            CALENDAR_FEATURES_CALENDAR_WRITE,
+            DEVICE_LIST_CALENDAR_WRITE);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_REMOVE_BATCH,
+                               removeBatchFunc));
+
+    //convertToString
+    AceFunction convertToStringFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONVERT_TO_STRING,
+            CALENDAR_FUNCTION_API_CONVERT_TO_STRING,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_CONVERT_TO_STRING,
+                               convertToStringFunc));
+
+    //addChangeListener
+    AceFunction addChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD_CHANGE_LISTENER,
+            CALENDAR_FUNCTION_API_ADD_CHANGE_LISTENER,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_ADD_CHANGE_LISTENER,
+                               addChangeListenerFunc));
+
+    //removeChangeListener
+    AceFunction removeChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_CHANGE_LISTENER,
+            CALENDAR_FUNCTION_API_REMOVE_CHANGE_LISTENER,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_REMOVE_CHANGE_LISTENER,
+                               removeChangeListenerFunc));
+
+    //expandRecurrence
+    AceFunction expandRecurrenceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_EXPAND_RECURRENCE,
+            CALENDAR_FUNCTION_API_EXPAND_RECURRENCE,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_EXPAND_RECURRENCE,
+                               expandRecurrenceFunc));
+
+    //get
+    AceFunction getFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET,
+            CALENDAR_FUNCTION_API_GET,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_GET,
+                               getFunc));
+
+    //clone
+    AceFunction cloneFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CLONE,
+            CALENDAR_FUNCTION_API_CLONE,
+            CALENDAR_FEATURES_CALENDAR_READ,
+            DEVICE_LIST_CALENDAR_READ);
+
+    calendarMapping.insert(std::make_pair(
+                               CALENDAR_FUNCTION_API_CLONE,
+                               getFunc));
+
+    return calendarMapping;
+}
+
+}
+}
diff --git a/src/Calendar/plugin_config.h b/src/Calendar/plugin_config.h
new file mode 100755 (executable)
index 0000000..ce04419
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _CALENDAR_PLUGIN_CONFIG_H_
+#define _CALENDAR_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+#include <Security.h>
+
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+DECLARE_FUNCTION_GETTER(Calendar);
+
+#define CALENDAR_CHECK_ACCESS(functionName) \
+        aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+        getCalendarFunctionData, \
+        functionName)
+}
+}
+
+#endif //  _CALENDAR_PLUGIN_CONFIG_H_
diff --git a/src/Calendar/plugin_config_impl.h b/src/Calendar/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..8ae9db0
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _CALENDAR_PLUGIN_CONFIG_IMPL_H_
+#define _CALENDAR_PLUGIN_CONFIG_IMPL_H_
+
+// Functions from calendar manager
+#define CALENDAR_FUNCTION_API_GET_CALENDARS "getCalendars"
+#define CALENDAR_FUNCTION_API_GET_DEFAULT_CALENDAR "getDefaultCalendar"
+#define CALENDAR_FUNCTION_API_GET_UNIFIED_CALENDAR "getUnifiedCalendar"
+#define CALENDAR_FUNCTION_API_GET_CALENDAR "getCalendar"
+#define CALENDAR_FUNCTION_API_ADD_CALENDAR "addCalendar"
+#define CALENDAR_FUNCTION_API_REMOVE_CALENDAR "removeCalendar"
+
+// Functions from calendar
+#define CALENDAR_FUNCTION_API_ADD "add"
+#define CALENDAR_FUNCTION_API_ADD_BATCH "addBatch"
+#define CALENDAR_FUNCTION_API_UPDATE "update"
+#define CALENDAR_FUNCTION_API_UPDATE_BATCH "updateBatch"
+#define CALENDAR_FUNCTION_API_REMOVE "remove"
+#define CALENDAR_FUNCTION_API_REMOVE_BATCH "removeBatch"
+#define CALENDAR_FUNCTION_API_FIND "find"
+#define CALENDAR_FUNCTION_API_CONVERT_TO_STRING "convertToString"
+#define CALENDAR_FUNCTION_API_ADD_CHANGE_LISTENER "addChangeListener"
+#define CALENDAR_FUNCTION_API_REMOVE_CHANGE_LISTENER "removeChangeListener"
+#define CALENDAR_FUNCTION_API_EXPAND_RECURRENCE "expandRecurrence"
+#define CALENDAR_FUNCTION_API_GET "get"
+#define CALENDAR_FUNCTION_API_CLONE "clone"
+
+#define TIZEN_CALENDAR_CALENDAR_MANAGER_CLASS "calendar"
+#define TIZEN_CALENDAR_CALENDAR_INTERFACE "Calendar"
+#define TIZEN_CALENDAR_CALENDAR_TASK_INTERFACE "CalendarTask"
+#define TIZEN_CALENDAR_CALENDAR_RECURRENCE_RULE_INTERFACE "CalendarRecurrenceRule"
+#define TIZEN_CALENDAR_CALENDAR_EVENT_ID_INTERFACE "CalendarEventId"
+#define TIZEN_CALENDAR_CALENDAR_EVENT_INTERFACE "CalendarEvent"
+#define TIZEN_CALENDAR_CALENDAR_ATTENDEE_INTERFACE "CalendarAttendee"
+#define TIZEN_CALENDAR_CALENDAR_ALARM_INTERFACE "CalendarAlarm"
+
+#endif //  _CALENDAR_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/Calendar/plugin_initializer.cpp b/src/Calendar/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..ec085e5
--- /dev/null
@@ -0,0 +1,165 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <Security.h>
+#include <TimeTracer.h>
+
+#include "CalendarManager.h"
+#include "JSCalendar.h"
+#include "JSCalendarAlarm.h"
+#include "JSCalendarAttendee.h"
+#include "JSCalendarEvent.h"
+#include "JSCalendarEventId.h"
+#include "JSCalendarManager.h"
+#include "JSCalendarRecurrenceRule.h"
+#include "JSCalendarTask.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Calendar {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+AceSecurityStatus calendarAceCheckAccessFunction(const char* functionName)
+{
+    return CALENDAR_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerCalendarSetter, CalendarManager, gSecurityAccessor);
+DEFINE_JSOBJECT_SECURITY_ACCESSOR_SETTER(AceCheckerCalendarConstructorSetter, gSecurityAccessor);
+
+class_definition_options_t CalendarOptions =
+{
+    JS_CLASS,
+    CREATE_INSTANCE,
+    ALWAYS_NOTICE,
+    USE_OVERLAYED, //ignored
+    AceCheckerCalendarSetter,
+    NULL,
+    NULL
+};
+
+class_definition_options_t CalendarInterfaceOptions = {
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    ALWAYS_NOTICE,
+    USE_OVERLAYED, //ignored
+    AceCheckerCalendarConstructorSetter, // JSWidget::acquireGlobalContext,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Calendar] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, calendarAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Calendar] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "Calendar";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+      LOGE("WrtAccess deinitialization failed");
+    }
+
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Calendar] on_frame_load_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Calendar] on_frame_unload_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CALENDAR_CALENDAR_MANAGER_CLASS,
+        (js_class_template_getter)JSCalendarManager::getClassRef,
+        &CalendarOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CALENDAR_CALENDAR_INTERFACE,
+        (js_class_template_getter)JSCalendar::getClassRef,
+        (js_class_constructor_cb_t)JSCalendar::constructor,
+        &CalendarInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CALENDAR_CALENDAR_EVENT_INTERFACE,
+        (js_class_template_getter)JSCalendarEvent::getClassRef,
+        (js_class_constructor_cb_t)JSCalendarEvent::constructor,
+        &CalendarInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CALENDAR_CALENDAR_TASK_INTERFACE,
+        (js_class_template_getter)JSCalendarTask::getClassRef,
+        (js_class_constructor_cb_t)JSCalendarTask::constructor,
+        &CalendarInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CALENDAR_CALENDAR_ATTENDEE_INTERFACE,
+        (js_class_template_getter)JSCalendarAttendee::getClassRef,
+        (js_class_constructor_cb_t)JSCalendarAttendee::constructor,
+        &CalendarInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CALENDAR_CALENDAR_RECURRENCE_RULE_INTERFACE,
+        (js_class_template_getter)JSCalendarRecurrenceRule::getClassRef,
+        (js_class_constructor_cb_t)JSCalendarRecurrenceRule::constructor,
+        &CalendarInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CALENDAR_CALENDAR_EVENT_ID_INTERFACE,
+        (js_class_template_getter)JSCalendarEventId::getClassRef,
+        (js_class_constructor_cb_t)JSCalendarEventId::constructor,
+        &CalendarInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CALENDAR_CALENDAR_ALARM_INTERFACE,
+        (js_class_template_getter)JSCalendarAlarm::getClassRef,
+        (js_class_constructor_cb_t)JSCalendarAlarm::constructor,
+        &CalendarInterfaceOptions)
+PLUGIN_CLASS_MAP_END
+
+}
+}
+
diff --git a/src/Callhistory/CMakeLists.txt b/src/Callhistory/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..08f1b51
--- /dev/null
@@ -0,0 +1,67 @@
+SET(TARGET_NAME ${callhistory_target})
+SET(DESTINATION_NAME ${callhistory_dest})
+SET(TARGET_IMPL_NAME ${callhistory_impl})
+
+IF(ENABLE_OPTIONAL_CALL_HISTORY)
+PKG_CHECK_MODULES(platform_pkgs_callhistory REQUIRED contacts-service2 glib-2.0 libpcrecpp tapi)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+SET(INCLUDE_DIRS
+    ${contact_include}
+    ${tizen_include}
+    ${platform_pkgs_callhistory_INCLUDE_DIRS}
+)
+
+INCLUDE_DIRECTORIES(${INCLUDE_COMMON} ${INCLUDE_DIRS})
+MESSAGE(STATUS "${TARGET_NAME} module includes: INCLUDE_COMMON ${INCLUDE_DIRS}")
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${contact_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    CallHistory.cpp
+    CallHistoryEntry.cpp
+    JSCallHistory.cpp
+    JSCallHistoryEntry.cpp
+    JSRemoteParty.cpp
+    RemoteParty.cpp
+    CallHistoryEntryArraySuccessCallback.cpp
+    CallHistoryChangeCallback.cpp
+    CallHistoryFilterQueryGenerator.cpp
+    CallHistoryUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+SET(LINK_LIBS
+    ${tizen_impl}
+    ${contact_impl}
+    ${platform_pkgs_callhistory_LIBRARIES}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME} ${LIBS_COMMON} ${LINK_LIBS})
+MESSAGE(STATUS "${TARGET_NAME} module links: LIBS_COMMON ${LINK_LIBS}")
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_CALL_HISTORY)
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/callhistory
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Callhistory/CallHistory.cpp b/src/Callhistory/CallHistory.cpp
new file mode 100755 (executable)
index 0000000..9c8eaea
--- /dev/null
@@ -0,0 +1,1296 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CallHistoryTypes.h"
+#include "CallHistory.h"
+#include "JSCallHistoryEntry.h"
+#include "CallHistory.h"
+#include "CallHistoryFilterQueryGenerator.h"
+#include "CallHistoryUtil.h"
+#include <FilterIterator.h>
+
+#include <iomanip>
+#include <CommonsJavaScript/Converter.h>
+#include <PlatformException.h>
+#include <Logger.h>
+#include <Ecore.h>
+#include <AbstractFilter.h>
+#include <cassert>
+#include <Commons/Exception.h>
+#include <TimeTracer.h>
+#include <JSWebAPIException.h>
+#include <GlobalContextManager.h>
+#include <memory>
+#include <future>
+#include <thread>
+#include <tapi_common.h>
+#include <TelSim.h>
+#include <ITapiSim.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+using namespace std;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+namespace {
+    static void get_sim_msisdn_cb(TapiHandle *handle,
+            int result, void *data, void *user_data)
+    {
+        LOGD("Enter");
+
+        TelSimMsisdnList_t *list;
+        std::promise<std::string> *prom =
+            reinterpret_cast<std::promise<std::string> *>(user_data);
+
+        char *number = NULL;
+        if (result == TAPI_SIM_ACCESS_SUCCESS) {
+            list = static_cast<TelSimMsisdnList_t *>(data);
+            if (list->count) {
+                number = list->list[0].num;
+            }
+
+            LOGD("Phone number: %s", number);
+        } else {
+            LOGE("Failed to access sim %d", result);
+        }
+
+        std::string n = number ? std::string(number) : "";
+        prom->set_value(n);
+    }
+}
+
+CallHistory::CallHistory():
+    m_listener_counter(0)
+{
+    LOGD("Entered");
+
+    int ret = contacts_connect();
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("Failed to connect Call history DB %d: %s",
+           ret, CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        return;
+    }
+    LOGD("Successful to connect Call history DB ");
+}
+
+CallHistory::~CallHistory()
+{
+    LOGD("Entered");
+    for(auto iter = m_listeners.begin(); iter != m_listeners.end(); iter++) {
+        removeChangeListener(NULL, iter->first);
+    }
+
+    int ret = contacts_disconnect();
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("Failed to disconnect Call history DB %d: %s",
+            ret, CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        return;
+    }
+    LOGD("Successful to disconnect Call history DB ");
+}
+
+CallHistory* CallHistory::getInstance() {
+    static CallHistory instance;
+    return &instance;
+}
+
+static gboolean findJobCompleteCB(void *data) {
+
+    LOGD("Entered");
+    CallHistoryEntryArraySuccessCallback *callback =
+        static_cast<CallHistoryEntryArraySuccessCallback*>(data);
+    JSContextRef context = callback->getContext();
+
+    std::vector<CallHistoryEntryPtr> callEntryList =
+        callback->getCallhistoryEntries();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    if (callback->isError()) {
+        JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context,
+            callback->getErrorName(), callback->getErrorMessage());
+        callback->callErrorCallback(error);
+    }
+
+    JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
+
+    if (jsResult == NULL) {
+        UnknownException error("Unknown error");
+        callback->callErrorCallback(
+                JSWebAPIErrorFactory::makeErrorObject(context, error));
+        return false;
+    }
+
+    LOGD("enter : callEntryList.size() %d", callEntryList.size());
+    for (std::size_t i = 0; i < callEntryList.size(); ++i) {
+        JSValueRef tempCallEntry =
+            JSCallHistoryEntry::createJSObject(context, callEntryList[i]);
+        if (!JSSetArrayElement(context, jsResult, i, tempCallEntry)) {
+            UnknownException error("Unknown error");
+            callback->callErrorCallback(
+                JSWebAPIErrorFactory::makeErrorObject(context, error));
+            return false;
+        }
+    }
+
+    callback->callSuccessCallback(jsResult);
+
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+static void* findWorkerThread(void *data)
+{
+    LOGD("Entered");
+    CallHistoryEntryArraySuccessCallback *callback = NULL;
+    int ret = 0;
+    try {
+        callback = static_cast<CallHistoryEntryArraySuccessCallback*>(data);
+        if (!callback) {
+            LOGE("Callback is NULL!");
+            throw UnknownException("callback is null");
+        }
+
+        ret = contacts_connect_on_thread();
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+               "contacts_connect_on_thread failed");
+        }
+
+        contacts_query_h query = NULL;
+        ret = contacts_query_create(_contacts_phone_log._uri, &query);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_query_create failed");
+        }
+
+        contacts_filter_h filter = NULL;
+        ret = contacts_filter_create(_contacts_phone_log._uri, &filter);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_filter_create failed");
+        }
+
+        if (callback->getFilterIsSet()) {
+            LOGD("Filter:%p is set", callback->getFilter().get());
+            CallHistoryFilterQueryGenerator filter_query_gen(filter);
+            filter_query_gen.generate(callback->getFilter());
+
+            ret = contacts_filter_add_operator(filter,
+                CONTACTS_FILTER_OPERATOR_AND);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(filter, _contacts_phone_log.log_type,
+                CONTACTS_MATCH_LESS_THAN_OR_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            LOGD("Filter is not set");
+            ret = contacts_filter_add_int(filter, _contacts_phone_log.log_type,
+                    CONTACTS_MATCH_LESS_THAN_OR_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        ret = contacts_query_set_filter(query, filter);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+
+        bool is_ascending = false;
+        if (callback->getSortModesIsSet()) {
+            if (callback->getSortMode()->getOrder() == Tizen::ASC) {
+                is_ascending = true;
+            }
+
+            const std::string attri_name(callback->getSortMode()->getAttributeName());
+            ret = contacts_query_set_sort(query,
+                CallHistory::convertAttrName(attri_name), is_ascending);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_query_set_sort failed");
+            }
+        } else {
+            ret = contacts_query_set_sort(query, _contacts_phone_log.id,
+                is_ascending);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_query_set_sort failed");
+            }
+        }
+
+        int limit = 0;
+        if (callback->getLimitIsSet()) {
+            limit = static_cast<int>(callback->getLimit());
+        }
+
+        int offset = 0;
+        if (callback->getOffsetIsSet()) {
+            offset = static_cast<int>(callback->getOffset());
+        }
+
+        LOGD("offset:%d limit:%d sort mode:%s", offset, limit, (is_ascending ?
+            "ascending" : "descending"));
+
+        contacts_list_h record_list = NULL;
+        ret = contacts_db_get_records_with_query(query, offset, limit,
+            &record_list);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_db_get_records_with_query failed");
+        }
+
+        std::vector<CallHistoryEntryPtr> callhistory_entries;
+        if (CallHistory::parseRecord(&record_list, callhistory_entries)) {
+            LOGD("CallHistory::parseRecord success, callhistory_entries.size() is %d",
+               callhistory_entries.size());
+            callback->setCallhistoryEntries(callhistory_entries);
+        }
+        else {
+            LOGD("CallHistory::parseRecord error");
+        }
+
+        callhistory_entries.clear();
+
+        ret = contacts_list_destroy(record_list, true);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_list_destroy failed");
+        }
+        ret = contacts_query_destroy(query);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_query_destroy failed");
+        }
+        ret = contacts_filter_destroy(filter);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_fliter_destroy failed");
+        }
+
+        ret = contacts_disconnect_on_thread();
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_disconnect_on_thread failed");
+        }
+        LOGD("Success to disconnect Call History DB for thread");
+
+    } catch (const Commons::PlatformException& ex) {
+        LOGE("Exception %s occured with message: %s", ex.GetClassName().c_str(),
+            ex.GetMessage().c_str());
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, ex.GetMessage());
+    } catch (const Common::BasePlatformException &ex) {
+        LOGE("Exception %s occured with message: %s", ex.getName().c_str(),
+            ex.getMessage().c_str());
+        callback->setError(ex.getName(), ex.getMessage());
+    } catch (...) {
+        LOGE("Unknown exception occured");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+            "UnknownException occured");
+    }
+
+    if (!g_idle_add(findJobCompleteCB, data)) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+
+static void* removeAllWorkerThread(void *data)
+{
+    int ret = 0;
+    CallHistoryEntryRemoveCallback *callback = NULL;
+    try {
+        ret = contacts_connect_on_thread();
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_connect_on_thread failed");
+        }
+        LOGD("Success to connect Call History DB for thread");
+
+        callback = static_cast<CallHistoryEntryRemoveCallback*>(data);
+        int* list = NULL;
+        contacts_list_h record_list = NULL;
+        contacts_record_h record = NULL;
+        int total = 0;
+        unsigned int cnt = 0;
+        int value = 0;
+
+        ret = contacts_db_get_all_records(_contacts_phone_log._uri, 0, 0,
+            &record_list);
+
+        JSContextRef context = callback->getContext();
+
+        if (!GlobalContextManager::getInstance()->
+            isAliveGlobalContext(context)) {
+
+            LOGE("context was closed");
+            delete callback;
+            callback = NULL;
+            if (record_list != NULL) {
+                ret = contacts_list_destroy(record_list, true);
+                if (ret != CONTACTS_ERROR_NONE) {
+                    LOGE("%d: %s", ret,
+                        CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+                }
+            }
+            return NULL;
+        }
+
+        if (record_list == NULL) {
+            UnknownException error("Unknown error");
+            callback->callErrorCallback(JSWebAPIErrorFactory::makeErrorObject(
+                context, error));
+            return NULL;
+        }
+
+        ret = contacts_list_get_count(record_list, &total);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_list_get_count failed");
+        }
+
+        list = new int[total];
+        LOGD("total [%u]", total);
+        for (int i = 0; i < total; i++) {
+            ret = contacts_list_get_current_record_p(record_list, &record);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_list_get_current_record_p failed");
+            }
+
+            if (record == NULL) {
+                ret = contacts_list_next(record_list);
+                if (ret !=CONTACTS_ERROR_NONE && ret != CONTACTS_ERROR_NO_DATA) {
+                    LOGE("%d", ret);
+                    CallHistoryUtil::throwCallHistoryException(ret,
+                        "contacts_list_get_next failed");
+                }
+                continue;
+            }
+
+            if (ret == CONTACTS_ERROR_NONE) {
+                ret = contacts_record_get_int(record, _contacts_phone_log.id,
+                    &value);
+                if (ret != CONTACTS_ERROR_NONE) {
+                    LOGE("%d", ret);
+                    CallHistoryUtil::throwCallHistoryException(ret,
+                        "contacts_record_get_int failed");
+                }
+                list[cnt] = value;
+                cnt++;
+            }
+            value = 0;
+            ret = contacts_list_next(record_list);
+            if (ret !=CONTACTS_ERROR_NONE && ret != CONTACTS_ERROR_NO_DATA) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_list_get_next failed");
+            }
+        }
+
+        LOGD("cnt [%u]", cnt);
+        if (cnt > 0) {
+            ret = contacts_db_delete_records(_contacts_phone_log._uri, list, cnt);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_db_delete_records failed");
+            }
+        }
+
+        ret = contacts_list_destroy(record_list, true);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_list_destroy failed");
+        }
+
+        if (list != NULL) {
+            delete[] list;
+            list = NULL;
+        }
+
+        ret = contacts_disconnect_on_thread();
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_disconnect_on_thread failed");
+        }
+
+        LOGD("Success to disconnect Call History DB for thread");
+    } catch (const BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        callback->setError(e.getName(), e.getMessage());
+    }
+
+    if (!g_idle_add(CallHistory::removeAllJobCompleteCB, data)) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+
+}
+void CallHistory::find(CallHistoryEntryArraySuccessCallback* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("callback is null");
+        return;
+    }
+
+    // to get phone number from sim index, phone number loading need to be done.
+    if (m_phoneNumbers.size() == 0) {
+        loadPhoneNumbers(callback);
+    } else {
+        std::thread(findWorkerThread, callback).detach();
+    }
+}
+
+bool CallHistory::remove(CallHistoryEntryPtr entry)
+{
+    std::string uId = entry->getUid();
+    int uIDInt = atoi(uId.c_str());
+
+    LOGD("uId = %s", uId.c_str());
+
+    int ret = contacts_db_delete_record(_contacts_phone_log._uri, (int)uIDInt);
+
+    if (ret == CONTACTS_ERROR_NONE) {
+        LOGD("1 calllog remove success");
+        return true;
+    } else {
+        LOGE("%d: %s", ret,
+            CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        return false;
+    }
+
+}
+
+gboolean CallHistory::removeBatchJobCompleteCB(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<CallHistoryEntryRemoveCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else{
+            if (callback->getSuccessCBIsSet()) {
+                callback->callSuccessCallback();
+            }
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("Uknown error occurred");
+    }
+
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+void* CallHistory::removeBatchThread(void *data)
+{
+    LOGD("Entered");
+    auto callback = static_cast<CallHistoryEntryRemoveCallback*>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return NULL;
+    }
+    try{
+        const std::vector<CallHistoryEntryPtr>& entry_list =
+            callback->getCallhistoryEntryList();
+        unsigned int entry_list_size = entry_list.size();
+        LOGD("enter : size %d", entry_list_size );
+        int list[entry_list_size];
+        memset(list, 0, entry_list_size*sizeof(int));
+        for (unsigned int i = 0; i < entry_list_size; ++i) {
+            list[i] = atoi(entry_list[i]->getUid().c_str());
+        }
+        callback->setCallHistoryIsSet(true);
+        int ret = contacts_db_delete_records(_contacts_phone_log._uri, list,
+            entry_list_size);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_cb_delete_records failed");
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+    }
+    catch (...) {
+        LOGE("removeBatchThread fails");
+        callback->setError("UnknownError", "removeBatchThread fails");
+    }
+
+    guint id = g_idle_add(removeBatchJobCompleteCB, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+        callback = NULL;
+    }
+    return NULL;
+}
+
+void CallHistory::removeBatch(CallHistoryEntryRemoveCallback* callback)
+{
+    LOGD("Entered");
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, removeBatchThread,
+                static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+gboolean CallHistory::removeAllJobCompleteCB(void *data)
+{
+    CallHistoryEntryRemoveCallback* callback =
+        static_cast<CallHistoryEntryRemoveCallback*>(data);
+    callback->callSuccessCallback();
+
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+void CallHistory::removeAll(CallHistoryEntryRemoveCallback* callback)
+{
+    LOGD("Entered");
+    if (callback == NULL) {
+        LOGD("Callback is null");
+        return;
+    }
+
+    pthread_t thread;
+    if (!pthread_create(&thread, NULL, removeAllWorkerThread, callback)) {
+        if (!pthread_detach(thread)) {
+            LOGD("Detach error");
+            return;
+        }
+    } else {
+        LOGD("Pthread create error");
+        return;
+    }
+}
+
+void CallHistory::changeListenerCB(const char* view_uri, char *changes,
+    void* user_data)
+{
+    LOGD("Entered");
+
+    if (NULL == changes) {
+        LOGW("changes is NULL");
+        return;
+    }
+    if (0 == strlen(changes)) {
+        LOGW("changes is empty");
+        return;
+    }
+    if (NULL == user_data) {
+        LOGW("ContactManager pointer is NULL in user_data");
+        return;
+    }
+
+
+    CallHistory* mgr = static_cast<CallHistory*>(user_data);
+
+    char seps[] = ",:";
+    char* tokenType = NULL;
+    char* tokenId = NULL;
+    int changeType = 0;
+    int changeId = 0;
+
+    std::vector<CallHistoryEntryPtr> addEntryList;
+    std::vector<CallHistoryEntryPtr> changedEntryList;
+    std::vector<string> removedEntryList;
+
+    tokenType = strtok( changes, seps );
+    while( tokenType != NULL )
+    {
+        tokenId = strtok( NULL, seps );
+
+        changeType = atoi((const char*)tokenType);
+
+        if (tokenId != NULL) {
+            changeId = atoi((const char*)tokenId);
+        }
+        else {
+            LOGD("There is no (more) changed Item : %s", tokenId );
+            break;
+        }
+
+        contacts_query_h query = NULL;
+        contacts_filter_h filter = NULL;
+        contacts_list_h recordList = NULL;
+        int ret = CONTACTS_ERROR_NONE;
+
+        try {
+            ret = contacts_query_create(_contacts_phone_log._uri, &query);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_query_create failed");
+            }
+            ret = contacts_filter_create(_contacts_phone_log._uri, &filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_filter_create failed");
+            }
+            ret = contacts_filter_add_int(filter, _contacts_phone_log.id,
+                CONTACTS_MATCH_EQUAL, changeId  );
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_filter_add_int failed");
+            }
+            ret = contacts_query_set_filter(query, filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_query_set_filter failed");
+            }
+            ret = contacts_query_set_sort(query, _contacts_phone_log.id, false);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_query_set_sort failed");
+            }
+            ret = contacts_db_get_records_with_query(query, 0, 1, &recordList);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_db_get_records_with_query failed");
+            }
+
+            if (changeType == CONTACTS_CHANGE_INSERTED) {
+                parseRecord(&recordList, addEntryList);
+            } else if (changeType == CONTACTS_CHANGE_UPDATED) {
+                parseRecord(&recordList, changedEntryList);
+            } else if (changeType == CONTACTS_CHANGE_DELETED) {
+                std::string recordStr(tokenId);
+                removedEntryList.push_back(recordStr);
+            }
+
+
+        } catch (BasePlatformException &e) {
+            LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+            return;
+        }
+
+        ret = contacts_list_destroy(recordList, true);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+        }
+        ret = contacts_query_destroy(query);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+        }
+        ret = contacts_filter_destroy(filter);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+        }
+        tokenType = strtok( NULL, seps );
+    }
+
+    ListenersMap listeners = mgr->m_listeners;
+    for (ListenersMap::iterator iter = listeners.begin();
+            iter != listeners.end(); iter++) {
+        if (addEntryList.size() > 0) {
+            iter->second->onadded(addEntryList);
+        }
+        if (changedEntryList.size() > 0) {
+            iter->second->onchanged(changedEntryList);
+        }
+        if (removedEntryList.size() > 0) {
+            iter->second->onremoved(removedEntryList);
+        }
+    }
+}
+
+
+long CallHistory::addChangeListener(CallHistoryChangeCallbackPtr callback)
+{
+    LOGD("Entered");
+    long listener_id = ++m_listener_counter;
+
+    if (m_listeners.empty()) {
+        int ret = contacts_db_add_changed_cb_with_info(_contacts_phone_log._uri,
+            changeListenerCB, static_cast<void*>(this));
+
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_db_add_changed_cb_with_info failed");
+        }
+    }
+    m_listeners.insert(ListenerPair(listener_id, callback));
+    return listener_id;
+}
+
+void CallHistory::removeChangeListener(JSContextRef context, long watch_id)
+{
+    LOGD("Entered");
+    ListenersMap::iterator it = m_listeners.find(watch_id);
+    JSContextRef g_ctx = NULL;
+    bool is_destructor_call = false;
+
+    if (context != NULL) {
+        g_ctx = Common::GlobalContextManager::getInstance()->
+            getGlobalContext(context);
+    } else {
+        // this is call from destructor, context will not be checked
+        is_destructor_call = true;
+    }
+
+    if (it != m_listeners.end() &&
+        (is_destructor_call || it->second->getContext() == g_ctx)) {
+
+        it->second->setActive(false);
+        m_listeners.erase(it);
+
+        if (m_listeners.empty()) {
+            int ret = contacts_db_remove_changed_cb_with_info(
+                _contacts_phone_log._uri, changeListenerCB,
+                static_cast<void*>(this));
+
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d", ret);
+                CallHistoryUtil::throwCallHistoryException(ret,
+                    "contacts_db_remove_changed_cb_with_info failed");
+            }
+        }
+    }
+    else {
+        LOGE("No listener with id: %d was found for this context.", watch_id);
+        throw NotFoundException(
+            "No listener with such id was found for this context.");
+    }
+}
+
+int CallHistory::updateValidPersonId(char* phoneNum)
+{
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+    contacts_list_h recordList = NULL;
+    int ret = CONTACTS_ERROR_NONE;
+    int validPersonId = 0;
+
+    try {
+        ret = contacts_query_create(_contacts_person_phone_log._uri, &query);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_query_create failed");
+        }
+        ret = contacts_filter_create(_contacts_person_phone_log._uri, &filter);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_filter_create failed");
+        }
+        ret = contacts_filter_add_str(filter, _contacts_person_phone_log.address,
+            CONTACTS_MATCH_EXACTLY, phoneNum);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_filter_add_str failed");
+        }
+        ret = contacts_query_set_filter(query, filter);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_query_set_filter failed");
+        }
+        ret = contacts_db_get_records_with_query(query, 0, 1, &recordList);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_db_get_records_with_query failed");
+        }
+
+        contacts_record_h record = NULL;
+
+        ret = contacts_list_get_current_record_p(recordList, &record);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_list_get_current_record_p failed");
+        }
+        ret = contacts_record_get_int(record,
+            _contacts_person_phone_log.person_id, &validPersonId);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_record_get_int failed");
+        }
+
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        validPersonId = 0;
+    }
+
+    ret = contacts_list_destroy(recordList, true);
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("%d", ret);
+    }
+    ret = contacts_query_destroy(query);
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("%d", ret);
+    }
+    ret = contacts_filter_destroy(filter);
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("%d", ret);
+    }
+
+    return validPersonId;
+
+}
+
+
+
+bool CallHistory::parseRecord(contacts_list_h *recordList,
+    std::vector<CallHistoryEntryPtr>& callhistoryEntries)
+{
+    int ret = CONTACTS_ERROR_NONE;
+    int total = 0;
+    contacts_record_h record = NULL;
+    callhistory_query_s query_data;
+    int logType = 0;
+    int time = 0;
+
+    ContactMapT contactTable;
+
+    ret = contacts_list_get_count(*recordList, &total);
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("%d", ret);
+        CallHistoryUtil::throwCallHistoryException(ret,
+            "contacts_list_get_count failed");
+    }
+
+    for (int i = 0; i < total; i++) {
+        ret = contacts_list_get_current_record_p(*recordList, &record);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+
+        if (!record) {
+            ret = contacts_list_next(*recordList);
+            if (ret != CONTACTS_ERROR_NONE && ret != CONTACTS_ERROR_NO_DATA) {
+                LOGD("callhistory parse error [%d] : %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+                return false;
+            } else {
+                continue;
+            }
+        }
+
+        memset(&query_data, 0x00, sizeof(callhistory_query_s));
+        if (ret == CONTACTS_ERROR_NONE) {
+            int ret = CONTACTS_ERROR_NONE;
+            ret = contacts_record_get_int(record, _contacts_phone_log.id,
+                &(query_data.calllog_db_id));
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("failed to get contacts phone log id %d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_record_get_int(record, _contacts_phone_log.log_type,
+                &logType);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("failed to get contacts phone log type %d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_record_get_int(record, _contacts_phone_log.person_id,
+                &(query_data.person_db_id));
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("failed to get contacts phone log person id %d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_record_get_str_p(record, _contacts_phone_log.address,
+                &(query_data.phone_number));
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("failed to get contacts phone log address %d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+
+            int id = contactTable[query_data.phone_number];
+            if (id != 0) {
+                query_data.person_db_id = id;
+            } else {
+                int updateId = updateValidPersonId(query_data.phone_number);
+                contactTable[query_data.phone_number] = updateId;
+                query_data.person_db_id = updateId;
+            }
+
+            ret = contacts_record_get_int(record, _contacts_phone_log.log_time,
+                &time);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("failed to get contacts phone log time %d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_record_get_int(record, _contacts_phone_log.extra_data1,
+                &(query_data.duration_sec));
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("failed to get contacts phone log extra data %d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_record_get_str(record, _contacts_phone_log.extra_data2,
+                &(query_data.ecc));
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("failed to get contacts phone log extra data 2 %d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_record_get_int(record, _contacts_phone_log.sim_slot_no,
+                &(query_data.sim_slot_no));
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("failed to get sim slot no %d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+
+            query_data.calllog_type =
+                static_cast<contacts_phone_log_type_e>(logType);
+            query_data.timestamp = static_cast<time_t>(time);
+            addCallEntry(&query_data, callhistoryEntries);
+        }
+
+        ret = contacts_list_next(*recordList);
+        if (ret != CONTACTS_ERROR_NONE && ret != CONTACTS_ERROR_NO_DATA) {
+            LOGD("callhistory parse error %d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            contactTable.clear();
+            return false;
+        }
+    }
+
+    contactTable.clear();
+    return true;
+
+}
+
+
+bool CallHistory::addCallEntry(callhistory_query_s *query_log,
+    std::vector<CallHistoryEntryPtr>& callEntries)
+{
+    LOGD("Enter");
+
+    if (query_log == NULL)
+        return false;
+
+    CallHistoryEntry* callEntry = new CallHistoryEntry();
+    RemoteParty* remoteParty = new RemoteParty();
+    std::vector<RemotePartyPtr> remoteParties;
+
+    std::string feature("");
+    std::vector<std::string> features;
+
+    std::string type("");
+    std::string direction("");
+    std::string number("");
+
+    if (query_log->phone_number != NULL) {
+        number.append(query_log->phone_number);
+    }
+
+    switch(query_log->calllog_type) {
+        case CONTACTS_PLOG_TYPE_VOICE_INCOMMING:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VOICE);
+            direction.append(STR_DIRECTION_RECEIVED);
+            break;
+        case CONTACTS_PLOG_TYPE_VOICE_OUTGOING:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VOICE);
+            direction.append(STR_DIRECTION_DIALED);
+            break;
+        case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VOICE);
+            direction.append(STR_DIRECTION_MISSED);
+            break;
+        case CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VOICE);
+            direction.append(STR_DIRECTION_MISSED_NEW);
+            break;
+        case CONTACTS_PLOG_TYPE_VOICE_REJECT:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VOICE);
+            direction.append(STR_DIRECTION_REJECTED);
+            break;
+        case CONTACTS_PLOG_TYPE_VOICE_BLOCKED:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VOICE);
+            direction.append(STR_DIRECTION_BLOCKED);
+            break;
+        case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VIDEO);
+            direction.append(STR_DIRECTION_RECEIVED);
+            break;
+        case CONTACTS_PLOG_TYPE_VIDEO_OUTGOING:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VIDEO);
+            direction.append(STR_DIRECTION_DIALED);
+            break;
+        case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VIDEO);
+            direction.append(STR_DIRECTION_MISSED);
+            break;
+        case CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VIDEO);
+            direction.append(STR_DIRECTION_MISSED_NEW);
+            break;
+        case CONTACTS_PLOG_TYPE_VIDEO_REJECT:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VIDEO);
+            direction.append(STR_DIRECTION_REJECTED);
+            break;
+        case CONTACTS_PLOG_TYPE_VIDEO_BLOCKED:
+            type.append(STR_CALLTYPE_TEL);
+            feature.append(STR_FEATURE_VIDEO);
+            direction.append(STR_DIRECTION_BLOCKED);
+            break;
+        default:
+            if (callEntry) delete callEntry;
+            if (remoteParty) delete remoteParty;
+            return false;
+    }
+
+    // uid
+    std::stringstream uidStream;
+    uidStream << query_log->calllog_db_id;
+    callEntry->setUid(uidStream.str());
+
+    if ((query_log->ecc !=NULL) && (!strcmp(query_log->ecc,"001"))) {
+        feature.append(STR_CALL_EMERGENCY);
+    }
+
+    callEntry->setType(type);
+
+    // Feature
+    features.push_back(feature);
+    callEntry->setFeatures(features);
+
+    // remoteParty
+    remoteParty->setRemoteParty(number);
+    std::stringstream personIdStream;
+    personIdStream << query_log->person_db_id;
+    remoteParty->setPersonId(personIdStream.str());
+
+    RemotePartyPtr remotePartyPtr(remoteParty);
+    remoteParties.push_back(remotePartyPtr);
+    callEntry->setRemoteParties(remoteParties);
+    remoteParties.clear();
+
+
+    callEntry->setStartTime(query_log->timestamp);
+    callEntry->setDuration((unsigned long)(query_log->duration_sec));
+    callEntry->setDirection(direction);
+
+    // callingParty
+    try {
+        auto *_this = CallHistory::getInstance();
+
+        int sim_index = query_log->sim_slot_no;
+        int sim_count = _this->m_phoneNumbers.size();
+
+        LOGD("%d, %d", sim_index, sim_count);
+
+        if (sim_index >= sim_count) {
+            LOGE("sim slot no. is out of count %d : %d",
+                    query_log->sim_slot_no, sim_count);
+            throw UnknownException("sim slot no. is out of count");
+        } else if (sim_index < 0) {
+            LOGD("Unknown sim : %d", sim_index);
+            callEntry->setCallingParty("");
+        } else {
+            std::string callingParty = _this->m_phoneNumbers.at(sim_index);
+            LOGD("callingParty: %s", callingParty.c_str());
+            callEntry->setCallingParty(callingParty);
+        }
+
+
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+    }
+
+    CallHistoryEntryPtr callHistoryPtr(callEntry);
+    callEntries.push_back(callHistoryPtr);
+
+    return true;
+}
+
+
+unsigned int CallHistory::convertAttrName(const std::string &name)
+{
+    if (name.compare(STR_RP_REMOTEPARTY) == 0) {
+        return _contacts_phone_log.address;
+    } else if (name.compare(STR_START_TIME) == 0) {
+        return _contacts_phone_log.log_time;
+    } else if (name.compare(STR_DURATION) == 0) {
+        return _contacts_phone_log.extra_data1;
+    } else if (name.compare(STR_DIRECTION) == 0) {
+        return _contacts_phone_log.log_type;
+    } else if (name.compare(STR_ENTRY_ID) == 0) {
+        return _contacts_phone_log.id;
+    } else {
+        return 0;
+    }
+}
+
+void CallHistory::loadPhoneNumbers(OperationCallback *operationCallback)
+{
+    LOGD("Enter");
+
+    std::thread([](std::vector<std::string> &numbers,
+                OperationCallback *operationCallback) {
+        try {
+            char **cp_list = NULL;
+            cp_list = tel_get_cp_name_list();
+            if (!cp_list) {
+                LOGE("Failed to get cp name list.");
+                throw UnknownException("Failed to get cp name list.");
+            }
+
+            unsigned int modem_num = 0;
+            while (cp_list[modem_num]) {
+                std::string n = "";
+                TapiHandle* handle;
+                do {
+                    LOGD("sim[%d] : %s", modem_num, cp_list[modem_num]);
+
+                    std::promise<std::string> prom;
+                    handle = tel_init(cp_list[modem_num]);
+                    if (!handle) {
+                        LOGE("Failed to init tapi handle.");
+                        break;
+                    }
+
+                    int card_changed;
+                    TelSimCardStatus_t card_status;
+                    int ret = tel_get_sim_init_info(handle, &card_status,
+                            &card_changed);
+                    if (ret != TAPI_API_SUCCESS) {
+                        LOGE("Failed to get sim init info: %d, ret");
+                        break;
+                    }
+                    LOGD("Card status: %d, Card Changed: %d", card_status,
+                            card_changed);
+                    if (card_status != TAPI_SIM_STATUS_SIM_INIT_COMPLETED) {
+                        LOGW("SIM is not ready, we can't get other properties");
+                        break;
+                    }
+
+                    ret = tel_get_sim_msisdn(handle, get_sim_msisdn_cb, &prom);
+                    if (ret != TAPI_API_SUCCESS) {
+                        LOGE("Failed to get msisdn : %d", ret);
+                        break;
+                    }
+
+                    auto fut = prom.get_future();
+                    LOGD("wait ...");
+                    fut.wait();
+                    n = fut.get();
+                    LOGD("Phone number[%d] : %s", modem_num, n.c_str());
+                } while(false);
+
+                numbers.push_back(n);
+                tel_deinit(handle);
+                modem_num++;
+            }
+            g_strfreev(cp_list);
+        } catch (BasePlatformException &err) {
+            operationCallback->setError(err.getName(), err.getMessage());
+        } catch (...) {
+            operationCallback->setError(
+               JSWebAPIErrorFactory::UNKNOWN_ERROR, "UnknownError");
+        }
+
+        CallHistoryEntryArraySuccessCallback *cb =
+            dynamic_cast<CallHistoryEntryArraySuccessCallback *>(operationCallback);
+        if (cb != NULL) {
+            findWorkerThread(cb);
+        }
+    }, std::ref(m_phoneNumbers), operationCallback).detach();
+}
+
+} // Callhistory
+} // DeviceAPI
diff --git a/src/Callhistory/CallHistory.h b/src/Callhistory/CallHistory.h
new file mode 100755 (executable)
index 0000000..acf1344
--- /dev/null
@@ -0,0 +1,93 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CALL_HISTORY_H__
+#define __TIZEN_CALL_HISTORY_H__
+
+#include <string>
+#include <vector>
+#include <sstream>
+#include <contacts.h>
+#include <contacts_internal.h>
+#include <stack>
+#include <Security.h>
+#include <AbstractFilter.h>
+#include <glib.h>
+#include "time.h"
+#include "CallHistoryEntryArraySuccessCallback.h"
+#include "CallHistoryEntry.h"
+#include "CallHistoryChangeCallback.h"
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+typedef struct
+{
+    int calllog_db_id;
+    contacts_phone_log_type_e calllog_type;
+    int person_db_id;
+    char* phone_number;
+    time_t timestamp;
+    int duration_sec;
+    char * ecc;
+    int sim_slot_no;
+} callhistory_query_s;
+
+class CallHistory: public DeviceAPI::Common::SecurityAccessor
+{
+public:
+    static CallHistory* getInstance();
+
+    void find(CallHistoryEntryArraySuccessCallback* callhistoryEntryCallback);
+
+    bool remove(CallHistoryEntryPtr entry);
+    void removeBatch(CallHistoryEntryRemoveCallback* callback);
+    void removeAll(CallHistoryEntryRemoveCallback* callback);
+    long addChangeListener(CallHistoryChangeCallbackPtr callback);
+    void removeChangeListener(JSContextRef context, long watch_id);
+
+    static gboolean removeBatchJobCompleteCB(void *data);
+    static gboolean removeAllJobCompleteCB(void *data);
+
+    static unsigned int convertAttrName(const std::string &name);
+    static int updateValidPersonId(char* phoneNum);
+    static bool parseRecord(contacts_list_h *recordList,
+            std::vector<CallHistoryEntryPtr>& callhistoryEntries);
+    static bool addCallEntry(callhistory_query_s *query_log,
+            std::vector<CallHistoryEntryPtr>& callEntries);
+private:
+    CallHistory();
+    virtual ~CallHistory();
+
+    static void* removeBatchThread(void *data);
+    static void changeListenerCB(const char* view_uri, char *changes, void* user_data);
+
+    typedef std::pair<long, CallHistoryChangeCallbackPtr> ListenerPair;
+    typedef std::map<long, CallHistoryChangeCallbackPtr> ListenersMap;
+    ListenersMap m_listeners;
+    long m_listener_counter;
+
+    std::vector<std::string> m_phoneNumbers;
+    void loadPhoneNumbers(OperationCallback *operationCallback);
+};
+
+typedef std::map<std::string, int> ContactMapT;
+
+} // Callhistory
+} // DeviceAPI
+
+#endif // __TIZEN_CALL_HISTORY_H__
diff --git a/src/Callhistory/CallHistoryChangeCallback.cpp b/src/Callhistory/CallHistoryChangeCallback.cpp
new file mode 100755 (executable)
index 0000000..1a83db7
--- /dev/null
@@ -0,0 +1,192 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/JSUtils.h>
+#include <JSWebAPIError.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+#include "CallHistoryEntry.h"
+#include "CallHistoryChangeCallback.h"
+#include "GlobalContextManager.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+CallHistoryChangeCallback::CallHistoryChangeCallback(JSContextRef globalCtx,
+    JSObjectRef object): m_is_active(true)
+{
+    LOGD("Entered");
+    m_callback = MultiCallbackUserDataPtr(new MultiCallbackUserData(globalCtx));
+
+    // onadded
+    JSValueRef onadded_ref =
+        JSUtil::getProperty(globalCtx, object, "onadded");
+    if (JSValueIsUndefined(globalCtx, onadded_ref)) {
+        onadded_ref = NULL;
+    } else {
+        JSObjectRef cb_obj = JSValueToObject(globalCtx, onadded_ref, NULL);
+        if (JSObjectIsFunction(globalCtx, cb_obj)) {
+            m_callback->setCallback("onadded", cb_obj);
+        } else {
+            throw TypeMismatchException("onadded is not a callback function.");
+        }
+    }
+
+    // onchanged
+    JSValueRef onchanged_ref =
+        JSUtil::getProperty(globalCtx, object, "onchanged");
+    if (JSValueIsUndefined(globalCtx, onchanged_ref)) {
+        onchanged_ref = NULL;
+    } else {
+        JSObjectRef cb_obj = JSValueToObject(globalCtx, onchanged_ref, NULL);
+        if (JSObjectIsFunction(globalCtx, cb_obj)) {
+            m_callback->setCallback("onchanged", cb_obj);
+        } else {
+            throw TypeMismatchException("onchanged is not a callback function.");
+        }
+    }
+
+
+    // onremoved
+    JSValueRef onremoved_ref =
+        JSUtil::getProperty(globalCtx, object, "onremoved");
+    if (JSValueIsUndefined(globalCtx, onremoved_ref)) {
+        onremoved_ref = NULL;
+    } else {
+        JSObjectRef cb_obj = JSValueToObject(globalCtx, onremoved_ref, NULL);
+        if (JSObjectIsFunction(globalCtx, cb_obj)) {
+            m_callback->setCallback("onremoved", cb_obj);
+        } else {
+            throw TypeMismatchException("onchanged is not a callback function.");
+        }
+    }
+}
+
+CallHistoryChangeCallback::~CallHistoryChangeCallback()
+{
+}
+
+CallHistoryChangeCallback::CallHistoryChangeCallback(
+    const CallHistoryChangeCallback& callback)
+{
+}
+
+CallHistoryChangeCallback& CallHistoryChangeCallback::operator =(
+    const CallHistoryChangeCallback& callback)
+{
+    return *this;
+}
+
+void CallHistoryChangeCallback::onadded(
+    const std::vector<CallHistoryEntryPtr>& new_items)
+{
+    LOGD("Entered");
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef context = m_callback->getContext();
+
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    JSObjectRef js_result = JSCreateArrayObject(context, 0, NULL);
+    if (js_result == NULL) {
+        LOGE("JSCreateArrayObject failed");
+        throw UnknownException("JSCreateArrayObject failed");
+    }
+
+    for (std::size_t i = 0; i < new_items.size(); ++i) {
+        JSValueRef temp_call_entry =
+            JSCallHistoryEntry::createJSObject(context, new_items[i]);
+        if (!JSSetArrayElement(context, js_result, i, temp_call_entry)) {
+            LOGE("JSSetArrayElement failed");
+            throw UnknownException("JSSetArrayElement failed");
+        }
+    }
+
+    m_callback->invokeCallback("onadded", js_result);
+
+}
+
+void CallHistoryChangeCallback::onchanged(
+    const std::vector<CallHistoryEntryPtr>& changed_items)
+{
+    LOGD("Entered");
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef context = m_callback->getContext();
+
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    JSObjectRef js_result = JSCreateArrayObject(context, 0, NULL);
+    if (js_result == NULL) {
+        LOGE("JSCreateArrayObject failed");
+        throw UnknownException("JSCreateArrayObject failed");
+    }
+
+    for (std::size_t i = 0; i < changed_items.size(); ++i) {
+        JSValueRef temp_call_entry =
+            JSCallHistoryEntry::createJSObject(context, changed_items[i]);
+        if (!JSSetArrayElement(context, js_result, i, temp_call_entry)) {
+            LOGE("JSSetArrayElement failed");
+            throw UnknownException("JSSetArrayElement failed");
+        }
+    }
+
+    m_callback->invokeCallback("onchanged", js_result );
+}
+
+void CallHistoryChangeCallback::onremoved(
+    const std::vector<string>& removed_items)
+{
+    LOGD("Entered");
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef context = m_callback->getContext();
+
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    m_callback->invokeCallback("onremoved",
+        JSUtil::toJSValueRef(context, removed_items));
+}
+
+void CallHistoryChangeCallback::setActive(bool act)
+{
+    m_is_active = act;
+}
+
+JSContextRef CallHistoryChangeCallback::getContext() const
+{
+    return m_callback->getContext();
+}
+
+} // Callhistory
+} // DeviceAPI
diff --git a/src/Callhistory/CallHistoryChangeCallback.h b/src/Callhistory/CallHistoryChangeCallback.h
new file mode 100755 (executable)
index 0000000..9a6f429
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CALL_HISTORY_CHANGE_CALLBACK_H__
+#define __TIZEN_CALL_HISTORY_CHANGE_CALLBACK_H__
+
+#include <string>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+
+#include "CallHistoryEntry.h"
+#include "JSCallHistoryEntry.h"
+
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+class CallHistoryChangeCallback;
+typedef std::shared_ptr<CallHistoryChangeCallback> CallHistoryChangeCallbackPtr;
+
+class CallHistoryChangeCallback
+{
+public:
+    CallHistoryChangeCallback(JSContextRef globalCtx, JSObjectRef object);
+    virtual ~CallHistoryChangeCallback();
+
+    void onremoved(const std::vector<string>& removed_items);
+    void onchanged(const std::vector<CallHistoryEntryPtr>& changed_items);
+    void onadded(const std::vector<CallHistoryEntryPtr>& new_items);
+
+    void setActive(bool act);
+    JSContextRef getContext() const;
+
+private:
+    CallHistoryChangeCallback(const CallHistoryChangeCallback& callback);
+    CallHistoryChangeCallback& operator =(const CallHistoryChangeCallback& callback);
+
+    MultiCallbackUserDataPtr m_callback;
+    bool m_is_active;
+};
+
+} // Callhistory
+} // DeviceAPI
+
+
+
+#endif // __TIZEN_CALL_HISTORY_CHANGE_CALLBACK_H__
diff --git a/src/Callhistory/CallHistoryEntry.cpp b/src/Callhistory/CallHistoryEntry.cpp
new file mode 100755 (executable)
index 0000000..5cfbd47
--- /dev/null
@@ -0,0 +1,191 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CallHistoryEntry.h"
+#include "CallHistoryUtil.h"
+#include "RemoteParty.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <sstream>
+#include <contacts.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+CallHistoryEntry::CallHistoryEntry():
+    m_uid(""),
+    m_type(""),
+    m_duration(0),
+    m_direction(""),
+    m_callingParty("")
+{
+}
+
+CallHistoryEntry::~CallHistoryEntry()
+{
+}
+
+std::string CallHistoryEntry::getUid() const
+{
+    return m_uid;
+}
+
+void CallHistoryEntry::setUid(std::string uid)
+{
+    m_uid = uid;
+}
+
+std::string CallHistoryEntry::getType() const
+{
+    return m_type;
+}
+
+void CallHistoryEntry::setType(std::string type)
+{
+    m_type = type;
+}
+
+std::vector<std::string> CallHistoryEntry::getFeatures() const
+{
+    return m_features;
+}
+
+void CallHistoryEntry::setFeatures(std::vector<std::string> features)
+{
+    m_features = features;
+}
+
+std::vector<RemotePartyPtr> CallHistoryEntry::getRemoteParties()
+{
+    return m_remoteParties;
+}
+
+void CallHistoryEntry::setRemoteParties(std::vector<RemotePartyPtr> remoteParties)
+{
+    m_remoteParties = remoteParties;
+}
+
+time_t CallHistoryEntry::getStartTime() const
+{
+    return m_startTime;
+}
+
+void CallHistoryEntry::setStartTime(time_t startTime)
+{
+    m_startTime = startTime;
+}
+
+unsigned long CallHistoryEntry::getDuration() const
+{
+    return m_duration;
+}
+
+void CallHistoryEntry::setDuration(unsigned long duration)
+{
+    m_duration = duration;
+}
+
+std::string CallHistoryEntry::getDirection() const
+{
+    return m_direction;
+}
+
+void CallHistoryEntry::setDirection(std::string direction)
+{
+    m_direction = direction;
+}
+
+std::string CallHistoryEntry::getCallingParty() const
+{
+    return m_callingParty;
+}
+
+void CallHistoryEntry::setCallingParty(std::string callingParty)
+{
+    m_callingParty = callingParty;
+}
+
+void CallHistoryEntry::setMissedDirection(std::string id)
+{
+    LOGD("Entered");
+    int idInt = atoi(id.c_str());
+
+    contacts_record_h record = NULL;
+    int ret = -1;
+    int logType = 0;
+
+    try {
+        ret = contacts_db_get_record(_contacts_phone_log._uri, (int)idInt,
+            &record);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_db_get_record failed");
+        }
+        ret = contacts_record_get_int(record, _contacts_phone_log.log_type,
+            &logType);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_record_get_int failed");
+        }
+
+        if (logType == CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN ) {
+            ret = contacts_record_set_int (record, _contacts_phone_log.log_type,
+                CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN);
+        } else if (logType == CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN ) {
+            ret = contacts_record_set_int (record, _contacts_phone_log.log_type,
+                CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN);
+        } else {
+            LOGE("Contact Type Mismatch");
+            throw TypeMismatchException("Contact Type Mismatch");
+        }
+
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_record_set_int failed");
+        }
+
+        ret = contacts_db_update_record(record);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+            CallHistoryUtil::throwCallHistoryException(ret,
+                "contacts_record_get_int failed");
+        }
+
+        ret = contacts_record_destroy(record, true);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d, %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+    } catch (BasePlatformException &e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        ret = contacts_record_destroy(record, true);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d", ret);
+        }
+        throw e;
+    }
+
+}
+
+} // Callhistory
+} // DeviceAPI
diff --git a/src/Callhistory/CallHistoryEntry.h b/src/Callhistory/CallHistoryEntry.h
new file mode 100755 (executable)
index 0000000..91d6259
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CALL_HISTORY_ENTRY_H__
+#define __TIZEN_CALL_HISTORY_ENTRY_H__
+
+#include <string>
+#include <vector>
+#include <memory>
+#include "CallHistoryTypes.h"
+#include "RemoteParty.h"
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+using namespace std;
+
+class CallHistoryEntry
+{
+public:
+    CallHistoryEntry();
+    virtual ~CallHistoryEntry();
+
+    std::string getUid() const;
+    void setUid(std::string uid);
+
+    std::string getType() const;
+    void setType(std::string type);
+
+    std::vector<std::string> getFeatures() const;
+    void setFeatures(std::vector<std::string> features);
+
+    std::vector<RemotePartyPtr> getRemoteParties();
+    void setRemoteParties(std::vector<RemotePartyPtr> remoteParties);
+
+    time_t getStartTime() const;
+    void setStartTime(time_t startTime);
+
+    unsigned long getDuration() const;
+    void setDuration(unsigned long duration);
+
+    std::string getDirection() const;
+    void setDirection(std::string direction);
+
+    std::string getCallingParty() const;
+    void setCallingParty(std::string callingParty);
+
+    static void setMissedDirection(std::string id);
+
+
+private:
+    std::string m_uid;
+    std::string m_type; // TEL, XMPP, SIP
+    std::vector<std::string> m_features; // CALL, VOICECALL, VIDEOCALL, EMERGENCYCALL
+    std::vector<RemotePartyPtr> m_remoteParties;
+    time_t m_startTime;
+    unsigned long m_duration;
+    std::string m_direction; // DIALED, RECEIVED, MISSEDNEW, MISSED, REJECTED
+    std::string m_callingParty;
+};
+
+typedef std::shared_ptr<CallHistoryEntry> CallHistoryEntryPtr;
+
+} // Callhistory
+} // DeviceAPI
+
+#endif // __TIZEN_CALL_HISTORY_ENTRY_H__
diff --git a/src/Callhistory/CallHistoryEntryArraySuccessCallback.cpp b/src/Callhistory/CallHistoryEntryArraySuccessCallback.cpp
new file mode 100755 (executable)
index 0000000..e6f0bc9
--- /dev/null
@@ -0,0 +1,229 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/JSUtils.h>
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+#include "CallHistoryEntryArraySuccessCallback.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+OperationCallback::OperationCallback(JSContextRef globalCtx)
+    : CallbackUserData(globalCtx),
+      m_is_error(false)
+{
+}
+
+OperationCallback::~OperationCallback()
+{
+}
+
+void OperationCallback::setError(const std::string &err_name,
+        const std::string &err_message)
+{
+    m_err_name = err_name;
+    m_err_message = err_message;
+    m_is_error = true;
+}
+
+bool OperationCallback::isError() const
+{
+    return m_is_error;
+}
+
+const std::string& OperationCallback::getErrorName() const
+{
+    return m_err_name;
+}
+
+const std::string& OperationCallback::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+CallHistoryEntryArraySuccessCallback::CallHistoryEntryArraySuccessCallback(
+    JSContextRef globalCtx)
+    : OperationCallback(globalCtx),
+      m_filterIsSet(false),
+      m_sortModesIsSet(false),
+      m_limitIsSet(false),
+      m_offsetIsSet(false)
+{
+}
+
+
+CallHistoryEntryArraySuccessCallback::~CallHistoryEntryArraySuccessCallback()
+{
+    if (m_callhistoryEntries.size() > 0) {
+        m_callhistoryEntries.clear();
+    }
+
+}
+
+void CallHistoryEntryArraySuccessCallback::setFilter(
+    const AbstractFilterPtr &filter)
+{
+    m_filter = filter;
+    m_filterIsSet = true;
+}
+
+
+void CallHistoryEntryArraySuccessCallback::setSortMode(
+    const SortModePtr &sortMode)
+{
+    m_sortModes = sortMode;
+    m_sortModesIsSet = true;
+}
+
+void CallHistoryEntryArraySuccessCallback::setLimit(const unsigned long limit)
+{
+    if (limit > 0) {
+        m_limit = limit;
+        m_limitIsSet = true;
+    }
+}
+
+void CallHistoryEntryArraySuccessCallback::setOffset(const unsigned long offset)
+{
+    if (offset > 0) {
+        m_offset = offset;
+        m_offsetIsSet = true;
+    }
+}
+
+void CallHistoryEntryArraySuccessCallback::setCallhistoryEntries(
+    std::vector<CallHistoryEntryPtr> callhistoryEntries)
+{
+    if (callhistoryEntries.size() > 0)
+    {
+        m_callhistoryEntries = callhistoryEntries;
+    }
+}
+
+std::vector<CallHistoryEntryPtr>
+CallHistoryEntryArraySuccessCallback::getCallhistoryEntries() const
+{
+    return m_callhistoryEntries;
+}
+
+
+bool CallHistoryEntryArraySuccessCallback::getFilterIsSet() const
+{
+    return m_filterIsSet;
+}
+
+bool CallHistoryEntryArraySuccessCallback::getSortModesIsSet() const
+{
+    return m_sortModesIsSet;
+}
+
+bool CallHistoryEntryArraySuccessCallback::getLimitIsSet() const
+{
+    return m_limitIsSet;
+}
+
+bool CallHistoryEntryArraySuccessCallback::getOffsetIsSet() const
+{
+    return m_offsetIsSet;
+}
+
+AbstractFilterPtr CallHistoryEntryArraySuccessCallback::getFilter() const
+{
+    return m_filter;
+}
+
+SortModePtr CallHistoryEntryArraySuccessCallback::getSortMode() const
+{
+    return m_sortModes;
+}
+
+unsigned long CallHistoryEntryArraySuccessCallback::getLimit() const
+{
+    return m_limit;
+}
+
+unsigned long CallHistoryEntryArraySuccessCallback::getOffset() const
+{
+    return m_offset;
+}
+
+CallHistoryEntryRemoveCallback::CallHistoryEntryRemoveCallback(
+    JSContextRef globalCtx)
+     : OperationCallback(globalCtx),
+       m_successCBIsSet(false),
+       m_callHistoryIsSet(false)
+{
+}
+
+CallHistoryEntryRemoveCallback::~CallHistoryEntryRemoveCallback()
+{
+    if (m_callhistoryEntryList.size() > 0)
+    {
+        m_callhistoryEntryList.clear();
+    }
+}
+
+void CallHistoryEntryRemoveCallback::setCallhistoryEntryList(
+    std::vector<CallHistoryEntryPtr> callhistoryEntryList)
+{
+    if (callhistoryEntryList.size() > 0) {
+        m_callhistoryEntryList = callhistoryEntryList;
+    }
+    else{
+        LOGE("CallHistory list is empty");
+        throw TypeMismatchException("CallHistory list is empty");
+    }
+}
+
+const std::vector<CallHistoryEntryPtr>&
+CallHistoryEntryRemoveCallback::getCallhistoryEntryList()
+{
+    return m_callhistoryEntryList;
+}
+
+void CallHistoryEntryRemoveCallback::setSuccessCBIsSet(bool status)
+{
+    m_successCBIsSet = status;
+}
+
+bool CallHistoryEntryRemoveCallback::getSuccessCBIsSet()
+{
+    return m_successCBIsSet;
+}
+
+void CallHistoryEntryRemoveCallback::setCallHistoryIsSet(bool status)
+{
+    m_callHistoryIsSet = status;
+}
+
+bool CallHistoryEntryRemoveCallback::getCallHistoryIsSet()
+{
+    return m_callHistoryIsSet;
+}
+
+} // Callhistory
+} // DeviceAPI
diff --git a/src/Callhistory/CallHistoryEntryArraySuccessCallback.h b/src/Callhistory/CallHistoryEntryArraySuccessCallback.h
new file mode 100755 (executable)
index 0000000..a0856cb
--- /dev/null
@@ -0,0 +1,110 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CALL_HISTORY_ENTRY_ARRAY_SUCCESS_CALLBACK_H__
+#define __TIZEN_CALL_HISTORY_ENTRY_ARRAY_SUCCESS_CALLBACK_H__
+
+#include <string>
+#include <AbstractFilter.h>
+#include <SortMode.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <CallbackUserData.h>
+
+#include "CallHistoryEntry.h"
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+class OperationCallback: public Common::CallbackUserData
+{
+public:
+    OperationCallback(JSContextRef globalCtx);
+    virtual ~OperationCallback();
+    void setError(const std::string &err_name,
+            const std::string &err_message);
+    bool isError() const;
+    const std::string& getErrorName() const;
+    const std::string& getErrorMessage() const;
+private:
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+};
+
+class CallHistoryEntryArraySuccessCallback : public OperationCallback
+{
+public:
+    CallHistoryEntryArraySuccessCallback(JSContextRef globalCtx);
+    virtual ~CallHistoryEntryArraySuccessCallback();
+
+    void setFilter(const Tizen::AbstractFilterPtr &filter);
+    void setSortMode(const Tizen::SortModePtr &sortMode);
+    void setLimit(const unsigned long limit);
+    void setOffset(const unsigned long offset);
+    void setCallhistoryEntries(std::vector<CallHistoryEntryPtr> callhistoryEntries);
+
+    Tizen::AbstractFilterPtr getFilter() const;
+    Tizen::SortModePtr getSortMode() const;
+    unsigned long getLimit() const;
+    unsigned long getOffset() const;
+    std::vector<CallHistoryEntryPtr> getCallhistoryEntries() const;
+
+    bool getFilterIsSet() const;
+    bool getSortModesIsSet() const;
+    bool getLimitIsSet() const;
+    bool getOffsetIsSet() const;
+
+    std::vector<CallHistoryEntryPtr> m_callhistoryEntries;
+
+private:
+    Tizen::AbstractFilterPtr m_filter;
+    Tizen::SortModePtr m_sortModes;
+    unsigned long m_limit;
+    unsigned long m_offset;
+
+    bool m_filterIsSet;
+    bool m_sortModesIsSet;
+    bool m_limitIsSet;
+    bool m_offsetIsSet;
+};
+
+class CallHistoryEntryRemoveCallback : public OperationCallback
+{
+public:
+    CallHistoryEntryRemoveCallback(JSContextRef globalCtx);
+    virtual ~CallHistoryEntryRemoveCallback();
+
+    void setCallhistoryEntryList(std::vector<CallHistoryEntryPtr> callhistoryEntryList);
+    const std::vector<CallHistoryEntryPtr>& getCallhistoryEntryList();
+
+    void setSuccessCBIsSet(bool status);
+    bool getSuccessCBIsSet();
+
+    void setCallHistoryIsSet(bool status);
+    bool getCallHistoryIsSet();
+
+private:
+    std::vector<CallHistoryEntryPtr> m_callhistoryEntryList;
+    bool m_successCBIsSet;
+    bool m_callHistoryIsSet;
+};
+
+} // Callhistory
+} // DeviceAPI
+
+#endif // __TIZEN_CALL_HISTORY_ENTRY_ARRAY_SUCCESS_CALLBACK_H__
diff --git a/src/Callhistory/CallHistoryFilterQueryGenerator.cpp b/src/Callhistory/CallHistoryFilterQueryGenerator.cpp
new file mode 100755 (executable)
index 0000000..b1e713d
--- /dev/null
@@ -0,0 +1,836 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <iomanip>
+#include "CallHistoryTypes.h"
+#include "CallHistoryFilterQueryGenerator.h"
+#include "CallHistoryUtil.h"
+#include <Logger.h>
+#include <FilterIterator.h>
+
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+CallHistoryFilterQueryGenerator::CallHistoryFilterQueryGenerator(
+    contacts_filter_h filter)
+{
+    m_filter_stack.push(filter);
+}
+
+CallHistoryFilterQueryGenerator::~CallHistoryFilterQueryGenerator()
+{
+    contacts_filter_h filter = NULL;
+    int ret = 0;
+    while (m_filter_stack.size() > 1) {
+        filter = m_filter_stack.top();
+        ret = contacts_filter_destroy(filter);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+        m_filter_stack.pop();
+    }
+}
+
+contacts_filter_h CallHistoryFilterQueryGenerator::generate(
+    AbstractFilterPtr src_filter)
+{
+    LOGD("Entered");
+
+    int ret = 0;
+    if (!src_filter) {
+        LOGW("src_filter is NULL");
+    }
+    else {
+        LOGD("src_filter is %p, type:%d", src_filter.get(),
+            src_filter->getFilterType());
+    }
+
+    for(FilterIterator it(src_filter); it.isEnd() == false; ++it) {
+
+        switch(it.getState()) {
+            case FIS_COMPOSITE_START: {
+                LOGD("COMPOSITE START {");
+                contacts_filter_h filter = NULL;
+                ret = contacts_filter_create(_contacts_phone_log._uri, &filter);
+                if (ret != CONTACTS_ERROR_NONE) {
+                    LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+                }
+                if (filter != NULL) {
+                    m_filter_stack.push(filter);
+                }
+            } break;
+            case FIS_COMPOSITE_END: {
+                contacts_filter_h top_filter = m_filter_stack.top();
+                if (m_filter_stack.size() > 1) {
+                    m_filter_stack.pop();
+                    contacts_filter_h parent_filter = m_filter_stack.top();
+                    ret = contacts_filter_add_filter(parent_filter, top_filter);
+                    if (ret != CONTACTS_ERROR_NONE) {
+                        LOGE("%d: %s", ret,
+                            CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+                    }
+                    ret = contacts_filter_destroy(top_filter);
+                    if (ret != CONTACTS_ERROR_NONE) {
+                        LOGE("%d: %s", ret,
+                            CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+                    }
+                }
+                LOGD("} COMPOSITE END");
+            } break;
+            case FIS_ATTRIBUTE_FILTER:
+            case FIS_ATTRIBUTE_RANGE_FILTER: {
+
+                if (FIS_ATTRIBUTE_FILTER == it.getState()) {
+                    LOGD("ATTRIBUTE Filter");
+                    visitAttribute(castToAttributeFilter(*it));
+                }
+                else {
+                    LOGD("ATTRIBUTE RANGE Filter");
+                    visitAttributeRange(castToAttributeRangeFilter(*it));
+                }
+
+                if (it.isInsideCompositeFilter() && !it.isLastCompositeSubFilter()) {
+                    CompositeFilterPtr c_filter = it.getCurrentCompositeFilter();
+
+                    contacts_filter_h top_filter = m_filter_stack.top();
+                    if (Tizen::UNION == c_filter->getType()) {
+                        ret = contacts_filter_add_operator(top_filter,
+                            CONTACTS_FILTER_OPERATOR_OR);
+                        if (ret != CONTACTS_ERROR_NONE) {
+                            LOGE("%d: %s", ret,
+                                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+                        }
+                        LOGD("added OR operator");
+                    }
+                    else {
+                        ret = contacts_filter_add_operator(top_filter,
+                                CONTACTS_FILTER_OPERATOR_AND);
+                        if (ret != CONTACTS_ERROR_NONE) {
+                            LOGE("%d: %s", ret,
+                                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+                        }
+                        LOGD("added AND operator");
+                    }
+                }
+            } break;
+
+            default:
+                break;
+        }
+    }
+
+    return m_filter_stack.top();
+}
+
+contacts_filter_h CallHistoryFilterQueryGenerator::getResult() const
+{
+    return m_filter_stack.top();
+}
+
+void CallHistoryFilterQueryGenerator::visitAttribute(AttributeFilterPtr attr_filter)
+{
+    LOGD("Entered");
+    if (!attr_filter) {
+        LOGW("AttributeFilterPtr is NULL");
+        return;
+    }
+
+    AnyPtr match_value = attr_filter->getMatchValue();
+    if (!match_value) {
+        LOGW("match_value is NULL");
+        return;
+    }
+
+    contacts_filter_h filter = m_filter_stack.top();
+    contacts_filter_h sub_filter = NULL;
+    int ret = 0;
+    ret = contacts_filter_create(_contacts_phone_log._uri, &sub_filter);
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("%d: %s", ret,
+            CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+    }
+
+    contacts_match_str_flag_e c_match_flag;
+    switch (attr_filter->getMatchFlag()) {
+        case FULLSTRING:
+            c_match_flag = CONTACTS_MATCH_FULLSTRING;
+            break;
+        case CONTAINS:
+            c_match_flag = CONTACTS_MATCH_CONTAINS;
+            break;
+        case STARTSWITH:
+            c_match_flag = CONTACTS_MATCH_STARTSWITH;
+            break;
+        case ENDSWITH:
+            c_match_flag = CONTACTS_MATCH_ENDSWITH;
+            break;
+        case EXISTS:
+            c_match_flag = CONTACTS_MATCH_EXISTS;
+            break;
+        default:
+            c_match_flag = CONTACTS_MATCH_EXACTLY;
+            break;
+    }
+
+    const std::string& attr_name = attr_filter->getAttributeName();
+    if (attr_name.compare(STR_DIRECTION) == 0) {
+        const std::string match_value_str = match_value->toString();
+        if (match_value_str.compare(STR_RECEIVED) == 0) {
+            ret = contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_INCOMMING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_INCOMMING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (match_value_str.compare(STR_DIALED) == 0) {
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_OUTGOING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_OUTGOING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (match_value_str.compare(STR_MISSED) == 0) {
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (match_value_str.compare(STR_MISSED_NEW) == 0) {
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (match_value_str.compare(STR_REJECTED) == 0) {
+            ret = contacts_filter_add_int(sub_filter, _contacts_phone_log.log_type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_REJECT);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_REJECT);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (match_value_str.compare(STR_BLOCKED) == 0) {
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_BLOCKED);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            ret = contacts_filter_add_int(filter, _contacts_phone_log.log_type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_NONE);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+    }
+    else if (attr_name.compare(STR_TAGS) == 0) {
+        const std::string match_value_str = match_value->toString();
+        if (match_value_str.compare(STR_CALL) == 0) {
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type,
+                CONTACTS_MATCH_GREATER_THAN_OR_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_INCOMMING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_AND);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_LESS_THAN_OR_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (match_value_str.compare(STR_CALL_VOICE) == 0) {
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_INCOMMING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_OUTGOING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_INCOMMING_UNSEEN);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_INCOMMING_SEEN);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_REJECT);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VOICE_BLOCKED);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (match_value_str.compare(STR_CALL_VIDEO) == 0) {
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_INCOMMING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_OUTGOING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_UNSEEN);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_INCOMMING_SEEN);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_VIDEO_REJECT);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_OR);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type, CONTACTS_MATCH_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (match_value_str.compare(STR_CALL_EMERGENCY) == 0) {
+            ret = contacts_filter_add_str(filter,
+                _contacts_phone_log.extra_data2, CONTACTS_MATCH_EXACTLY, "001");
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            ret = contacts_filter_add_int(filter, _contacts_phone_log.log_type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_NONE);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+    }
+    else if (attr_name.compare(STR_RP_REMOTEPARTY) == 0) {
+        ret = contacts_filter_add_str(filter, _contacts_phone_log.address,
+            c_match_flag, match_value->toString().c_str());
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+    }
+    else if (attr_name.compare(STR_RP_PERSONID) == 0) {
+        ret = contacts_filter_add_str(filter, _contacts_phone_log.person_id,
+            c_match_flag, match_value->toString().c_str());
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+    }
+    else if (attr_name.compare(STR_START_TIME) == 0) {
+        ret = contacts_filter_add_int(filter, _contacts_phone_log.log_time,
+            CONTACTS_MATCH_EQUAL, static_cast<int>(match_value->toTimeT()));
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+
+    }
+    else if (attr_name.compare(STR_DURATION) == 0) {
+        ret = contacts_filter_add_str(filter, _contacts_phone_log.extra_data1,
+            c_match_flag, match_value->toString().c_str());
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+    }
+    else if (attr_name.compare(STR_CALL_TYPE) == 0) {
+        if (match_value->toString().compare(STR_TIZEN_TEL) == 0) {
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type,
+                CONTACTS_MATCH_GREATER_THAN_OR_EQUAL,
+                CONTACTS_PLOG_TYPE_VOICE_INCOMMING);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_AND);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter,
+                _contacts_phone_log.log_type,
+                CONTACTS_MATCH_LESS_THAN_OR_EQUAL,
+                CONTACTS_PLOG_TYPE_VIDEO_BLOCKED);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else {
+            ret = contacts_filter_add_int(filter, _contacts_phone_log.log_type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_NONE);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+    }
+    else if (attr_name.compare(STR_ENTRY_ID) == 0) {
+        ret = contacts_filter_add_str(filter, _contacts_phone_log.id,
+            c_match_flag, match_value->toString().c_str());
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+    }
+    else {
+        ret = contacts_filter_add_int(filter, _contacts_phone_log.log_type,
+            CONTACTS_MATCH_EQUAL, CONTACTS_PLOG_TYPE_NONE);
+        if (ret != CONTACTS_ERROR_NONE) {
+            LOGE("%d: %s", ret,
+                CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+        }
+    }
+
+    ret = contacts_filter_destroy(sub_filter);
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("%d: %s", ret,
+            CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+    }
+}
+
+void CallHistoryFilterQueryGenerator::visitAttributeRange(
+        AttributeRangeFilterPtr attr_range_filter)
+{
+    LOGD("Entered");
+    if (!attr_range_filter) {
+        return;
+    }
+
+    AnyPtr initial_value = attr_range_filter->getInitialValue();
+    AnyPtr end_value = attr_range_filter->getEndValue();
+    if (!initial_value || !end_value) {
+        LOGD("initial_value or end_value is NULL");
+        return;
+    }
+
+    const std::string& attr_name = attr_range_filter->getAttributeName();
+    contacts_filter_h filter = m_filter_stack.top();
+
+    unsigned int property_id = 0;
+    int i_value = 0;
+    int e_value = 0;
+    int ret = 0;
+
+    if (attr_name.compare(STR_RP_REMOTEPARTY) == 0) {
+        property_id = _contacts_phone_log.address;
+    }
+    else if (attr_name.compare(STR_RP_PERSONID) == 0) {
+        property_id = _contacts_phone_log.person_id;
+    }
+    else if (attr_name.compare(STR_START_TIME) == 0) {
+        property_id = _contacts_phone_log.log_time;
+    }
+    else if (attr_name.compare(STR_DURATION) == 0) {
+        property_id = _contacts_phone_log.extra_data1;
+    }
+    else if (attr_name.compare(STR_ENTRY_ID) == 0) {
+        property_id = _contacts_phone_log.id;
+    }
+    else {
+        LOGW("attribute: %s is not supported", attr_name.c_str());
+        return;
+    }
+
+    if (!initial_value->isNullOrUndefined()) {
+        if (property_id != _contacts_phone_log.address) {
+            if (attr_name.compare(STR_START_TIME) == 0) {
+                i_value = static_cast<int>(initial_value->toTimeT());
+            }
+            else {
+                i_value = atoi(initial_value->toString().c_str());
+            }
+        }
+    }
+
+    if (!end_value->isNullOrUndefined()) {
+        if (property_id != _contacts_phone_log.address) {
+            if (attr_name.compare(STR_START_TIME) == 0) {
+                e_value = static_cast<int>(end_value->toTimeT());
+            }
+            else {
+                e_value = atoi(end_value->toString().c_str());
+            }
+        }
+    }
+
+    contacts_filter_h sub_filter = NULL;
+    ret = contacts_filter_create(_contacts_phone_log._uri, &sub_filter);
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("%d: %s", ret,
+            CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+    }
+
+    if (property_id == _contacts_phone_log.address) {
+        if (!initial_value->isNullOrUndefined() && end_value->isNullOrUndefined()) {
+            ret = contacts_filter_add_str(filter, property_id,
+                CONTACTS_MATCH_STARTSWITH, initial_value->toString().c_str());
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (initial_value->isNullOrUndefined() &&
+            !end_value->isNullOrUndefined()) {
+            ret = contacts_filter_add_str(filter, property_id,
+                CONTACTS_MATCH_ENDSWITH, end_value->toString().c_str());
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (!initial_value->isNullOrUndefined() &&
+            !end_value->isNullOrUndefined()) {
+            ret = contacts_filter_add_str(sub_filter, property_id,
+                CONTACTS_MATCH_STARTSWITH, initial_value->toString().c_str());
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_AND);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_str(sub_filter, property_id,
+                CONTACTS_MATCH_ENDSWITH, end_value->toString().c_str());
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+    }
+    else {
+        if (!initial_value->isNullOrUndefined() && end_value->isNullOrUndefined()) {
+            ret = contacts_filter_add_int(filter, property_id,
+                CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, i_value);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (initial_value->isNullOrUndefined() &&
+            !end_value->isNullOrUndefined()) {
+            ret = contacts_filter_add_int(filter, property_id,
+                CONTACTS_MATCH_LESS_THAN, e_value);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+        else if (!initial_value->isNullOrUndefined() &&
+            !end_value->isNullOrUndefined()) {
+            ret = contacts_filter_add_int(sub_filter, property_id,
+                CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, i_value);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_operator(sub_filter,
+                CONTACTS_FILTER_OPERATOR_AND);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_int(sub_filter, property_id,
+                CONTACTS_MATCH_LESS_THAN, e_value);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+            ret = contacts_filter_add_filter(filter, sub_filter);
+            if (ret != CONTACTS_ERROR_NONE) {
+                LOGE("%d: %s", ret,
+                    CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+            }
+        }
+    }
+    ret = contacts_filter_destroy(sub_filter);
+    if (ret != CONTACTS_ERROR_NONE) {
+        LOGE("%d: %s", ret,
+            CallHistoryUtil::getCallHistoryErrorMessage(ret).c_str());
+    }
+}
+
+} //CallHistory
+} //DeviceAPI
diff --git a/src/Callhistory/CallHistoryFilterQueryGenerator.h b/src/Callhistory/CallHistoryFilterQueryGenerator.h
new file mode 100755 (executable)
index 0000000..5255935
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CALLHISTORY_FILTER_QUERY_GENERATOR_H__
+#define __TIZEN_CALLHISTORY_FILTER_QUERY_GENERATOR_H__
+
+#include <string>
+#include <stack>
+#include <contacts.h>
+#include "time.h"
+
+#include "AbstractFilter.h"
+#include "CallHistoryTypes.h"
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+class CallHistoryFilterQueryGenerator
+{
+public:
+    CallHistoryFilterQueryGenerator(contacts_filter_h filter);
+    ~CallHistoryFilterQueryGenerator();
+
+    contacts_filter_h generate(Tizen::AbstractFilterPtr src_filter);
+    contacts_filter_h getResult() const;
+
+private:
+    void visitAttribute(Tizen::AttributeFilterPtr attr_filter);
+    void visitAttributeRange(Tizen::AttributeRangeFilterPtr attr_range_filter);
+
+    std::stack<contacts_filter_h> m_filter_stack;
+};
+
+} //CallHistory
+} //DeviceAPI
+
+#endif //__TIZEN_CALLHISTORY_FILTER_QUERY_GENERATOR_H__
diff --git a/src/Callhistory/CallHistoryTypes.h b/src/Callhistory/CallHistoryTypes.h
new file mode 100755 (executable)
index 0000000..09d2cb2
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _CALLHISTORY_TYPES_H_
+#define _CALLHISTORY_TYPES_H_
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+
+#define STR_CALLTYPE_TEL            "TEL"
+#define STR_CALLTYPE_XMPP            "XMPP"
+#define STR_CALLTYPE_SIP            "SIP"
+
+#define STR_FEATURE_CALL            "CALL"
+#define STR_FEATURE_VOICE            "VOICECALL"
+#define STR_FEATURE_VIDEO            "VIDEOCALL"
+#define STR_FEATURE_EMERGENCY        "EMERGENCYCALL"
+
+#define STR_DIRECTION_DIALED            "DIALED"
+#define STR_DIRECTION_RECEIVED            "RECEIVED"
+#define STR_DIRECTION_MISSED_NEW        "MISSEDNEW"
+#define STR_DIRECTION_MISSED            "MISSED"
+#define STR_DIRECTION_REJECTED            "REJECTED"
+#define STR_DIRECTION_BLOCKED            "BLOCKED"
+
+#define STR_ENTRY_ID            "uid"
+#define STR_SERVICE_ID            "serviceId"
+#define STR_CALL_TYPE            "type"
+#define STR_TAGS                "features"
+#define STR_REMOTE_PARTIES        "remoteParties"
+#define STR_FORWARDEDFROM        "forwardedFrom"
+#define STR_START_TIME            "startTime"
+#define STR_DURATION            "duration"
+#define STR_END_REASON            "endReason"
+#define STR_DIRECTION            "direction"
+#define STR_CALLING_PARTY       "callingParty"
+
+#define STR_REMOTE_PARTY        "remoteParty"
+#define STR_PERSIONID            "personId"
+
+#define STR_RP_REMOTEPARTY        "remoteParties.remoteParty"
+#define STR_RP_PERSONID            "remoteParties.personId"
+
+#define STR_LOG_ID                "id"
+#define STR_NUMBER                "number"
+#define STR_LOG_TIME            "log_time"
+#define STR_LOG_TYPE            "log_type"
+#define STR_DATA1                "data1"
+#define STR_PERSON_ID            "person_id"
+
+
+#define STR_DIALED                "DIALED"
+#define STR_RECEIVED            "RECEIVED"
+#define STR_MISSED_NEW            "MISSEDNEW"
+#define STR_MISSED                "MISSED"
+#define STR_REJECTED            "REJECTED"
+#define STR_BLOCKED                "BLOCKED"
+
+#define STR_TIZEN_TEL            "TEL"
+#define STR_TIZEN_XMPP            "XMPP"
+#define STR_TIZEN_SIP            "SIP"
+
+#define STR_CALL                "CALL"
+#define STR_CALL_VOICE            "VOICECALL"
+#define STR_CALL_VIDEO            "VIDEOCALL"
+#define STR_CALL_EMERGENCY        "EMERGENCYCALL"
+
+
+} // Callhistory
+} // DeviceAPI
+
+#endif // _CALLHISTORY_TYPES_H_
diff --git a/src/Callhistory/CallHistoryUtil.cpp b/src/Callhistory/CallHistoryUtil.cpp
new file mode 100644 (file)
index 0000000..35e1094
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CallHistoryUtil.h"
+
+#include <sstream>
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+void CallHistoryUtil::throwCallHistoryException(const int error_code,
+                                                const std::string &hint)
+{
+    std::stringstream ss;
+    ss << hint << " : " << getCallHistoryErrorMessage(error_code);
+    LOGE("%s", ss.str().c_str());
+
+    throw UnknownException(ss.str().c_str());
+}
+
+std::string CallHistoryUtil::getCallHistoryErrorMessage(const int error_code)
+{
+    switch (error_code) {
+        case CONTACTS_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case CONTACTS_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case CONTACTS_ERROR_FILE_NO_SPACE:
+            return "FS Full";
+        case CONTACTS_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case CONTACTS_ERROR_NOT_SUPPORTED:
+            return "Not supported";
+        case CONTACTS_ERROR_NO_DATA:
+            return "Requested data does not exist";
+        case CONTACTS_ERROR_DB_LOCKED:
+            return "Database table locked or file locked";
+        case CONTACTS_ERROR_DB:
+            return "Unknown DB error";
+        case CONTACTS_ERROR_IPC_NOT_AVALIABLE:
+            return "IPC server is not available";
+        case CONTACTS_ERROR_IPC:
+            return "Unknown IPC error";
+        case CONTACTS_ERROR_SYSTEM:
+            return "Internal system module error";
+        case CONTACTS_ERROR_INTERNAL:
+            return "Implementation Error, Temporary Use";
+        default:
+            return "Unknown error";
+    }
+}
+
+} // CallHistory
+} // DeviceAPI
diff --git a/src/Callhistory/CallHistoryUtil.h b/src/Callhistory/CallHistoryUtil.h
new file mode 100644 (file)
index 0000000..54b3916
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CALL_HISTORY_CALL_HISTORY_UTIL_H_
+#define __TIZEN_CALL_HISTORY_CALL_HISTORY_UTIL_H_
+
+#include <string>
+#include <contacts.h>
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+class CallHistoryUtil {
+public:
+    static void throwCallHistoryException(
+        const int errorCode, const std::string &hint);
+    static std::string getCallHistoryErrorMessage(const int errorCode);
+};
+
+} // CallHistory
+} // DeviceAPI
+
+#endif // __TIZEN_CALL_HISTORY_CALL_HISTORY_UTIL_H_
diff --git a/src/Callhistory/Converter.cpp b/src/Callhistory/Converter.cpp
new file mode 100755 (executable)
index 0000000..18230c8
--- /dev/null
@@ -0,0 +1,280 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "Converter.h"
+#include <Commons/Exception.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include "CallHistoryTypes.h"
+#include "JSCallHistoryEntry.h"
+#include "JSRemoteParty.h"
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+Converter::Converter(JSContextRef context) : WrtDeviceApis::CommonsJavaScript::Converter(context)
+{
+    static bool init = initializeAllowedProperties();
+    (void) init;
+}
+
+std::vector<unsigned long> Converter::toVectorOfULongs(const JSValueRef& jsValue)
+{
+    return toVectorOfT_(jsValue, &Converter::toULong);
+}
+
+CallHistoryEntryList Converter::toVectorOfCallHistoryEntryProperties(const JSValueRef& jsValue)
+{
+    if (JSValueIsNull(m_context, jsValue) || JSValueIsUndefined(m_context, jsValue)) {
+        ThrowMsg(Commons::ConversionException, "Undefined history entry");
+    }
+
+    if (!JSIsArrayValue(m_context, jsValue)) {
+        ThrowMsg(Commons::ConversionException, "Argument is not an JS array.");
+    }
+
+    try {
+        CallHistoryEntryList result;
+        JSObjectRef objArg = toJSObjectRef(jsValue);
+        for (std::size_t i = 0; i < JSGetArrayLength(m_context, objArg); ++i) {
+            JSValueRef element = JSGetArrayElement(m_context, objArg, i);
+            result.push_back(toCallHistoryEntryProperties(element));
+        }
+        return result;
+    } catch (Commons::ConversionException& ex) {
+        ThrowMsg(Commons::ConversionException, ex.GetMessage());
+    } catch (Commons::InvalidArgumentException& ex) {
+        ThrowMsg(Commons::InvalidArgumentException, ex.GetMessage());
+    } catch (Commons::Exception& ex) {
+        ThrowMsg(Commons::Exception, ex.GetMessage());
+    }
+
+}
+
+StringArrayPtr Converter::toStringArray(const JSValueRef &jsValue)
+{
+    StringArrayPtr result(new StringArray());
+    try {
+        if (!JSValueIsNull(m_context, jsValue)) {
+            JSObjectRef jsObject = toJSObjectRef(jsValue);
+
+            for (std::size_t i = 0; i < JSGetArrayLength(m_context, jsObject); ++i) {
+                JSValueRef element = JSGetArrayElement(m_context, jsObject, i);
+                result->push_back(toString(element));
+            }
+        }
+    } catch (Commons::ConversionException& ex) {
+        ThrowMsg(Commons::ConversionException, ex.GetMessage());
+    } catch (Commons::InvalidArgumentException& ex) {
+        ThrowMsg(Commons::InvalidArgumentException, ex.GetMessage());
+    } catch (Commons::Exception& ex) {
+        ThrowMsg(Commons::Exception, ex.GetMessage());
+    }
+    return result;
+}
+
+RemotePartyListPtr Converter::toRemotePartyList(const JSValueRef &jsValue)
+{
+    RemotePartyListPtr result(new RemotePartyList());
+    try {
+        if (!JSValueIsNull(m_context, jsValue)) {
+            JSObjectRef jsObject = toJSObjectRef(jsValue);
+
+            for (std::size_t i = 0; i < JSGetArrayLength(m_context, jsObject); ++i) {
+                JSValueRef element = JSGetArrayElement(m_context, jsObject, i);
+                result->push_back(toRemoteParty(element));
+            }
+        }
+    } catch (Commons::ConversionException& ex) {
+        ThrowMsg(Commons::ConversionException, ex.GetMessage());
+    } catch (Commons::InvalidArgumentException& ex) {
+        ThrowMsg(Commons::InvalidArgumentException, ex.GetMessage());
+    } catch (Commons::Exception& ex) {
+        ThrowMsg(Commons::Exception, ex.GetMessage());
+    }
+    return result;
+}
+
+RemotePartyPtr Converter::toRemoteParty(const JSValueRef &jsValue)
+{
+    try {
+        return JSRemoteParty::getRemoteParty(m_context, jsValue);
+    } catch (Commons::ConversionException& ex) {
+        ThrowMsg(Commons::ConversionException, ex.GetMessage());
+    } catch (Commons::Exception& ex) {
+        ThrowMsg(Commons::Exception, ex.GetMessage());
+    }
+}
+
+CallHistoryEntryPropertiesPtr Converter::toCallHistoryEntryProperties(const JSValueRef &jsValue)
+{
+    try {
+        return JSCallHistoryEntry::getCallHistoryEntry(m_context, jsValue);
+    } catch (Commons::ConversionException& ex) {
+        ThrowMsg(Commons::ConversionException, ex.GetMessage());
+    } catch (Commons::Exception& ex) {
+        ThrowMsg(Commons::Exception, ex.GetMessage());
+    }
+}
+
+EventCallHistoryListenerPrivateDataPtr
+    Converter::toEventCallHistoryListenerPrivateData(const JSValueRef &jsValue, JSContextRef context)
+{
+    LOGD("Entered");
+
+    if (JSValueIsNull(m_context, jsValue) || JSValueIsUndefined(m_context, jsValue)) {
+        ThrowMsg(Commons::ConversionException, "Type missmatch error : Listener callback is null or undefined");
+    }
+    if (!JSValueIsObject(m_context, jsValue) || JSObjectIsFunction(m_context, toJSObjectRef(jsValue))) {
+        ThrowMsg(Commons::ConversionException, "Type missmatch error : Listener callback");
+    }
+
+    JSObjectRef objectCallbacks = toJSObjectRef(jsValue);
+    CallHistoryChangeCB result;
+
+    result.onAdded = JSUtils::getJSPropertyOrUndefined(m_context, objectCallbacks, "onadded");
+    result.onChanged = JSUtils::getJSPropertyOrUndefined(m_context, objectCallbacks, "onchanged");
+    result.onRemoved = JSUtils::getJSPropertyOrUndefined(m_context, objectCallbacks, "onremoved");
+
+    JSCallbackManagerPtr onAddedCbm = JSCallbackManager::createObject(context);
+    JSCallbackManagerPtr onChangedCbm = JSCallbackManager::createObject(context);
+    JSCallbackManagerPtr onRemovedCbm = JSCallbackManager::createObject(context);
+
+    if (!JSValueIsNull(m_context, result.onAdded) && !JSValueIsUndefined(m_context, result.onAdded)) {
+        if (JSObjectIsFunction(m_context, toJSObjectRef(result.onAdded))) {
+            onAddedCbm->setOnSuccess(result.onAdded);
+        } else {
+            ThrowMsg(Commons::ConversionException, "Type missmatch error : onadded callback");
+        }
+    }
+
+    if (!JSValueIsNull(m_context, result.onChanged) && !JSValueIsUndefined(m_context, result.onChanged)) {
+        if (JSObjectIsFunction(m_context, toJSObjectRef(result.onChanged))) {
+            onChangedCbm->setOnSuccess(result.onChanged);
+        } else {
+            ThrowMsg(Commons::ConversionException, "Type missmatch error : onchanged callback");
+        }
+    }
+
+    if (!JSValueIsNull(m_context, result.onRemoved) && !JSValueIsUndefined(m_context, result.onRemoved)) {
+        if (JSObjectIsFunction(m_context, toJSObjectRef(result.onRemoved))) {
+            onRemovedCbm->setOnSuccess(result.onRemoved);
+            LOGD("onRemoved register");
+        } else {
+
+            ThrowMsg(Commons::ConversionException, "Type missmatch exception");
+        }
+    }
+
+
+    return EventCallHistoryListenerPrivateDataPtr(new EventCallHistoryListenerPrivateData(onAddedCbm, onChangedCbm, onRemovedCbm));
+}
+
+JSValueRef Converter::toJSValueRef(const CallHistoryEntryListPtr& arg, JSContextRef context)
+{
+    JSObjectRef jsResult = JSCreateArrayObject(m_context, 0, NULL);
+    if (!jsResult) {
+        ThrowMsg(Commons::ConversionException, "Could not create js array object");
+    }
+    /*  // Temporary
+    CallHistoryEntryProperties tmpCallEntry;
+
+    try {
+        for (size_t i = 0; i < (*arg).size(); i++) {
+            tmpCallEntry = *((*arg)[i]);
+            JSObjectRef jsObject = JSCallHistoryEntry::createJSObject(context, tmpCallEntry);
+            if (!jsObject) {
+                ThrowMsg(Commons::ConversionException, "Could not create JS object.");
+            }
+
+            if (!JSSetArrayElement(m_context, jsResult, i, jsObject)) {
+                ThrowMsg(Commons::ConversionException, "Could not insert value into js array");
+            }
+        }
+    } catch (Commons::ConversionException& ex) {
+        ThrowMsg(Commons::ConversionException, ex.GetMessage());
+    } catch (Commons::InvalidArgumentException& ex) {
+        ThrowMsg(Commons::InvalidArgumentException, ex.GetMessage());
+    } catch (Commons::Exception& ex) {
+        ThrowMsg(Commons::Exception, ex.GetMessage());
+    }
+    */
+    return jsResult;
+}
+
+JSValueRef Converter::toJSValueRef(const StringArrayPtr &arg, JSContextRef context)
+{
+    JSObjectRef jsResult = JSCreateArrayObject(m_context, 0, NULL);
+    if (!jsResult) {
+        ThrowMsg(Commons::ConversionException, "Could not create js array object");
+    }
+
+    for (size_t i = 0; i < (*arg).size(); i++) {
+        if (!JSSetArrayElement(m_context, jsResult, i, toJSValueRef((*arg)[i]))) {
+            ThrowMsg(Commons::ConversionException, "Could not insert value into js array");
+        }
+    }
+
+    return jsResult;
+}
+
+JSValueRef Converter::toJSValueRef(const RemotePartyListPtr& arg, JSContextRef context)
+{
+    JSObjectRef jsResult = JSCreateArrayObject(m_context, 0, NULL);
+    if (!jsResult) {
+        ThrowMsg(Commons::ConversionException, "Could not create js array object");
+    }
+
+    RemoteParty tmpRemoteParty;
+
+    try {
+        for (size_t i = 0; i < (*arg).size(); i++) {
+            tmpRemoteParty = *((*arg)[i]);
+            JSObjectRef jsObject = JSRemoteParty::createJSObject(context, tmpRemoteParty);
+            if (!jsObject) {
+                ThrowMsg(Commons::ConversionException, "Could not create JS object.");
+            }
+
+            if (!JSSetArrayElement(m_context, jsResult, i, jsObject)) {
+                ThrowMsg(Commons::ConversionException, "Could not insert value into js array");
+            }
+        }
+    } catch (Commons::ConversionException& ex) {
+        ThrowMsg(Commons::ConversionException, ex.GetMessage());
+    } catch (Commons::InvalidArgumentException& ex) {
+        ThrowMsg(Commons::InvalidArgumentException, ex.GetMessage());
+    } catch (Commons::Exception& ex) {
+        ThrowMsg(Commons::Exception, ex.GetMessage());
+    }
+    return jsResult;
+}
+
+bool Converter::initializeAllowedProperties()
+{
+    return true;
+}
+
+}
+}
+
diff --git a/src/Callhistory/Converter.h b/src/Callhistory/Converter.h
new file mode 100755 (executable)
index 0000000..ba6a437
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZEN_APIS_CALL_CONVERTER_H_
+#define TIZEN_APIS_CALL_CONVERTER_H_
+
+#include <vector>
+#include <string>
+#include <map>
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/Converter.h>
+#include "RemoteParty.h"
+#include <ContactConverter.h>
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+class Converter : public WrtDeviceApis::CommonsJavaScript::Converter
+{
+public:
+    using WrtDeviceApis::CommonsJavaScript::Converter::toJSValueRef;
+
+public:
+    explicit Converter(JSContextRef context);
+
+    std::vector<unsigned long> toVectorOfULongs(const JSValueRef& jsValue);
+
+    CallHistoryEntryList toVectorOfCallHistoryEntryProperties(const JSValueRef& jsValue);
+
+    StringArrayPtr toStringArray(const JSValueRef &jsValue);
+
+    RemotePartyListPtr toRemotePartyList(const JSValueRef &jsValue);
+
+    RemotePartyPtr toRemoteParty(const JSValueRef &jsValue);
+
+    CallHistoryEntryPropertiesPtr toCallHistoryEntryProperties(const JSValueRef &jsValue);
+
+    EventCallHistoryListenerPrivateDataPtr toEventCallHistoryListenerPrivateData(const JSValueRef &jsValue, JSContextRef context);
+
+    JSValueRef toJSValueRef(const CallHistoryEntryListPtr &arg, JSContextRef context);
+
+    JSValueRef toJSValueRef(const StringArrayPtr &arg, JSContextRef context);
+
+    JSValueRef toJSValueRef(const RemotePartyListPtr& arg, JSContextRef context);
+
+private:
+    bool initializeAllowedProperties();
+};
+
+typedef WrtDeviceApis::CommonsJavaScript::ConverterFactory<Converter> ConverterFactory;
+typedef ConverterFactory::ConverterType ConverterPtr;
+}
+}
+
+#endif
\ No newline at end of file
diff --git a/src/Callhistory/JSCallHistory.cpp b/src/Callhistory/JSCallHistory.cpp
new file mode 100755 (executable)
index 0000000..07702b4
--- /dev/null
@@ -0,0 +1,465 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+
+#include "CallHistory.h"
+#include "CallHistoryEntryArraySuccessCallback.h"
+#include "CallHistoryEntry.h"
+#include "CallHistoryChangeCallback.h"
+#include "JSCallHistory.h"
+#include "JSCallHistoryEntry.h"
+
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+#include <Logger.h>
+#include <Export.h>
+#include <JSSortMode.h>
+
+using namespace std;
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+namespace {
+    const char* CALLBACK_NAME_ONADDED = "onadded";
+    const char* CALLBACK_NAME_ONCHANGED = "onchanged";
+    const char* CALLBACK_NAME_ONREMVOED = "onremoved";
+}
+
+JSClassRef JSCallHistory::m_jsClassRef =
+    JSClassCreate(JSCallHistory::getClassInfo());
+
+JSClassDefinition JSCallHistory::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_CALLHISTORY_CALLHISTORY_CLASS,
+    NULL,
+    NULL, // m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    hasInstance,
+    NULL
+};
+
+JSStaticValue JSCallHistory::m_property[] = {
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSCallHistory::m_function[] =
+{
+    {
+        "find",
+        JSCallHistory::find,
+        kJSPropertyAttributeNone
+    },
+    {
+        "remove",
+        JSCallHistory::remove,
+        kJSPropertyAttributeNone
+    },
+    {
+        "removeBatch",
+        JSCallHistory::removeBatch,
+        kJSPropertyAttributeNone
+    },
+    {
+        "removeAll",
+        JSCallHistory::removeAll,
+        kJSPropertyAttributeNone
+    },
+    {
+        "addChangeListener",
+        JSCallHistory::addChangeListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        "removeChangeListener",
+        JSCallHistory::removeChangeListener,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSCallHistory::getClassRef() {
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSCallHistory::getClassInfo() {
+    return &m_classInfo;
+}
+
+void JSCallHistory::initialize(JSContextRef context, JSObjectRef object) {
+    LOGD("Entered");
+    JSObjectSetPrivate(object, static_cast<void*>(CallHistory::getInstance()));
+}
+
+void JSCallHistory::finalize(JSObjectRef object) {
+    LOGD("Entered");
+}
+
+
+bool JSCallHistory::hasInstance(JSContextRef context,
+    JSObjectRef constructor,
+    JSValueRef possibleInstance,
+    JSValueRef* exception)
+{
+    return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
+}
+
+JSValueRef JSCallHistory::find(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef this_object,
+    size_t argument_count,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    SET_TIME_TRACER_ITEM(0);
+    CallHistoryEntryArraySuccessCallback* callback = NULL;
+
+    try {
+        CallHistory* callHistory = CallHistory::getInstance();
+        if (!callHistory) {
+            LOGE("callhistory instance is null");
+            throw TypeMismatchException("callhistory instance is null");
+        }
+
+        auto global_ctx = GlobalContextManager::getInstance()->
+           getGlobalContext(context);
+
+        callback = new CallHistoryEntryArraySuccessCallback(global_ctx);
+
+        TIZEN_CHECK_ACCESS(context, exception, callHistory,
+            CALL_HISTORY_FUNCTION_API_FIND);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        JSObjectRef success_CB = validator.toFunction(0);
+        if (success_CB) {
+            callback->setSuccessCallback(success_CB);
+        }
+
+        JSObjectRef err_CB = validator.toFunction(1, true);
+        if (err_CB) {
+            callback->setErrorCallback(err_CB);
+        }
+
+        JSValueRef filter_ref = validator.toJSValueRef(2, true);
+        if (!JSValueIsNull(context, filter_ref)) {
+            AbstractFilterPtr filter = AbstractFilter::getPrivateObject(context,
+                filter_ref);
+            callback->setFilter(filter);
+            LOGD("Set filter with type: %d", filter->getFilterType());
+        }
+
+        JSValueRef sort_mode_ref = validator.toJSValueRef(3, true);
+        if (!JSValueIsNull(context, sort_mode_ref)) {
+            SortModePtr sort_mode =
+                JSSortMode::getPrivateObject(context, sort_mode_ref);
+            callback->setSortMode(sort_mode);
+            LOGD("Set sort mode: %d for attribute: %s", sort_mode->getOrder(),
+                   sort_mode->getAttributeName().c_str());
+        }
+
+        callback->setLimit(validator.toULong(4, true));
+        callback->setOffset(validator.toULong(5, true));
+
+        callHistory->find(callback);
+
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        delete callback;
+        callback = NULL;
+
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch(...) {
+        LOGE("Catched unknown exception");
+
+        delete callback;
+        callback = NULL;
+
+        DeviceAPI::Common::UnknownException err("Unknown error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCallHistory::remove(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    LOGD("Entered");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        CallHistory* callHistory = CallHistory::getInstance();
+        if (!callHistory) {
+            LOGE("callhistory instance is null");
+            throw TypeMismatchException("callhistory instance is null");
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, callHistory,
+            CALL_HISTORY_FUNCTION_API_REMOVE);
+
+        if (argumentCount < 1) {
+            LOGE("argument is less than 1");
+            throw TypeMismatchException("argument is less than 1");
+        }
+
+        if (!JSValueIsObjectOfClass(context, arguments[0],
+                JSCallHistoryEntry::getClassRef())) {
+            LOGE("object is not callhistory entry");
+            throw TypeMismatchException("objet is not callhistory entry");
+        }
+
+        JSObjectRef entryObj = validator.toObject(0);
+        CallHistoryEntryHolderPtr holder =
+            static_cast<CallHistoryEntryHolderPtr>(JSObjectGetPrivate(entryObj));
+        if (!holder) {
+            LOGE("holder is null");
+            throw TypeMismatchException(
+                "CallHistoryEntry's private object is NULL.");
+        }
+
+        callHistory->remove(holder->mEntry);
+
+        return JSValueMakeUndefined(context);
+    } catch(const BasePlatformException& err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSCallHistory::removeBatch(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+    CallHistoryEntryRemoveCallback* callback = NULL;
+
+    try {
+        CallHistory* callHistory = CallHistory::getInstance();
+        if (!callHistory) {
+            LOGE("callhistory instance is null");
+            throw TypeMismatchException("callhistory instance is null");
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, callHistory,
+            CALL_HISTORY_FUNCTION_API_REMOVE_BATCH);
+
+        if (argumentCount < 1) {
+            LOGE("argument is less than 1");
+            throw TypeMismatchException("argument is less than 1");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new CallHistoryEntryRemoveCallback(
+            GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        JSObjectRef entryListObj = validator.toObject(0);
+        std::vector<CallHistoryEntryPtr> entryList =
+            JSUtil::JSArrayToType_<CallHistoryEntryPtr>(context, entryListObj,
+                JSCallHistoryEntry::toCallHistoryEntry);
+        callback->setCallhistoryEntryList(entryList);
+        callback->setCallHistoryIsSet(true);
+
+        JSObjectRef successCB = validator.toFunction(1, true);
+        if (successCB) {
+            callback->setSuccessCallback(successCB);
+            callback->setSuccessCBIsSet(true);
+        }
+
+        JSObjectRef errCB = validator.toFunction(2, true);
+        if (errCB)
+            callback->setErrorCallback(errCB);
+
+        callHistory->removeBatch(callback);
+        return JSValueMakeUndefined(context);
+    } catch(const BasePlatformException& err) {
+        delete callback;
+        callback = NULL;
+
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSCallHistory::removeAll(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+
+    SET_TIME_TRACER_ITEM(0);
+
+    CallHistoryEntryRemoveCallback* callback = NULL;
+
+    try{
+        CallHistory* callHistory = CallHistory::getInstance();
+        if (!callHistory) {
+            LOGE("callhistory instance is null");
+            throw TypeMismatchException("callhistory instance is null");
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, callHistory,
+            CALL_HISTORY_FUNCTION_API_REMOVE_ALL);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new CallHistoryEntryRemoveCallback(
+            GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        JSObjectRef successCB = validator.toFunction(0, true);
+        if (successCB != NULL) {
+            callback->setSuccessCallback(successCB);
+            callback->setSuccessCBIsSet(true);
+        }
+
+        JSObjectRef errCB = validator.toFunction(1, true);
+        if (errCB != NULL)
+            callback->setErrorCallback(errCB);
+
+        callHistory->removeAll(callback);
+    } catch(const BasePlatformException& err) {
+        delete callback;
+        callback = NULL;
+
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSCallHistory::addChangeListener(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef this_object,
+    size_t argument_count,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    CallHistoryChangeCallbackPtr callback;
+    try {
+        CallHistory* callHistory = CallHistory::getInstance();
+        if (!callHistory) {
+            LOGE("Private object is NULL");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, callHistory,
+            CALL_HISTORY_FUNCTION_API_ADDLISTENER);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+        JSObjectRef observer_obj = validator.toCallbackObject(0, false,
+            CALLBACK_NAME_ONADDED,
+            CALLBACK_NAME_ONCHANGED,
+            CALLBACK_NAME_ONREMVOED,
+            NULL);
+
+        if (observer_obj) {
+            callback = CallHistoryChangeCallbackPtr(
+                new CallHistoryChangeCallback(
+                    GlobalContextManager::getInstance()->getGlobalContext(context),
+                    observer_obj));
+        }
+
+        long ret = callHistory->addChangeListener(callback);
+        LOGD("addChangeListener returned: %d", ret);
+
+        return JSUtil::toJSValueRef(context, ret);
+    } catch(const BasePlatformException& err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSCallHistory::removeChangeListener(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    long handle = 0;
+
+    try {
+        CallHistory* callHistory = CallHistory::getInstance();
+        if (!callHistory) {
+            LOGE("Private object is null");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, callHistory,
+            CALL_HISTORY_FUNCTION_API_REMOVELISTENER);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        handle = validator.toLong(0);
+        if (handle != 0) {
+            callHistory->removeChangeListener(context, handle);
+        } else {
+            LOGE("%ld", handle);
+            throw InvalidValuesException("Invalid watchId");
+        }
+        return JSValueMakeUndefined(context);
+    } catch(const BasePlatformException& e) {
+        LOGE("%s: %s", e.getName().c_str(), e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+}
+
+}
+}
diff --git a/src/Callhistory/JSCallHistory.h b/src/Callhistory/JSCallHistory.h
new file mode 100755 (executable)
index 0000000..957f4f7
--- /dev/null
@@ -0,0 +1,86 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZEN_APIS_JS_CALLHISTORY_H_
+#define TIZEN_APIS_JS_CALLHISTORY_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+class JSCallHistory
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef createJSObject(JSContextRef context, JSObjectRef object);
+private:
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object,
+            JSStringRef propertyName, JSValueRef* exception);
+
+    static bool hasInstance(JSContextRef context, JSObjectRef constructor,
+            JSValueRef possibleInstance, JSValueRef* exception);
+
+
+    static JSValueRef find(JSContextRef context, JSObjectRef object,
+            JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef remove(JSContextRef context, JSObjectRef object,
+            JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeBatch(JSContextRef context, JSObjectRef object,
+            JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeAll(JSContextRef context, JSObjectRef object,
+            JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addChangeListener(JSContextRef context, JSObjectRef object,
+            JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeChangeListener(JSContextRef context, JSObjectRef object,
+            JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSClassDefinition m_classInfo;
+
+    static JSStaticValue m_property[];
+
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+}
+}
+
+#endif
+
diff --git a/src/Callhistory/JSCallHistoryEntry.cpp b/src/Callhistory/JSCallHistoryEntry.cpp
new file mode 100755 (executable)
index 0000000..6fd0a6c
--- /dev/null
@@ -0,0 +1,284 @@
+
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+#include "RemoteParty.h"
+#include "CallHistoryEntry.h"
+#include "JSCallHistoryEntry.h"
+#include "JSRemoteParty.h"
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h> // DeviceAPI::Common
+#include <CommonsJavaScript/Converter.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+JSClassDefinition JSCallHistoryEntry::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "CallHistoryEntry",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    getProperty, //GetProperty,
+    setProperty, //NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSCallHistoryEntry::m_property[] = {
+    {
+        STR_ENTRY_ID,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        STR_CALL_TYPE,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        STR_TAGS,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        STR_REMOTE_PARTIES,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        STR_START_TIME,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        STR_DURATION,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        STR_DIRECTION,
+        getProperty,
+        setProperty,
+        kJSPropertyAttributeNone
+    },
+    {
+        STR_CALLING_PARTY,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSCallHistoryEntry::m_jsClassRef =
+    JSClassCreate(JSCallHistoryEntry::getClassInfo());
+
+const JSClassRef JSCallHistoryEntry::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSCallHistoryEntry::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSCallHistoryEntry::createJSObject(JSContextRef context,
+    CallHistoryEntryPtr callEntryPtr)
+{
+    CallHistoryEntryHolderPtr holder = new CallHistoryEntryHolder(callEntryPtr);
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+}
+
+
+void JSCallHistoryEntry::initialize(JSContextRef context, JSObjectRef object) {
+
+}
+
+void JSCallHistoryEntry::finalize(JSObjectRef object) {
+
+}
+
+JSValueRef JSCallHistoryEntry::RemotePartytoJSValueRef(JSContextRef context,
+    std::vector<RemotePartyPtr> remotePartyList)
+{
+    JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
+    if (NULL == jsResult) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    for (size_t i = 0; i < remotePartyList.size(); i++) {
+        JSValueRef jsObject = JSRemoteParty::createJSObject(context, remotePartyList[i]);
+        if (!jsObject) {
+            throw DeviceAPI::Common::UnknownException("object creation error");
+        }
+        if (!JSSetArrayElement(context, jsResult, i, jsObject)) {
+            throw DeviceAPI::Common::UnknownException("array element set error");
+        }
+    }
+
+    return jsResult;
+}
+
+
+JSValueRef JSCallHistoryEntry::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        CallHistoryEntryHolderPtr priv =
+            static_cast<CallHistoryEntryHolderPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            LOGE("Private object is null");
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        Converter convert(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, STR_ENTRY_ID)) {
+            return JSUtil::toJSValueRef(context, priv->mEntry->getUid());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, STR_CALL_TYPE)) {
+            return JSUtil::toJSValueRef(context, priv->mEntry->getType());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, STR_TAGS)) {
+            return JSUtil::toJSValueRef(context, priv->mEntry->getFeatures());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, STR_REMOTE_PARTIES)) {
+            return JSCallHistoryEntry::RemotePartytoJSValueRef(context,
+                priv->mEntry->getRemoteParties());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, STR_START_TIME)) {
+            return convert.toJSValueRef(priv->mEntry->getStartTime());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, STR_DURATION)) {
+            return JSUtil::toJSValueRef(context, priv->mEntry->getDuration());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, STR_DIRECTION)) {
+            return JSUtil::toJSValueRef(context, priv->mEntry->getDirection());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, STR_CALLING_PARTY)) {
+            std::string callingParty = priv->mEntry->getCallingParty();
+            if (callingParty.empty()) {
+                return JSValueMakeNull(context);
+            }
+            return JSUtil::toJSValueRef(context, callingParty);
+        }
+
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    return NULL;
+}
+
+
+CallHistoryEntryPtr JSCallHistoryEntry::toCallHistoryEntry(JSContextRef context,
+    JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Not CallHistory Entry");
+        throw TypeMismatchException("Not CallHistory Entry");
+    }
+
+    JSObjectRef object = JSValueToObject(context, value, NULL);
+    if (!object) {
+        LOGE("object is NULL");
+        throw UnknownException("Unknown Exception");
+    }
+
+    CallHistoryEntryHolderPtr holder =
+        static_cast<CallHistoryEntryHolderPtr>(JSObjectGetPrivate(object));
+    if (!holder) {
+        LOGE("Private object is NULL");
+        throw TypeMismatchException("Private object is NULL.");
+     }
+
+    return holder->mEntry;
+}
+
+bool JSCallHistoryEntry::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    try {
+        CallHistoryEntryHolderPtr priv =
+            static_cast<CallHistoryEntryHolderPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, STR_DIRECTION)) {
+
+            std::string privDirection = priv->mEntry->getDirection();
+            std::string changedDirection = JSUtil::JSValueToString(context,value);
+
+            if ((privDirection.compare(STR_DIRECTION_MISSED_NEW)==0) &&
+                (changedDirection.compare(STR_DIRECTION_MISSED)==0)) {
+                priv->mEntry->setDirection(changedDirection);
+                CallHistoryEntry::setMissedDirection(priv->mEntry->getUid());
+                return true;
+            }
+            else{
+                return true;
+            }
+        }
+
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    return false;
+}
+
+
+
+} // Callhistory
+} // DeviceAPI
diff --git a/src/Callhistory/JSCallHistoryEntry.h b/src/Callhistory/JSCallHistoryEntry.h
new file mode 100755 (executable)
index 0000000..ee47c21
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_CALL_HISTORY_ENTRY_H__
+#define __TIZEN_JS_CALL_HISTORY_ENTRY_H__
+
+#define STR_DIRECTION_MISSED_NEW            "MISSEDNEW"
+#define STR_DIRECTION_MISSED            "MISSED"
+
+
+#include <JavaScriptCore/JavaScript.h>
+#include <JSUtil.h>
+
+#include "CallHistoryEntry.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+
+class CallHistoryEntryHolder
+{
+public:
+    CallHistoryEntryHolder(CallHistoryEntryPtr entry) {mEntry = entry;}
+    CallHistoryEntryPtr mEntry;
+};
+
+typedef CallHistoryEntryHolder* CallHistoryEntryHolderPtr;
+
+
+
+class JSCallHistoryEntry
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, CallHistoryEntryPtr callEntryPtr);
+
+    static CallHistoryEntryPtr toCallHistoryEntry(JSContextRef context, JSValueRef value);
+
+
+private:
+
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef RemotePartytoJSValueRef(JSContextRef context, std::vector<RemotePartyPtr> remotePartyList);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Callhistory
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Callhistory/JSRemoteParty.cpp b/src/Callhistory/JSRemoteParty.cpp
new file mode 100755 (executable)
index 0000000..768ba0c
--- /dev/null
@@ -0,0 +1,149 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+#include "RemoteParty.h"
+#include "JSRemoteParty.h"
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+JSClassDefinition JSRemoteParty::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "RemoteParty",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    getProperty, //GetProperty,
+    setProperty, // NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSRemoteParty::m_property[] = {
+    {
+        STR_REMOTE_PARTY,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    {
+        STR_PERSIONID,
+        getProperty,
+        NULL,
+        kJSPropertyAttributeReadOnly
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSRemoteParty::m_jsClassRef =
+    JSClassCreate(JSRemoteParty::getClassInfo());
+
+const JSClassRef JSRemoteParty::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSRemoteParty::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSRemoteParty::createJSObject(JSContextRef context,
+    RemotePartyPtr remoteParty)
+{
+    RemotePartyHolderPtr holder = new RemotePartyHolder(remoteParty);
+    return JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+
+}
+
+void JSRemoteParty::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSRemoteParty::finalize(JSObjectRef object)
+{
+
+}
+
+
+
+JSValueRef JSRemoteParty::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+
+        RemotePartyHolderPtr priv =
+            static_cast<RemotePartyHolderPtr>(JSObjectGetPrivate(object));
+        if (!priv) {
+            LOGE("Private object is NULL");
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, STR_REMOTE_PARTY)) {
+            return JSUtil::toJSValueRef(context, priv->mRemote->getRemoteParty());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, STR_PERSIONID)) {
+            return JSUtil::toJSValueRef(context, priv->mRemote->getPersonId());
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return NULL;
+}
+
+
+bool JSRemoteParty::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    return false;
+}
+
+
+} // Callhistory
+} // DeviceAPI
diff --git a/src/Callhistory/JSRemoteParty.h b/src/Callhistory/JSRemoteParty.h
new file mode 100755 (executable)
index 0000000..2a4114e
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_REMOTE_PARTY_H__
+#define __TIZEN_JS_REMOTE_PARTY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "RemoteParty.h"
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+class RemotePartyHolder
+{
+public:
+    RemotePartyHolder(RemotePartyPtr remote) {mRemote = remote;}
+    RemotePartyPtr mRemote;
+};
+
+typedef RemotePartyHolder* RemotePartyHolderPtr;
+
+
+
+class JSRemoteParty
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, RemotePartyPtr remoteParty);
+
+private:
+
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Callhistory
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Callhistory/RemoteParty.cpp b/src/Callhistory/RemoteParty.cpp
new file mode 100755 (executable)
index 0000000..09b8169
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "RemoteParty.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+RemoteParty::RemoteParty():
+    m_remoteParty(""), m_personId("")
+{
+}
+
+RemoteParty::~RemoteParty()
+{
+}
+
+std::string RemoteParty::getRemoteParty() const
+{
+    return m_remoteParty;
+}
+
+void RemoteParty::setRemoteParty(std::string remoteParty)
+{
+    m_remoteParty = remoteParty;
+}
+
+std::string RemoteParty::getPersonId() const
+{
+    return m_personId;
+}
+
+void RemoteParty::setPersonId(std::string personId)
+{
+    m_personId = personId;
+}
+
+
+} // Callhistory
+} // DeviceAPI
diff --git a/src/Callhistory/RemoteParty.h b/src/Callhistory/RemoteParty.h
new file mode 100755 (executable)
index 0000000..6755023
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_REMOTE_PARTY_H__
+#define __TIZEN_REMOTE_PARTY_H__
+
+#include <string>
+#include <memory>
+#include "CallHistoryTypes.h"
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+class RemoteParty
+{
+public:
+    RemoteParty();
+    virtual ~RemoteParty();
+
+    std::string getRemoteParty() const;
+    void setRemoteParty(std::string remoteParty);
+
+    std::string getPersonId() const;
+    void setPersonId(std::string personId);
+
+private:
+    std::string m_remoteParty;
+    std::string m_personId;
+    //PersonId m_personId;
+};
+
+//typedef RemoteParty* RemotePartyPtr;
+typedef std::shared_ptr<RemoteParty> RemotePartyPtr;
+
+
+} // Callhistory
+} // DeviceAPI
+
+#endif // __TIZEN_REMOTE_PARTY_H__
diff --git a/src/Callhistory/config.xml b/src/Callhistory/config.xml
new file mode 100755 (executable)
index 0000000..3aff3ca
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-callhistory.so</library-name>
+    <feature-install-uri>callhistory.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/callhistory.read</name>
+        <device-capability>callhistory.read</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/callhistory.write</name>
+        <device-capability>callhistory.write</device-capability>
+    </api-feature>
+</plugin-properties>
+
diff --git a/src/Callhistory/plugin_config.cpp b/src/Callhistory/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..e78dd3c
--- /dev/null
@@ -0,0 +1,122 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <map>
+#include <utility>
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include "plugin_config.h"
+
+#define CALL_HISTORY_FEATURE_API_READ "http://tizen.org/privilege/callhistory.read"
+#define CALL_HISTORY_FEATURE_API_WRITE "http://tizen.org/privilege/callhistory.write"
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+const char* CALL_HISTORY_DEVICE_CAP_READ = "callhistory.read";
+const char* CALL_HISTORY_DEVICE_CAP_WRITE = "callhistory.write";
+
+static WrtDeviceApis::Commons::FunctionMapping createCallHistoryFunctions();
+
+static WrtDeviceApis::Commons::FunctionMapping CallHistoryFunctions = createCallHistoryFunctions();
+
+#pragma GCC visibility push(default)
+DEFINE_FUNCTION_GETTER(CallHistory, CallHistoryFunctions);
+#pragma GCC visibility pop
+
+static WrtDeviceApis::Commons::FunctionMapping createCallHistoryFunctions()
+{
+    using namespace WrtDeviceApis::Commons;
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_CALL_HISTORY_READ, CALL_HISTORY_DEVICE_CAP_READ);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_CALL_HISTORY_WRITE, CALL_HISTORY_DEVICE_CAP_WRITE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_CALL_HISTORY_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_CALL_HISTORY_READ, DEVICE_CAP_CALL_HISTORY_READ);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_CALL_HISTORY_WRITE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_CALL_HISTORY_WRITE, DEVICE_CAP_CALL_HISTORY_WRITE);
+
+    ACE_CREATE_FEATURE(FEATURE_CALL_HISTORY_READ, CALL_HISTORY_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_CALL_HISTORY_WRITE, CALL_HISTORY_FEATURE_API_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(CALL_FEATURES_CALL_HISTORY_READ);
+    ACE_ADD_API_FEATURE(CALL_FEATURES_CALL_HISTORY_READ, FEATURE_CALL_HISTORY_READ);
+
+    ACE_CREATE_FEATURE_LIST(CALL_FEATURES_CALL_HISTORY_WRITE);
+    ACE_ADD_API_FEATURE(CALL_FEATURES_CALL_HISTORY_WRITE, FEATURE_CALL_HISTORY_WRITE);
+
+    FunctionMapping CallHistoryMapping;
+
+    AceFunction findFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_FIND,
+            CALL_HISTORY_FUNCTION_API_FIND,
+            CALL_FEATURES_CALL_HISTORY_READ,
+            EMPTY_DEVICE_LIST);
+
+    CallHistoryMapping.insert(std::make_pair(CALL_HISTORY_FUNCTION_API_FIND, findFunc));
+
+    AceFunction removeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE,
+            CALL_HISTORY_FUNCTION_API_REMOVE,
+            CALL_FEATURES_CALL_HISTORY_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    CallHistoryMapping.insert(std::make_pair(CALL_HISTORY_FUNCTION_API_REMOVE, removeFunc));
+
+    AceFunction removeBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_BATCH,
+            CALL_HISTORY_FUNCTION_API_REMOVE_BATCH,
+            CALL_FEATURES_CALL_HISTORY_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    CallHistoryMapping.insert(std::make_pair(CALL_HISTORY_FUNCTION_API_REMOVE_BATCH, removeBatchFunc));
+
+    AceFunction removeAllFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_ALL,
+            CALL_HISTORY_FUNCTION_API_REMOVE_ALL,
+            CALL_FEATURES_CALL_HISTORY_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    CallHistoryMapping.insert(std::make_pair(CALL_HISTORY_FUNCTION_API_REMOVE_ALL, removeAllFunc));
+
+    AceFunction addListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD_LISTENER,
+            CALL_HISTORY_FUNCTION_API_ADDLISTENER,
+            CALL_FEATURES_CALL_HISTORY_READ,
+            EMPTY_DEVICE_LIST);
+
+    CallHistoryMapping.insert(std::make_pair(CALL_HISTORY_FUNCTION_API_ADDLISTENER, addListenerFunc));
+
+    AceFunction removeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_LISTENER,
+            CALL_HISTORY_FUNCTION_API_REMOVELISTENER,
+            CALL_FEATURES_CALL_HISTORY_READ,
+            EMPTY_DEVICE_LIST);
+
+    CallHistoryMapping.insert(std::make_pair(CALL_HISTORY_FUNCTION_API_REMOVELISTENER, removeListenerFunc));
+
+    return CallHistoryMapping;
+}
+
+}
+}
diff --git a/src/Callhistory/plugin_config.h b/src/Callhistory/plugin_config.h
new file mode 100755 (executable)
index 0000000..b10b48c
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _CALLHISTORY_PLUGIN_CONFIG_H_
+#define _CALLHISTORY_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+DECLARE_FUNCTION_GETTER(CallHistory);
+
+#define CALLHISTORY_CHECK_ACCESS(functionName) \
+    WrtDeviceApis::Commons::aceCheckAccess<AceFunctionGetter, \
+    WrtDeviceApis::Commons::DefaultArgsVerifier<> >(                \
+        getCallHistoryFunctionData,         \
+        functionName)
+
+}
+}
+
+#endif
diff --git a/src/Callhistory/plugin_config_impl.h b/src/Callhistory/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..d4670aa
--- /dev/null
@@ -0,0 +1,31 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _CALLHISTORY_PLUGIN_CONFIG_IMPL_H_
+#define _CALLHISTORY_PLUGIN_CONFIG_IMPL_H_
+
+#define CALL_HISTORY_FUNCTION_API_FIND "find"
+#define CALL_HISTORY_FUNCTION_API_REMOVE "remove"
+#define CALL_HISTORY_FUNCTION_API_REMOVE_BATCH "removeBatch"
+#define CALL_HISTORY_FUNCTION_API_REMOVE_ALL "removeAll"
+#define CALL_HISTORY_FUNCTION_API_ADDLISTENER "addListener"
+#define CALL_HISTORY_FUNCTION_API_REMOVELISTENER "removeListener"
+
+#define TIZEN_CALLHISTORY_CALLHISTORY_CLASS "callhistory"
+
+#endif // _CALLHISTORY_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/Callhistory/plugin_initializer.cpp b/src/Callhistory/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..10938cc
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CallHistory.h"
+#include "JSCallHistory.h"
+
+#include "plugin_config.h"
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+
+namespace DeviceAPI {
+namespace CallHistory {
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+AceSecurityStatus callhistoryAceCheckAccessFunction(const char* functionName)
+{
+    return CALLHISTORY_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerCallhistorySetter,
+                                CallHistory,
+                                gSecurityAccessor);
+
+class_definition_options_t option =
+{
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerCallhistorySetter,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId) {
+    LOGD("[Tizen\\callhistory] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch(...) {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, callhistoryAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId) {
+    LOGD("[Tizen\\callhistory] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "CallHistory";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch(...) {
+    LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\callhistory] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\callhistory] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CALLHISTORY_CALLHISTORY_CLASS,
+        (js_class_template_getter)DeviceAPI::CallHistory::JSCallHistory::getClassRef,
+        &option)
+PLUGIN_CLASS_MAP_END
+
+} // CallHistory
+} // DeviceAPI
diff --git a/src/Common/ArgumentValidator.cpp b/src/Common/ArgumentValidator.cpp
new file mode 100755 (executable)
index 0000000..6a9f1c4
--- /dev/null
@@ -0,0 +1,314 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "ArgumentValidator.h"
+#include "PlatformException.h"
+#include "JSUtil.h"
+
+#include <limits>
+#include <dlog.h>
+#include <math.h>
+#include <stdarg.h>
+
+using namespace std;
+
+namespace DeviceAPI {
+namespace Common{
+
+ArgumentValidator::ArgumentValidator(JSContextRef ctx, int argc, const JSValueRef* argv):mContext(ctx),mArgc(argc), mArgv(argv){
+}
+
+ArgumentValidator::~ArgumentValidator(){
+}
+
+JSValueRef ArgumentValidator::getArgument(int index, bool nullable) const{
+    if( index < mArgc ){
+        return mArgv[index];
+    }
+
+    JSValueRef value = NULL;
+    if( nullable )
+        value = JSValueMakeNull(mContext);
+    else
+        value = JSValueMakeUndefined(mContext);
+    return value;
+}
+
+bool ArgumentValidator::isOmitted(int index){
+    if( index < mArgc)
+        return false;
+    return true;
+}
+bool ArgumentValidator::isNull(int index){
+    if( !isOmitted(index) && JSValueIsNull(mContext, mArgv[index]) ){
+        return true;
+    }
+    return false;
+}
+bool ArgumentValidator::isUndefined(int index){
+    if( !isOmitted(index) && JSValueIsUndefined(mContext, mArgv[index]) ){
+        return true;
+    }
+    return false;
+}
+
+double ArgumentValidator::toNumber(int index, bool nullable, double defaultvalue) const{
+    JSValueRef value = getArgument(index, nullable);
+    if( JSValueIsNull(mContext, value) && nullable){
+        return defaultvalue;
+    }
+    return JSUtil::JSValueToNumber(mContext, value);
+}
+
+long ArgumentValidator::toLong(int index, bool nullable, long defaultvalue) const{
+    return static_cast<long>(toLongLong(index,nullable,defaultvalue));
+}
+
+signed char ArgumentValidator::toByte(int index, bool nullable, signed char defaultvalue) const{
+    return static_cast<signed char>(toLong(index,nullable,defaultvalue));
+}
+
+unsigned char ArgumentValidator::toOctet(int index, bool nullable, unsigned char defaultvalue) const{
+    return static_cast<unsigned char>(toULong(index,nullable,defaultvalue));
+}
+
+unsigned long ArgumentValidator::toULong(int index, bool nullable, unsigned long defaultvalue) const{
+    return static_cast<unsigned long>(toLongLong(index,nullable,defaultvalue));
+}
+
+long long ArgumentValidator::toLongLong(int index, bool nullable, long long defaultvalue) const{
+    double double_value = toNumber(index,nullable,defaultvalue);
+    if(isnan(double_value)) {
+        double_value = 0.0;
+    }
+    return static_cast<long long>(double_value);
+}
+
+unsigned long long ArgumentValidator::toULongLong(int index, bool nullable, unsigned long long defaultvalue) const{
+    return static_cast<unsigned long long>(toLongLong(index,nullable,defaultvalue));
+}
+
+double ArgumentValidator::toDouble(int index, bool nullable, double defaultvalue) const{
+    JSValueRef value = getArgument(index, nullable);
+    if( JSValueIsNull(mContext, value) && nullable){
+        return defaultvalue;
+    }
+    return JSUtil::JSValueToDouble(mContext, value);
+}
+
+std::string ArgumentValidator::toString(int index, bool nullable, const  string & defaultvalue) const{
+    JSValueRef value = getArgument(index, nullable);
+    if( JSValueIsNull(mContext, value) && nullable){
+        return defaultvalue;
+    }
+
+    std::string result;
+
+    JSValueRef exception = NULL;
+    JSStringRef str = JSValueToStringCopy(mContext, value, &exception);
+    if (exception != NULL) {
+        throw TypeMismatchException(mContext, exception);
+    }
+    size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
+    {
+        char buffer[jsSize];
+        JSStringGetUTF8CString(str, buffer, jsSize);
+        result = buffer;
+    }
+    JSStringRelease(str);
+    return result;
+}
+
+bool ArgumentValidator::toBool(int index, bool nullable, bool defaultvalue) const{
+    JSValueRef value = getArgument(index, nullable);
+    if( JSValueIsNull(mContext, value) && nullable){
+        return defaultvalue;
+    }
+    bool boolvalue = JSValueToBoolean(mContext, value);
+    return boolvalue;
+}
+
+time_t ArgumentValidator::toTimeT(int index, bool nullable, time_t defaultvalue) const{
+    JSValueRef value = getArgument(index, nullable);
+    if( JSValueIsNull(mContext, value) && nullable){
+        return defaultvalue;
+    }
+    return JSUtil::JSValueToTimeT(mContext, value);
+}
+
+JSObjectRef ArgumentValidator::toObject(int index, bool nullable) const{
+    JSValueRef value = getArgument(index, nullable);
+    if( JSValueIsNull(mContext, value) && nullable){
+        return NULL;
+    }
+    if( !JSValueIsObject(mContext, value) ){
+        throw TypeMismatchException("Value is not Object");
+    }
+
+    JSValueRef exception = NULL;
+    JSObjectRef object = JSValueToObject(mContext, value, &exception);
+    if( exception ){
+        throw TypeMismatchException(mContext, exception);
+    }
+    return object;
+}
+
+JSObjectRef ArgumentValidator::toObject(int index, JSClassRef info, bool nullable) const{
+    JSObjectRef obj = toObject(index, nullable);
+    if( obj == NULL )
+        return NULL;
+    if( !JSValueIsObjectOfClass( mContext, obj, info) ){
+        throw TypeMismatchException("Value is not correct type");
+    }
+    return obj;
+}
+
+JSValueRef ArgumentValidator::toJSValueRef(int index, bool nullable) const{
+    return getArgument(index, nullable);
+}
+
+JSObjectRef ArgumentValidator::toFunction(int index, bool nullable) const{
+    JSObjectRef obj = toObject(index, nullable);
+    if( obj == NULL && nullable){
+        return NULL;
+    }
+    if( !JSObjectIsFunction( mContext, obj )){
+        throw TypeMismatchException("Value is not function");
+    }
+    return obj;
+}
+
+JSObjectRef ArgumentValidator::toArrayObject(int index, bool nullable) const{
+    JSValueRef value = getArgument(index, nullable);
+    if( JSValueIsNull(mContext, value) && nullable){
+        return NULL;
+    }
+
+    if( !JSIsArrayValue(mContext, value)){
+        throw TypeMismatchException("Type is not Array");
+    }
+
+    JSValueRef exception = NULL;
+    JSObjectRef obj = JSValueToObject(mContext, value, &exception);
+    if( exception != NULL )
+        throw TypeMismatchException(mContext, exception);
+    return obj;
+}
+
+
+std::vector<std::string> ArgumentValidator::toStringVector(int index, bool nullable) const{
+    JSObjectRef value = toArrayObject(index, nullable);
+    if( value == NULL || JSValueIsNull(mContext, value) ){
+        return std::vector<std::string>();
+    }
+    return JSUtil::JSArrayToStringVector(mContext, value);
+}
+
+std::vector<long> ArgumentValidator::toLongVector(int index, bool nullable) const{
+    JSObjectRef value = toArrayObject(index, nullable);
+    if( value == NULL || JSValueIsNull(mContext, value) ){
+        return std::vector<long>();
+    }
+    return JSUtil::JSArrayToLongVector(mContext, value);
+}
+
+
+std::vector<double> ArgumentValidator::toDoubleVector(int index, bool nullable) const{
+    JSObjectRef value = toArrayObject(index, nullable);
+    if( value == NULL || JSValueIsNull(mContext, value) ){
+        return std::vector<double>();
+    }
+    return JSUtil::JSArrayToDoubleVector(mContext, value);
+}
+
+std::vector<time_t> ArgumentValidator::toTimeTVector(int index, bool nullable) const{
+    JSObjectRef value = toArrayObject(index, nullable);
+    if( value == NULL || JSValueIsNull(mContext, value) ){
+        return std::vector<time_t>();
+    }
+    return JSUtil::JSArrayToTimeTVector(mContext, value);
+}
+
+std::vector<bool> ArgumentValidator::toBoolVector(int index, bool nullable) const{
+    JSObjectRef value = toArrayObject(index, nullable);
+    if( value == NULL || JSValueIsNull(mContext, value) ){
+        return std::vector<bool>();
+    }
+    return JSUtil::JSArrayToBoolVector(mContext, value);
+}
+
+std::vector<unsigned char> ArgumentValidator::toUCharVector(int index, bool nullable) const{
+    JSObjectRef value = toArrayObject(index, nullable);
+    if( value == NULL || JSValueIsNull(mContext, value) ){
+        return std::vector<unsigned char>();
+    }
+    return JSUtil::JSArrayToUCharVector(mContext, value);
+}
+
+std::vector<JSValueRef> ArgumentValidator::toJSValueRefVector(int index, bool nullable) const{
+    JSObjectRef value = toArrayObject(index, nullable);
+    if( value == NULL || JSValueIsNull(mContext, value) ){
+        return std::vector<JSValueRef>();
+    }
+
+    std::vector<JSValueRef> result;
+    for (std::size_t i = 0; i < JSGetArrayLength(mContext, value); ++i) {
+        JSValueRef element = JSGetArrayElement(mContext, value, i);
+        result.push_back(element);
+    }
+    return result;
+}
+
+std::map<std::string, std::string> ArgumentValidator::toStringMap(int index, bool nullable) const{
+    JSObjectRef value = toObject(index, nullable);
+    if( value == NULL || JSValueIsNull(mContext, value) ){
+        return std::map<std::string, std::string>();
+    }
+
+    return JSUtil::JSValueToStringMap(mContext, value);
+}
+
+JSObjectRef ArgumentValidator::toCallbackObject(int index, bool nullable, const char *callback, ...) const{
+    JSObjectRef obj = toObject(index, nullable);
+    if( obj == NULL && nullable){
+        return NULL;
+    }
+    va_list var_args;
+    va_start (var_args, callback);
+    const char * check = callback;
+    while( check != NULL ){
+        JSStringRef propertyName = JSStringCreateWithUTF8CString(check);
+        bool has = JSObjectHasProperty(mContext, obj, propertyName);
+        JSStringRelease(propertyName);
+        if( has ){
+            JSObjectRef o = JSUtil::JSValueToObject(mContext, JSUtil::getProperty(mContext, obj, check));
+            if( !JSObjectIsFunction(mContext, o) ){
+                va_end(var_args);
+                throw TypeMismatchException("Property is not function object");
+            }
+        }
+        check = static_cast<const char *>(va_arg(var_args, const char *));
+    }
+    va_end(var_args);
+    return obj;
+}
+
+
+
+}
+}
diff --git a/src/Common/ArgumentValidator.h b/src/Common/ArgumentValidator.h
new file mode 100755 (executable)
index 0000000..4f63d8b
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _ARGUMENT_VALIDATOR_H_
+#define _ARGUMENT_VALIDATOR_H_
+
+#include <string>
+#include <vector>
+#include <map>
+#include <JavaScriptCore/JavaScript.h>
+#include <ctime>
+
+namespace DeviceAPI {
+namespace Common{
+
+class ArgumentValidator{
+public:
+    ArgumentValidator(JSContextRef ctx, int argc, const JSValueRef* argv);
+    ~ArgumentValidator();
+
+    double toNumber(int index, bool nullable = false, double defaultvalue = 0.0) const;
+    long toLong(int index, bool nullable = false, long defaultvalue = 0) const;
+    unsigned long toULong(int index, bool nullable = false, unsigned long defaultvalue = 0) const;
+    long long toLongLong(int index, bool nullable = false, long long defaultvalue = 0) const;
+    unsigned long long toULongLong(int index, bool nullable = false, unsigned long long defaultvalue = 0) const;
+    double toDouble(int index, bool nullable = false, double defaultvalue = 0.0) const;
+    signed char toByte(int index, bool nullable = false, signed char defaultvalue = 0) const;
+    unsigned char toOctet(int index, bool nullable = false, unsigned char defaultvalue = 0) const;
+    std::string toString(int index, bool nullable = false, const std::string& defaultvalue = "") const;
+    bool toBool(int index, bool nullable = false, bool defaultvalue = false) const;
+    time_t toTimeT(int index, bool nullable = false, time_t defaultvalue = 0) const;
+    JSObjectRef toObject(int index, bool nullable = false) const;
+    JSObjectRef toObject(int index, JSClassRef info, bool nullable = false) const;
+    JSObjectRef toFunction(int index, bool nullable = false) const;
+    JSObjectRef toArrayObject(int index, bool nullable = false) const;
+    JSValueRef toJSValueRef(int index, bool nullable = false) const;
+
+    bool isOmitted(int index);
+    bool isNull(int index);
+    bool isUndefined(int index);
+
+    JSObjectRef toCallbackObject(int index, bool nullable, const char *callback, ...) const;
+
+    std::vector<std::string> toStringVector(int index, bool nullable = false) const;
+    std::vector<long> toLongVector(int index, bool nullable = false) const;
+    std::vector<double> toDoubleVector(int index, bool nullable = false) const;
+    std::vector<time_t> toTimeTVector(int index, bool nullable = false) const;
+    std::vector<bool> toBoolVector(int index, bool nullable = false) const;
+    std::vector<unsigned char> toUCharVector(int index, bool nullable = false) const;
+    std::vector<JSValueRef> toJSValueRefVector(int index, bool nullable= false) const;
+
+    std::map<std::string, std::string> toStringMap(int index, bool nullable = false) const;
+
+private:
+    JSValueRef getArgument(int index, bool nullable) const;
+    JSContextRef mContext;
+    int mArgc;
+    const JSValueRef* mArgv;
+
+};
+
+}
+}
+
+#endif //_ARGUMENT_VALIDATOR_H_
+
+
diff --git a/src/Common/AsyncCallbackManager.cpp b/src/Common/AsyncCallbackManager.cpp
new file mode 100644 (file)
index 0000000..6cb3588
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AsyncCallbackManager.h"
+#include "Logger.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+AsyncCallbackManager::AsyncCallbackManager()
+{
+}
+
+AsyncCallbackManager::~AsyncCallbackManager()
+{
+    m_map.clear();
+}
+
+void AsyncCallbackManager::registerCallbackManager(
+        WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr &cbm,
+        const JSContextRef context)
+{
+    LOGD("Registering an callback manager on context: %p", context);
+    m_map.insert(JSCallbackManagerPair(cbm, context));
+}
+
+void AsyncCallbackManager::unregisterContext(const JSContextRef context)
+{
+    LOGD("Unregistering all callback managers on context: %p", context);
+    for(JSCallbackManagerMapIter it = m_map.begin(); it != m_map.end(); it++) {
+        if(context == it->second) {
+            LOGD("Unregister a callback manager");
+            it->first->setOnSuccess(NULL);
+            it->first->setOnError(NULL);
+            // This function does not remove cbm from multimap.
+            // It only prohibit plugin invoke javascript callback.
+        }
+    }
+}
+
+void AsyncCallbackManager::unregisterCallbackManager(
+        const WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr &cbm)
+{
+    LOGD("Unregistering an callback manager");
+    JSCallbackManagerMapIter it = m_map.find(cbm);
+    if(it == m_map.end()) {
+        LOGW("Callback manager not found - nothing to unregister");
+        return;
+    }
+
+    m_map.erase(it);
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/AsyncCallbackManager.h b/src/Common/AsyncCallbackManager.h
new file mode 100644 (file)
index 0000000..d81b3af
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        AsyncCallbackManager.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef __TIZEN_COMMON_ASYNC_CALLBACK_MANAGER_H__
+#define __TIZEN_COMMON_ASYNC_CALLBACK_MANAGER_H__
+
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include "Singleton.h"
+#include "Export.h"
+#include "Logger.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+class AsyncCallbackManager
+{
+public:
+    typedef std::map<WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr,
+            JSContextRef> JSCallbackManagerMap;
+    typedef typename JSCallbackManagerMap::iterator JSCallbackManagerMapIter;
+    typedef std::pair<WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr,
+            JSContextRef> JSCallbackManagerPair;
+
+    AsyncCallbackManager();
+    virtual ~AsyncCallbackManager();
+
+    virtual void registerCallbackManager(
+            WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr &cbm,
+            const JSContextRef context);
+
+    virtual void unregisterContext(const JSContextRef context);
+    virtual void unregisterCallbackManager(const WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr &cbm);
+
+private:
+    JSCallbackManagerMap m_map;
+};
+
+} // Common
+} // DeviceAPI
+
+#endif // __TIZEN_COMMON_ASYNC_CALLBACK_MANAGER_H__
diff --git a/src/Common/CMakeLists.txt b/src/Common/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..7a96a12
--- /dev/null
@@ -0,0 +1,32 @@
+SET(SRCS
+  AsyncCallbackManager.cpp
+  CallbackUserData.cpp
+  GlobalContextManager.cpp
+  ArgumentValidator.cpp
+  JSUtil.cpp
+  PlatformException.cpp
+  MultiCallbackUserData.cpp
+  JSStringRefWrapper.cpp
+  JSWebAPIErrorFactory.cpp
+  JSWebAPIError.cpp
+  JSWebAPIException.cpp
+  WebAPIError.cpp
+  PropertyBag.cpp
+  JSArray.cpp
+  SecurityAccessor.cpp
+  JSTizenSecurityObject.cpp
+  WebKitProxy.cpp
+  DBusOperation.cpp
+)
+
+ADD_LIBRARY(${COMMON_TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${COMMON_TARGET_NAME}
+       ${LIBS_COMMON}
+)
+
+INSTALL(TARGETS ${COMMON_TARGET_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${COMMON_DESTINATION_NAME})
+INSTALL(
+       DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/common
+       FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Common/CallbackUserData.cpp b/src/Common/CallbackUserData.cpp
new file mode 100644 (file)
index 0000000..7d41f0d
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CallbackUserData.h"
+#include "MultiCallbackUserData.h"
+#include <stdarg.h>
+
+namespace DeviceAPI {
+namespace Common {
+
+namespace {
+const char* CALLBACK_SUCCESS = "success";
+const char* CALLBACK_ERROR = "error";
+} //anonymous namespace
+
+CallbackUserData::CallbackUserData(JSContextRef global_ctx):
+        m_context(global_ctx),
+        m_impl(new MultiCallbackUserData(global_ctx)),
+        m_is_act(true)
+{
+}
+
+CallbackUserData::~CallbackUserData()
+{
+    delete m_impl;
+}
+
+void CallbackUserData::setSuccessCallback(JSValueRef on_success)
+{
+    if(on_success && JSValueIsObject(m_context, on_success)) {
+        JSObjectRef success = JSValueToObject(m_context, on_success, NULL);
+        m_impl->setCallback(CALLBACK_SUCCESS, success);
+    }
+}
+
+void CallbackUserData::setErrorCallback(JSValueRef on_error)
+{
+    if(on_error && JSValueIsObject(m_context, on_error)) {
+        JSObjectRef error = JSValueToObject(m_context, on_error, NULL);
+        m_impl->setCallback(CALLBACK_ERROR, error);
+    }
+}
+
+void CallbackUserData::callSuccessCallback(int count, JSValueRef obj[])
+{
+    if(!m_is_act) {
+        return;
+    }
+
+    m_impl->invokeCallback(CALLBACK_SUCCESS, count, obj);
+}
+
+void CallbackUserData::callSuccessCallback(JSValueRef obj)
+{
+    JSValueRef args[1] = {obj};
+    callSuccessCallback(1, args);
+}
+
+void CallbackUserData::callSuccessCallback()
+{
+    callSuccessCallback(0, NULL);
+}
+
+void CallbackUserData::callErrorCallback(int count, JSValueRef obj[])
+{
+    if(!m_is_act) {
+        return;
+    }
+
+    m_impl->invokeCallback(CALLBACK_ERROR, count, obj);
+}
+
+void CallbackUserData::callErrorCallback(JSValueRef obj)
+{
+    JSValueRef args[1] = {obj};
+    callErrorCallback(1, args);
+}
+
+void CallbackUserData::callErrorCallback()
+{
+    callErrorCallback(0, NULL);
+}
+
+JSContextRef CallbackUserData::getContext()
+{
+    return m_context;
+}
+
+void CallbackUserData::setActive(bool act)
+{
+    m_is_act = act;
+}
+
+bool CallbackUserData::isActive() const
+{
+    return m_is_act;
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/CallbackUserData.h b/src/Common/CallbackUserData.h
new file mode 100644 (file)
index 0000000..1c1d1bf
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_COMMON_CALLBACK_USER_DATA_H__
+#define __TIZEN_COMMON_CALLBACK_USER_DATA_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Common {
+
+class MultiCallbackUserData;
+
+class CallbackUserData {
+public:
+    CallbackUserData(JSContextRef global_ctx);
+    virtual ~CallbackUserData();
+
+    JSContextRef getContext();
+    void setSuccessCallback(JSValueRef on_success);
+    void setErrorCallback(JSValueRef on_error);
+
+    void callSuccessCallback();
+    void callSuccessCallback(JSValueRef obj);
+    void callSuccessCallback(int count, JSValueRef obj[]);
+
+    void callErrorCallback();
+    void callErrorCallback(JSValueRef obj);
+    void callErrorCallback(int count, JSValueRef obj[]);
+
+    void setActive(bool act);
+    bool isActive() const;
+private:
+    JSContextRef m_context;
+    MultiCallbackUserData* m_impl;
+    bool m_is_act;
+};
+
+} // Common
+} // DeviceAPI
+
+#endif //__TIZEN_COMMON_CALLBACK_USER_DATA_H__
+
diff --git a/src/Common/DBusOperation.cpp b/src/Common/DBusOperation.cpp
new file mode 100755 (executable)
index 0000000..4cefcfa
--- /dev/null
@@ -0,0 +1,381 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "DBusOperation.h"
+
+#include <dbus/dbus.h>
+#include <string>
+#include <sstream>
+#include <vector>
+#include <set>
+#include <dbus/dbus-glib-lowlevel.h>
+#include "Logger.h"
+#include "PlatformException.h"
+
+#define DBUS_REPLY_TIMEOUT (-1)
+
+namespace DeviceAPI {
+namespace Common {
+
+DBusOperationArguments::DBusOperationArguments()
+{
+}
+
+DBusOperationArguments::~DBusOperationArguments()
+{
+    Arguments::iterator iter;
+    for (iter = m_arguments.begin(); iter != m_arguments.end(); iter++)
+    {
+        ArgType type = iter->first;
+        void *pVal = iter->second;
+
+        switch (type)
+        {
+        case ArgType::TYPE_BOOL:
+        case ArgType::TYPE_INT32:
+            delete static_cast<int32_t *>(pVal);
+            break;
+        case ArgType::TYPE_UINT32:
+            delete static_cast<uint32_t *>(pVal);
+            break;
+        case ArgType::TYPE_UINT64:
+            delete static_cast<uint64_t *>(pVal);
+            break;
+        case ArgType::TYPE_STRING:
+            delete[] static_cast<char *>(pVal);
+            break;
+        default:
+            LoggerE("invalid type");
+            break;
+        }
+    }
+
+    m_arguments.clear();
+}
+
+void DBusOperationArguments::addArgumentBool(bool val)
+{
+    int32_t *pVal = new int32_t;
+    *pVal = val;
+
+    ArgumentElement element = ArgumentElement(ArgType::TYPE_BOOL, static_cast<void *>(pVal));
+
+    m_arguments.push_back(element);
+}
+
+void DBusOperationArguments::addArgumentInt32(int val)
+{
+    int32_t *pVal = new int32_t;
+    *pVal = val;
+
+    ArgumentElement element = ArgumentElement(ArgType::TYPE_INT32, static_cast<void *>(pVal));
+
+    m_arguments.push_back(element);
+}
+
+void DBusOperationArguments::addArgumentUint32(unsigned int val)
+{
+    uint32_t *pVal = new uint32_t;
+    *pVal = val;
+
+    ArgumentElement element = ArgumentElement(ArgType::TYPE_UINT32, static_cast<void *>(pVal));
+
+    m_arguments.push_back(element);
+}
+
+void DBusOperationArguments::addArgumentUint64(uint64_t val)
+{
+    uint64_t *pVal = new uint64_t;
+    *pVal = val;
+
+    ArgumentElement element = ArgumentElement(ArgType::TYPE_UINT64, static_cast<void *>(pVal));
+
+    m_arguments.push_back(element);
+}
+
+void DBusOperationArguments::addArgumentString(std::string val)
+{
+    int length = val.length();
+
+    char *pVal = new char[length * 2];
+    strncpy(pVal, val.c_str(), length * 2);
+
+    ArgumentElement element = ArgumentElement(ArgType::TYPE_STRING, static_cast<void *>(pVal));
+
+    m_arguments.push_back(element);
+}
+
+void DBusOperationArguments::appendVariant(DBusMessageIter *busMsgIter)
+{
+    Arguments::iterator iter;
+    for (iter = m_arguments.begin(); iter != m_arguments.end(); iter++)
+    {
+        ArgType type = iter->first;
+        void *pVal = iter->second;
+
+        switch (type)
+        {
+        case ArgType::TYPE_BOOL:
+            dbus_message_iter_append_basic(busMsgIter, DBUS_TYPE_BOOLEAN, pVal);
+            break;
+        case ArgType::TYPE_INT32:
+            dbus_message_iter_append_basic(busMsgIter, DBUS_TYPE_INT32, pVal);
+            break;
+        case ArgType::TYPE_UINT32:
+            dbus_message_iter_append_basic(busMsgIter, DBUS_TYPE_UINT32, pVal);
+            break;
+        case ArgType::TYPE_UINT64:
+            dbus_message_iter_append_basic(busMsgIter, DBUS_TYPE_UINT64, pVal);
+            break;
+        case ArgType::TYPE_STRING:
+            dbus_message_iter_append_basic(busMsgIter, DBUS_TYPE_STRING, &pVal);
+            break;
+        default:
+            throw new DeviceAPI::Common::UnknownException("Wrong debug parameter type");
+        }
+    }
+}
+
+DBusOperationListener::DBusOperationListener()
+{
+}
+
+DBusOperationListener::~DBusOperationListener()
+{
+}
+
+std::set<DBusOperation *> DBusOperation::s_objects;
+
+DBusOperation::DBusOperation(std::string destination, std::string path, std::string interface) :
+        m_destination(destination), m_path(path), m_interface(interface), m_conn(NULL)
+{
+    LoggerD( "Created DBusOperator \"" << destination << "\" \"" << path << "\":\"" << interface << "\"");
+
+    s_objects.insert(this);
+}
+
+DBusOperation::~DBusOperation()
+{
+    if (m_conn)
+    {
+        dbus_connection_close(m_conn);
+        dbus_connection_unref(m_conn);
+        m_conn = NULL;
+    }
+
+    std::set<DBusOperation *>::iterator iter = s_objects.find(this);
+    if (iter != s_objects.end())
+        s_objects.erase(iter);
+    else
+        LoggerE("Object is not existing in the static pool");
+}
+
+int DBusOperation::invokeSyncGetInt(std::string method, DBusOperationArguments *args)
+{
+    DBusMessage *msg;
+    DBusMessage *reply;
+    DBusMessageIter iter;
+    DBusError err;
+    int ret, result;
+
+    if (!m_conn)
+        m_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL);
+
+    if (!m_conn)
+    {
+        LoggerE("dbus_bus_get_private error");
+        throw new DeviceAPI::Common::UnknownException("Failed to get dbus connection");
+    }
+
+    msg = dbus_message_new_method_call(m_destination.c_str(), m_path.c_str(), m_interface.c_str(), method.c_str());
+    if (!msg)
+    {
+        LoggerE("dbus_message_new_method_call error");
+        throw new DeviceAPI::Common::UnknownException("Failed to create dbus message");
+    }
+
+    dbus_message_iter_init_append(msg, &iter);
+    try
+    {
+        if (args != NULL)
+            args->appendVariant(&iter);
+    }
+    catch (DeviceAPI::Common::UnknownException &ex)
+    {
+        LoggerE("append_variant error");
+        dbus_message_unref(msg);
+        throw new DeviceAPI::Common::UnknownException("Failed to append dbus variable");
+    }
+
+    dbus_error_init(&err);
+    reply = dbus_connection_send_with_reply_and_block(m_conn, msg, DBUS_REPLY_TIMEOUT, &err);
+    dbus_message_unref(msg);
+    if (!reply)
+    {
+        LoggerE("dbus_connection_send_with_reply_and_block error(%s) : \"%s\"", err.name, err.message);
+        dbus_error_free(&err);
+        throw new DeviceAPI::Common::UnknownException("Failed to send request via dbus");
+    }
+
+    ret = dbus_message_get_args(reply, &err, DBUS_TYPE_INT32, &result, DBUS_TYPE_INVALID);
+    dbus_message_unref(reply);
+    if (!ret)
+    {
+        LoggerE("dbus_message_get_args error(%s) : \"%s\"", err.name, err.message);
+        dbus_error_free(&err);
+        throw new DeviceAPI::Common::UnknownException("Failed to get reply from dbus");
+    }
+
+    return result;
+}
+
+void DBusOperation::registerSignalListener(std::string signalName, DBusOperationListener* listener)
+{
+    addDBusSignalFilter();
+
+    SignalListenerPair pair(signalName, listener);
+
+    m_listeners.insert(pair);
+}
+
+void DBusOperation::unregisterSignalListener(std::string signalName, DBusOperationListener* listener)
+{
+    LoggerD("unregister signal listener : " << signalName);
+
+    bool signalFound = false;
+
+    SignalListenerSet::iterator iter;
+    for (iter = m_listeners.begin(); iter != m_listeners.end(); iter++)
+    {
+        if (iter->first == signalName && iter->second == listener)
+        {
+            LoggerD("Find and remove");
+            m_listeners.erase(iter);
+
+            signalFound = true;
+
+            break;
+        }
+    }
+
+    if (signalFound == false)
+    {
+        LoggerW("Failed to find signal handler");
+        throw new DeviceAPI::Common::UnknownException("Failed to find signal handler");
+    }
+
+    if (m_listeners.size() == 0)
+        removeDBusSignalFilter();
+}
+
+void DBusOperation::addDBusSignalFilter()
+{
+    DBusError err;
+
+    std::stringstream rule;
+
+    if (!m_conn)
+        m_conn = dbus_bus_get_private(DBUS_BUS_SYSTEM, NULL);
+
+    if (!m_conn)
+    {
+        LoggerE("dbus_bus_get_private error");
+        throw new DeviceAPI::Common::UnknownException("Failed to get dbus connection");
+    }
+
+    dbus_connection_setup_with_g_main(m_conn, NULL);
+
+    rule << "type='signal',sender='" << m_destination << "',path='" << m_path << "',interface='" << m_interface << "'";
+    m_rule = rule.str();
+
+    dbus_error_init(&err);
+    dbus_bus_add_match(m_conn, m_rule.c_str(), &err);
+    if (dbus_error_is_set(&err))
+    {
+        LoggerE("dbus_bus_add_match error(%s) : \"%s\"", err.name, err.message);
+        dbus_error_free(&err);
+        throw new DeviceAPI::Common::UnknownException("Failed to set rule for dbus signal");
+    }
+
+    if (dbus_connection_add_filter(m_conn, _dbus_signal_filter, this, NULL) == FALSE)
+    {
+        LoggerE("dbus_bus_add_match error(%s) : \"%s\"", err.name, err.message);
+        throw new DeviceAPI::Common::UnknownException("Failed to set handler for dbus signal");
+    }
+}
+
+void DBusOperation::removeDBusSignalFilter()
+{
+    DBusError err;
+
+    dbus_error_init(&err);
+    dbus_bus_remove_match(m_conn, m_rule.c_str(), &err);
+    if (dbus_error_is_set(&err))
+    {
+        LoggerE("dbus_bus_remove_match error(%s) : \"%s\"", err.name, err.message);
+        dbus_error_free(&err);
+        throw new DeviceAPI::Common::UnknownException("Failed to remove rule for dbus signal");
+    }
+
+    dbus_connection_remove_filter(m_conn, _dbus_signal_filter, this);
+}
+
+DBusHandlerResult DBusOperation::dbusSignalFilter(DBusConnection *conn, DBusMessage *message)
+{
+    int val;
+    DBusError err;
+
+    dbus_error_init(&err);
+    if (dbus_message_get_args(message, &err, DBUS_TYPE_INT32, &val, DBUS_TYPE_INVALID) == FALSE)
+    {
+        LoggerE("dbus_message_get_args error(%s) : \"%s\"", err.name, err.message);
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+    SLoggerD("val : " << val);
+
+    SignalListenerSet::iterator iter;
+    for (iter = m_listeners.begin(); iter != m_listeners.end(); iter++)
+    {
+        if (dbus_message_is_signal(message, m_interface.c_str(), iter->first.c_str()))
+        {
+            LoggerD("find to call : " << iter->first);
+            iter->second->OnDBusSignal(val);
+        }
+    }
+
+    return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+DBusHandlerResult DBusOperation::_dbus_signal_filter(DBusConnection *conn, DBusMessage *message, void *user_data)
+{
+    LoggerD("invoked callback from dbus");
+
+    DBusOperation *thisObj = static_cast<DBusOperation *>(user_data);
+
+    std::set<DBusOperation *>::iterator iter = s_objects.find(thisObj);
+    if (iter == s_objects.end())
+    {
+        LoggerE("Object is not existing in the static pool");
+        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+    }
+
+    return thisObj->dbusSignalFilter(conn, message);
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/DBusOperation.h b/src/Common/DBusOperation.h
new file mode 100755 (executable)
index 0000000..d16e0b5
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _DEVICEAPI_COMMON_DBUSOPERATION_H_
+#define _DEVICEAPI_COMMON_DBUSOPERATION_H_
+
+#include <dbus/dbus.h>
+#include <string>
+#include <vector>
+#include <set>
+
+namespace DeviceAPI {
+namespace Common {
+
+class DBusOperation;
+
+class DBusOperationArguments
+{
+public:
+       DBusOperationArguments();
+       virtual ~DBusOperationArguments();
+
+       void addArgumentBool(bool val);
+       void addArgumentInt32(int val);
+       void addArgumentUint32(unsigned int val);
+       void addArgumentUint64(uint64_t val);
+       void addArgumentString(std::string val);
+
+private:
+       enum ArgType
+       {
+               TYPE_BOOL, TYPE_INT32, TYPE_UINT32, TYPE_UINT64, TYPE_STRING
+       };
+       typedef std::pair<ArgType, void*> ArgumentElement;
+       typedef std::vector<ArgumentElement> Arguments;
+
+       Arguments m_arguments;
+
+       friend class DBusOperation;
+
+       void appendVariant(DBusMessageIter *busMsgIter);
+};
+
+class DBusOperationListener
+{
+public:
+       DBusOperationListener();
+       virtual ~DBusOperationListener();
+
+       virtual void OnDBusSignal(int value) = 0;
+};
+
+class DBusOperation
+{
+public:
+       DBusOperation(std::string destination, std::string path, std::string interface);
+       virtual ~DBusOperation();
+
+       int invokeSyncGetInt(std::string method, DBusOperationArguments *args);
+
+       void registerSignalListener(std::string signalName, DBusOperationListener* listener);
+       void unregisterSignalListener(std::string signalName, DBusOperationListener* listener);
+
+private:
+       std::string m_destination;
+       std::string m_path;
+       std::string m_interface;
+
+       typedef std::pair<std::string, DBusOperationListener*> SignalListenerPair;
+       typedef std::set<SignalListenerPair> SignalListenerSet;
+       SignalListenerSet m_listeners;
+
+       DBusConnection *m_conn;
+       std::string m_rule;
+
+       void addDBusSignalFilter();
+       void removeDBusSignalFilter();
+
+       DBusHandlerResult dbusSignalFilter(DBusConnection *conn, DBusMessage *message);
+       static DBusHandlerResult _dbus_signal_filter(DBusConnection *conn, DBusMessage *message, void *user_data);
+
+       static std::set<DBusOperation *> s_objects;
+};
+
+} // Common
+} // DeviceAPI
+
+#endif // _DEVICEAPI_COMMON_DBUSOPERATION_H_
diff --git a/src/Common/Export.h b/src/Common/Export.h
new file mode 100644 (file)
index 0000000..44afafc
--- /dev/null
@@ -0,0 +1,29 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_EXPORT_H__
+#define __TIZEN_EXPORT_H__
+
+#if defined(__GNUC__) && __GNUC__ >= 4
+    #define DLL_EXPORT      __attribute__((visibility("default")))
+    #define DLL_LOCAL       __attribute__((visibility("hidden")))
+#else
+    #define DLL_EXPORT
+    #define DLL_LOCAL
+#endif
+
+#endif // __TIZEN_EXPORT_H__
diff --git a/src/Common/GlobalContextManager.cpp b/src/Common/GlobalContextManager.cpp
new file mode 100644 (file)
index 0000000..b0bce5e
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "GlobalContextManager.h"
+#include "Logger.h"
+
+using namespace std;
+
+namespace DeviceAPI {
+namespace Common {
+
+GlobalContextManager::GlobalContextManager()
+{
+}
+
+GlobalContextManager* GlobalContextManager::getInstance()
+{
+    static GlobalContextManager instance;
+    return &instance;
+}
+
+JSContextRef GlobalContextManager::getGlobalContext(JSContextRef ctx)
+{
+    if(!ctx) {
+        LOGE("local context is NULL");
+        return NULL;
+    }
+
+    JSObjectRef global = JSContextGetGlobalObject(ctx);
+    ContextMapT::iterator itr = m_contexts.find(global);
+    if(itr == m_contexts.end()) {
+        LOGE("Can not found global Context");
+        return NULL;
+    }
+    return itr->second;
+}
+
+bool GlobalContextManager::isAliveGlobalContext(JSContextRef ctx)
+{
+    if(!ctx) {
+        return false;
+    }
+
+    const JSContextRef context = getGlobalContext(ctx);
+    return context == ctx;
+}
+
+void GlobalContextManager::addGlobalContext(JSContextRef ctx)
+{
+    JSObjectRef global = JSContextGetGlobalObject(ctx);
+    ContextMapT::iterator itr = m_contexts.find(global);
+    if(itr != m_contexts.end()) {
+        LOGD("already added global context");
+        return;
+    }
+    m_contexts[global] = ctx;
+}
+
+void GlobalContextManager::removeGlobalContext(JSContextRef ctx)
+{
+    JSObjectRef global = JSContextGetGlobalObject(ctx);
+    ContextMapT::iterator itr = m_contexts.find(global);
+    if(itr == m_contexts.end()) {
+        LOGD("does not exist context");
+        return;
+    }
+
+    if(itr->second == ctx) {
+        m_contexts.erase(itr);
+    }
+    else {
+        LOGE("passed context is not global context");
+    }
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/GlobalContextManager.h b/src/Common/GlobalContextManager.h
new file mode 100644 (file)
index 0000000..4e84ca3
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_COMMON_GLOBAL_CONTEXT_MANAGER_H__
+#define __TIZEN_COMMON_GLOBAL_CONTEXT_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "Logger.h"
+#include <map>
+
+namespace DeviceAPI {
+namespace Common {
+
+/**
+ * @brief Manage and tracking global context handle
+ */
+class GlobalContextManager {
+public:
+    /**
+     * @breif Gets global context from local context
+     *
+     * @param ctx local context
+     * @return The global context reference or NULL if function has failed
+     */
+    JSContextRef getGlobalContext(JSContextRef ctx);
+
+    /**
+     * @breif Add global context in manager
+     *
+     * @param ctx The global context to add
+     */
+    void addGlobalContext(JSContextRef ctx);
+
+    /**
+     * @breif Remove global context in manager
+     *
+     * @param ctx The global context to remove
+     */
+    void removeGlobalContext(JSContextRef ctx);
+
+    /**
+     * @breif Check the validation of global context
+     *
+     * @param ctx The global context to check
+     * @return true : the global context is alive, false : the global context was released
+     */
+    bool isAliveGlobalContext(JSContextRef ctx);
+
+    /**
+     * @breif Gets singletone handle
+     *
+     * @return GlobalContextManager handle
+     */
+    static GlobalContextManager* getInstance();
+
+private:
+    GlobalContextManager();
+    typedef std::map<JSObjectRef, JSContextRef> ContextMapT;
+    ContextMapT m_contexts;
+};
+
+#define CHECK_CURRENT_CONTEXT_ALIVE(context)\
+if( !GlobalContextManager::getInstance()->isAliveGlobalContext(context)){\
+    LOGE("context was closed");\
+    return;\
+}
+
+} // Common
+} // DeviceAPI
+#endif //__TIZEN_COMMON_GLOBAL_CONTEXT_MANAGER_H__
diff --git a/src/Common/IListenerManager.h b/src/Common/IListenerManager.h
new file mode 100644 (file)
index 0000000..bd23a70
--- /dev/null
@@ -0,0 +1,156 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        IListenerManager.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _TIZEN_COMMONS_ILISTENER_MANAGER_H_
+#define _TIZEN_COMMONS_ILISTENER_MANAGER_H_
+
+#include <map>
+#include <JavaScriptCore/JavaScript.h>
+#include <memory>
+#include "Singleton.h"
+#include "Export.h"
+#include "Logger.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+class IListenerItem;
+typedef std::shared_ptr<IListenerItem> IListenerItemPtr;
+
+class IListenerItem
+{
+public:
+       IListenerItem(JSContextRef context, JSObjectRef object, long watchId) :
+               m_context(context),
+               m_object(object),
+               m_watchId(watchId)
+       {
+       }
+
+       virtual ~IListenerItem()
+       {
+       }
+
+       virtual void protectObject()
+       {
+               LOGD("Protect object: %p", m_object);
+
+               JSValueProtect(m_context, m_object);
+       }
+
+       virtual void unprotectObject()
+       {
+               LOGD("Unprotect object: %p", m_object);
+
+               JSValueUnprotect(m_context, m_object);
+       }
+
+       virtual void cancelListener()
+       {
+               LOGW("IListenerItem MUST be used as an inherited shape.");
+               LOGW("If this log has been printed, it must be used with wrong usage.");
+       }
+
+       virtual bool equal(const DeviceAPI::Common::IListenerItemPtr &other) const
+       {
+               if(!other)
+                       return false;
+
+               if(m_object == other->m_object && m_watchId == other->m_watchId)
+                       return true;
+
+               return false;
+       }
+
+protected:
+       JSContextRef    m_context;
+       JSObjectRef             m_object;
+       long                    m_watchId;
+};
+
+class IListenerController
+{
+public:
+       typedef std::multimap<JSContextRef, IListenerItemPtr>   ListenerMap;
+       typedef typename ListenerMap::iterator                  ListenerMapIter;
+       typedef std::pair<JSContextRef, IListenerItemPtr>       ListenerPair;
+       typedef std::pair<ListenerMapIter, ListenerMapIter>     ListenerMapIterPair;
+
+       IListenerController()
+       {
+       }
+
+       virtual ~IListenerController()
+       {
+       }
+
+       virtual void registerListener(IListenerItemPtr &canceller, const JSContextRef context)
+       {
+               LOGD("Registering a listener on context: %p", context);
+
+               canceller->protectObject();
+               m_map.insert(ListenerPair(context, canceller));
+       }
+
+       virtual void unregisterContext(const JSContextRef context)
+       {
+               LOGD("Unregistering all listeners on context: %p", context);
+
+               ListenerMapIterPair iterPair = m_map.equal_range(context);
+
+               for(ListenerMapIter i=iterPair.first; i!=iterPair.second; i++)
+               {
+                       LOGD("Unregistering a listener");
+                       i->second->cancelListener();
+                       i->second->unprotectObject();
+               }
+
+               m_map.erase(context);
+       }
+
+       virtual void unregisterListener(const IListenerItemPtr &canceller)
+       {
+               LOGD("Unregistering a listener");
+
+               for(ListenerMapIter i=m_map.begin(); i!=m_map.end(); i++)
+               {
+                       if(i->second->equal(canceller))
+                       {
+                               LOGD("Found object");
+                               i->second->unprotectObject();
+
+                               m_map.erase(i);
+
+                               break;
+                       }
+               }
+       }
+
+private:
+       ListenerMap m_map;
+};
+
+} // Common
+} // DeviceAPI
+
+#endif // _TIZEN_COMMONS_ILISTENER_MANAGER_H_
diff --git a/src/Common/JSArray.cpp b/src/Common/JSArray.cpp
new file mode 100755 (executable)
index 0000000..a15b392
--- /dev/null
@@ -0,0 +1,49 @@
+#include "JSArray.h"
+#include "PlatformException.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+JSArrayBase::JSArrayBase( JSContextRef context, JSObjectRef array ):mContext(context), mArray(array){
+    if(!JSIsArrayValue(context, array)){
+        throw TypeMismatchException("The type is not array");
+    }
+    JSValueProtect(context, array);
+}
+
+JSArrayBase::JSArrayBase( JSContextRef context):mContext(context){
+    JSValueRef exception = NULL;
+    mArray = JSObjectMakeArray( context, 0, NULL, &exception);
+    if(exception != NULL){
+        throw UnknownException(context, exception);
+    }
+    JSValueProtect(context, mArray);
+}
+
+JSArrayBase::~JSArrayBase(){
+    JSValueUnprotect(mContext, mArray);
+}
+
+size_t JSArrayBase::size() const {
+    return JSGetArrayLength(mContext, mArray);
+}
+
+void JSArrayBase::resize(size_t array_size){
+    JSUtil::setProperty(mContext, mArray, "length", JSUtil::toJSValueRef(mContext, static_cast<double>(array_size)), kJSPropertyAttributeNone, NULL);
+}
+
+JSValueRef JSArrayBase::get(int index){
+    return JSGetArrayElement(mContext, mArray, index);
+}
+
+bool JSArrayBase::set( int index, JSValueRef value){
+    bool t = JSSetArrayElement(mContext, mArray, index, value);
+    return t;
+}
+
+bool JSArrayBase::append( JSValueRef value ){
+    return set( size(), value);
+}
+
+}//Common
+}//DeviceAPI
diff --git a/src/Common/JSArray.h b/src/Common/JSArray.h
new file mode 100755 (executable)
index 0000000..745b9e2
--- /dev/null
@@ -0,0 +1,206 @@
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_COMMON_JSARRAY_H__
+#define __TIZEN_COMMON_JSARRAY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <vector>
+#include "JSUtil.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+class JSArrayBase{
+public:
+    JSArrayBase( JSContextRef context, JSObjectRef array );
+    JSArrayBase( JSContextRef context );
+
+    virtual ~JSArrayBase();
+    size_t size() const;
+    void resize(size_t size);
+    JSValueRef get(int index);
+    bool set(int index, JSValueRef value);
+    bool append(JSValueRef value);
+
+protected:
+    JSContextRef mContext;
+    JSObjectRef mArray;
+};
+
+
+template <typename T>
+class JSArray : protected JSArrayBase{
+    friend class ItemProxy;
+public:
+    typedef JSValueRef (*ToJSFunction)(JSContextRef, T);
+    typedef T (*ToNativeFunction)(JSContextRef, JSValueRef );
+
+
+    JSArray( JSContextRef context, JSObjectRef array, ToNativeFunction nativefun, ToJSFunction jsfun)
+       :JSArrayBase(context,array),mToNative(nativefun), mToJs(jsfun) {
+    }
+    JSArray( JSContextRef context, ToNativeFunction nativefun, ToJSFunction jsfun)
+       :JSArrayBase(context),mToNative(nativefun), mToJs(jsfun) {
+    }
+
+    ~JSArray(){
+    }
+
+    class ItemProxy {
+        JSArray<T> *mArray;
+        int mIndex;
+        public:
+            ItemProxy(JSArray<T>* array, int index):mArray(array), mIndex(index){
+            }
+            operator T(){
+                return mArray->mToNative(mArray->mContext, mArray->get(mIndex));
+            }
+            ItemProxy& operator=( const T native){
+                JSValueRef v = mArray->mToJs(mArray->mContext, native);
+                mArray->set(mIndex, v);
+                return *this;
+            }
+            ItemProxy& operator=( const ItemProxy& other){
+                JSValueRef v = other.mArray->get(other.mIndex);
+                mArray->set(mIndex, v);
+                return *this;
+            }
+
+    };
+    size_t size() const{
+        return JSArrayBase::size();
+    }
+
+    void resize(size_t array_size){
+        JSArrayBase::resize(array_size);
+    }
+
+    bool empty() const{
+        return size() == 0;
+    }
+
+    bool append( T v){
+        return JSArrayBase::set( size(), mToJs(mContext, v));
+    }
+
+    ItemProxy operator[]( int index ){
+        return ItemProxy(this, index);
+    }
+
+    operator JSObjectRef(){
+        return mArray;
+    }
+
+    operator std::vector<T>(){
+        std::vector<T> v;
+        size_t length = size();
+        for( unsigned int i = 0 ; i < length ; i++){
+            JSValueRef t = get(i);
+            T tmp = mToNative(mContext, t);
+            v.push_back(tmp);
+        }
+        return v;
+    }
+
+    void operator=( const std::vector<T>& list ){
+        overwrite(list);
+    }
+
+    void operator=( const JSArray<T>& rhs){
+        resize(rhs.size());
+        for(unsigned int i = 0 ; i < rhs.size(); i++){
+            set(i, rhs.get(i));
+        }
+    }
+
+    JSContextRef getContext(){
+        return mContext;
+    }
+
+protected:
+    void overwrite( const std::vector<T>& list ){
+        unsigned int i;
+        unsigned int listSize = list.size();
+        resize(listSize);
+        for( i = 0 ; i < listSize ; i++){
+            JSValueRef v = mToJs(mContext, list[i]);
+            set(i, v);
+        }
+    }
+
+private:
+    ToNativeFunction mToNative;
+    ToJSFunction mToJs;
+};
+
+
+class JSStringArray : public JSArray<std::string>{
+    static JSValueRef makeJSValue(JSContextRef ctx, std::string v){
+        return JSUtil::toJSValueRef(ctx, v);
+    }
+    public:
+        // We need to pass pointer to function converting
+        // std::string -> JSValueRef. JSUtil::toJSValueRef is overloaded so we
+        // specify which version to use here by defining makeJSValue function.
+        JSStringArray(JSContextRef ctx, JSObjectRef array): JSArray<std::string>(ctx, array, JSUtil::JSValueToString, makeJSValue){}
+        JSStringArray(JSContextRef ctx): JSArray<std::string>(ctx, JSUtil::JSValueToString, makeJSValue){}
+        // We need to duplicate this function from JSArray because otherwise
+        // compiler see only assignment operator for JSArray and it doesn't
+        // propagate to derived classes.
+        void operator=( const std::vector<std::string>& list ){
+            JSArray<std::string>::operator=(list);
+        }
+};
+
+
+class JSLongArray : public JSArray<long>{
+    static JSValueRef makeJSValue(JSContextRef ctx, long v){
+        return JSUtil::toJSValueRef(ctx, v);
+    }
+    public:
+        JSLongArray(JSContextRef ctx, JSObjectRef array): JSArray<long>(ctx, array, JSUtil::JSValueToLong, makeJSValue){}
+        JSLongArray(JSContextRef ctx): JSArray<long>(ctx, JSUtil::JSValueToLong, makeJSValue){}
+        void operator=( const std::vector<long>& list ){
+            JSArray<long>::operator=(list);
+        }
+
+};
+
+
+template <class ObjectSharedPtr, class ObjectJSClass>
+class JSObjectArray : public JSArray<ObjectSharedPtr>{
+    static JSValueRef makeJSValue(JSContextRef ctx, ObjectSharedPtr v){
+        return ObjectJSClass::makeJSObject(ctx, v);
+    }
+    public:
+        // We need to pass pointer to function converting
+        // ObjectSharedPtr -> JSValueRef. ObjectJSClass::makeJSObject returns
+        // JSObjectRef so we use makeJSValue function to convert JSObjectRef to
+        // JSValueRef.
+        JSObjectArray(JSContextRef ctx, JSObjectRef array):
+            JSArray<ObjectSharedPtr>(ctx, array,
+                ObjectJSClass::getPrivateObject, makeJSValue){}
+        JSObjectArray(JSContextRef ctx):
+            JSArray<ObjectSharedPtr>(ctx,
+                ObjectJSClass::getPrivateObject, makeJSValue){}
+        void operator=( const std::vector<ObjectSharedPtr>& list ){
+            JSArray<ObjectSharedPtr>::operator=(list);
+        }
+};
+
+}
+}
+#endif //__TIZEN_COMMON_JSARRAY_H__
+
diff --git a/src/Common/JSStringRefWrapper.cpp b/src/Common/JSStringRefWrapper.cpp
new file mode 100644 (file)
index 0000000..b0aa69c
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSStringRefWrapper.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+JSStringRefWrapper::JSStringRefWrapper(JSStringRefWrapper &obj) : m_ref(NULL)
+{
+       JSStringRef ref = obj.m_ref;
+       if(ref)
+       {
+               const JSChar* chars = JSStringGetCharactersPtr(ref);
+               size_t numChars = JSStringGetLength(ref);
+
+               m_ref = JSStringCreateWithCharacters(chars, numChars);
+       }
+}
+
+JSStringRefWrapper::JSStringRefWrapper(JSStringRef ref) : m_ref(ref)
+{
+}
+
+JSStringRefWrapper::JSStringRefWrapper(const std::string str)
+{
+       m_ref = JSStringCreateWithUTF8CString(str.c_str());
+}
+
+JSStringRefWrapper::JSStringRefWrapper(const char * str)
+{
+       m_ref = JSStringCreateWithUTF8CString(str);
+}
+
+JSStringRefWrapper::~JSStringRefWrapper()
+{
+       if (m_ref != NULL)
+               JSStringRelease(m_ref);
+}
+
+JSStringRefWrapper & JSStringRefWrapper::operator=(const JSStringRefWrapper &obj)
+{
+       JSStringRef ref = obj.m_ref;
+
+       if (m_ref != NULL)
+               JSStringRelease(m_ref);
+
+       if(ref)
+       {
+               const JSChar* chars = JSStringGetCharactersPtr(ref);
+               size_t numChars = JSStringGetLength(ref);
+
+               m_ref = JSStringCreateWithCharacters(chars, numChars);
+       }
+       else
+       {
+               m_ref = NULL;
+       }
+
+       return *this;
+}
+
+JSStringRef JSStringRefWrapper::get() const
+{
+       return m_ref;
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/JSStringRefWrapper.h b/src/Common/JSStringRefWrapper.h
new file mode 100644 (file)
index 0000000..f9e9dd5
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _JS_STRING_REF_WRAPPER_H_
+#define _JS_STRING_REF_WRAPPER_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Common {
+
+class JSStringRefWrapper
+{
+public:
+       JSStringRefWrapper(JSStringRefWrapper &obj);
+       JSStringRefWrapper(JSStringRef ref);
+       JSStringRefWrapper(const std::string str);
+       JSStringRefWrapper(const char * str);
+       virtual ~JSStringRefWrapper();
+
+       JSStringRefWrapper & operator=(const JSStringRefWrapper &obj);
+
+       JSStringRef get() const;
+
+private:
+       JSStringRef m_ref;
+};
+
+} // Common
+} // DeviceAPI
+
+#endif // _JS_STRING_REF_WRAPPER_H_
diff --git a/src/Common/JSTizenSecurityObject.cpp b/src/Common/JSTizenSecurityObject.cpp
new file mode 100644 (file)
index 0000000..8177d12
--- /dev/null
@@ -0,0 +1,116 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "JSTizenSecurityObject.h"
+
+#include <string>
+
+#include "PlatformException.h"
+#include "JSStringRefWrapper.h"
+#include "Logger.h"
+
+#define CLASS_NAME "TizenSecurityObject"
+
+#define TIZEN_SECURITY_PROPERTY_NAME "__tizenobj"
+
+namespace DeviceAPI {
+namespace Common {
+
+JSClassDefinition JSTizenSecurityObject::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    CLASS_NAME,
+    0,
+    NULL, // staticValues
+    NULL, // staticFunctions
+    initialize,
+    finalize,
+    NULL, // hasProperty,
+    NULL, // getProperty,
+    NULL, // setProperty,
+    NULL, // deleteProperty,
+    NULL, // getPropertyNames,
+    NULL, // callAsFunction,
+    NULL, // callAsConstructor,
+    NULL, // hasInstance,
+    NULL  // convertToType
+};
+
+JSClassRef JSTizenSecurityObject::m_jsClassRef = JSClassCreate(JSTizenSecurityObject::getClassInfo());
+
+const JSClassRef JSTizenSecurityObject::getClassRef()
+{
+    if (!m_jsClassRef)
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSTizenSecurityObject::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSTizenSecurityObject::initialize(JSContextRef context, JSObjectRef object)
+{
+    if(!JSObjectGetPrivate(object))
+    {
+        LOGE("JSTizenSecurityObject has been created with no priv object.");
+    }
+}
+
+void JSTizenSecurityObject::finalize(JSObjectRef object)
+{
+}
+
+void JSObjectSetSecurityAccessor(JSContextRef context, JSObjectRef object, SecurityAccessor* securityAccessor)
+{
+    JSObjectRef jsSecurityObj = JSObjectMake(context, JSTizenSecurityObject::getClassRef(), static_cast<void*>(securityAccessor));
+
+    DeviceAPI::Common::JSStringRefWrapper securityObjName(TIZEN_SECURITY_PROPERTY_NAME);
+
+    JSValueRef exception = NULL;
+    JSObjectSetProperty(context, object, securityObjName.get(), jsSecurityObj,
+            kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontEnum | kJSPropertyAttributeDontDelete, &exception);
+
+    if(exception != NULL)
+        throw(InvalidValuesException("Failed to assign security module."));
+}
+
+SecurityAccessor* JSObjectGetSecurityAccessor(JSContextRef context, JSObjectRef object)
+{
+    DeviceAPI::Common::JSStringRefWrapper securityObjName(TIZEN_SECURITY_PROPERTY_NAME);
+
+    JSValueRef exception = NULL;
+    JSValueRef jsSecurityVal = JSObjectGetProperty(context, object, securityObjName.get(), &exception);
+    if(exception != NULL)
+        throw(InvalidValuesException("Failed to get security module. (no property)"));
+
+    JSObjectRef jsSecurityObj = JSValueToObject(context, jsSecurityVal, &exception);
+    if(exception != NULL)
+        throw(InvalidValuesException("Failed to get security module. (not a object)"));
+
+    SecurityAccessor *priv = static_cast<SecurityAccessor*>(JSObjectGetPrivate(jsSecurityObj));
+    if(priv == NULL)
+        throw(InvalidValuesException("Failed to get security module. (no priv)"));
+
+    return priv;
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/JSTizenSecurityObject.h b/src/Common/JSTizenSecurityObject.h
new file mode 100644 (file)
index 0000000..df6ade1
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_COMMON_JS_TIZEN_SECURITY_OBJECT_H__
+#define __TIZEN_COMMON_JS_TIZEN_SECURITY_OBJECT_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SecurityAccessor.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+class JSTizenSecurityObject
+{
+private:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_jsClassRef;
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    static void finalize(JSObjectRef object);
+
+    friend void JSObjectSetSecurityAccessor(JSContextRef context, JSObjectRef object, SecurityAccessor* securityAccessor);
+
+    friend SecurityAccessor* JSObjectGetSecurityAccessor(JSContextRef context, JSObjectRef object);
+};
+
+void JSObjectSetSecurityAccessor(JSContextRef context, JSObjectRef object, SecurityAccessor* securityAccessor);
+
+SecurityAccessor* JSObjectGetSecurityAccessor(JSContextRef context, JSObjectRef object);
+
+} // Common
+} // DeviceAPI
+
+#endif // __TIZEN_COMMON_JS_TIZEN_SECURITY_OBJECT_H__
diff --git a/src/Common/JSUtil.cpp b/src/Common/JSUtil.cpp
new file mode 100755 (executable)
index 0000000..ff5c49a
--- /dev/null
@@ -0,0 +1,347 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSUtil.h"
+#include "PlatformException.h"
+#include <WKBundle.h>
+#include <cmath>
+#include <limits>
+
+
+using namespace std;
+
+namespace DeviceAPI {
+namespace Common{
+
+JSValueRef JSUtil::getProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef *exception){
+    JSValueRef value;
+    JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
+    JSValueRef localException = NULL;
+    value = JSObjectGetProperty(ctx, object, propertyName, &localException);
+    JSStringRelease(propertyName);
+
+    if( localException != NULL ){
+        if( exception != NULL )
+            *exception = localException;
+        else
+            throw TypeMismatchException(ctx,localException);
+    }
+    return value;
+}
+
+void JSUtil::setProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef value, JSPropertyAttributes attributes, JSValueRef *exception){
+    JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
+    JSValueRef localException = NULL;
+    JSObjectSetProperty(ctx, object, propertyName, value,attributes, &localException);
+    JSStringRelease(propertyName);
+    if( localException != NULL ){
+        if( exception != NULL )
+            *exception = localException;
+        else
+            throw TypeMismatchException(ctx,localException);
+    }
+}
+
+string JSUtil::JSStringToString(JSContextRef ctx, JSStringRef str){
+    std::string result;
+    size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
+    {
+        char buffer[jsSize];
+        JSStringGetUTF8CString(str, buffer, jsSize);
+        result = buffer;
+    }
+    return result;
+}
+
+string JSUtil::JSValueToString(JSContextRef ctx, JSValueRef value){
+    std::string result;
+    JSValueRef exception = NULL;
+    JSStringRef str = JSValueToStringCopy(ctx, value, &exception);
+    if (exception != NULL) {
+        throw TypeMismatchException(ctx, exception);
+    }
+    size_t jsSize = JSStringGetMaximumUTF8CStringSize(str);
+    {
+        char buffer[jsSize];
+        JSStringGetUTF8CString(str, buffer, jsSize);
+        result = buffer;
+    }
+    JSStringRelease(str);
+    return result;
+}
+
+long JSUtil::JSValueToLong(JSContextRef ctx, JSValueRef value){
+    return static_cast<long>(JSValueToLongLong(ctx,value));
+}
+
+unsigned long JSUtil::JSValueToULong(JSContextRef ctx, JSValueRef value){
+     return static_cast<unsigned long>(JSValueToLongLong(ctx,value));
+}
+
+long long JSUtil::JSValueToLongLong(JSContextRef ctx, JSValueRef value){
+    return static_cast<long long>(JSValueToNumber(ctx, value));
+}
+
+unsigned long long JSUtil::JSValueToULongLong(JSContextRef ctx, JSValueRef value){
+    return static_cast<unsigned long long>(JSValueToLongLong(ctx,value));
+}
+
+double JSUtil::JSValueToDouble(JSContextRef ctx, JSValueRef value){
+    JSValueRef exception = NULL;
+
+    double doublevalue = ::JSValueToNumber(ctx, value, &exception);
+    if(exception != NULL){
+        throw TypeMismatchException(ctx, exception);
+    }
+    if( doublevalue == std::numeric_limits<double>::infinity() )
+        throw TypeMismatchException("Value is POSITIVE_INFINITY");
+    if( doublevalue == -std::numeric_limits<double>::infinity() )
+        throw TypeMismatchException("Value is NEGATIVE_INFINITY");
+    if( std::isnan(doublevalue)){
+        throw TypeMismatchException("Value is not number");
+    }
+    return doublevalue;
+}
+
+double JSUtil::JSValueToNumber(JSContextRef ctx, JSValueRef value){
+    JSValueRef exception = NULL;
+
+    double doublevalue = ::JSValueToNumber(ctx, value, &exception);
+    if(exception != NULL){
+        throw TypeMismatchException(ctx, exception);
+    }
+    if( doublevalue == std::numeric_limits<double>::infinity() )
+        doublevalue = 0.0;
+
+    if( doublevalue == -std::numeric_limits<double>::infinity() )
+        doublevalue = 0.0;
+
+    return doublevalue;
+}
+
+signed char JSUtil::JSValueToByte(JSContextRef ctx, JSValueRef value){
+    return static_cast<signed char>(JSValueToNumber(ctx,value));
+}
+
+unsigned char JSUtil::JSValueToOctet(JSContextRef ctx, JSValueRef value){
+    return static_cast<unsigned char>(JSValueToNumber(ctx,value));
+}
+
+bool JSUtil::JSValueToBoolean(JSContextRef ctx, JSValueRef value){
+    return ::JSValueToBoolean(ctx, value);
+}
+
+time_t JSUtil::JSValueToTimeT(JSContextRef ctx, JSValueRef value){
+    if(!JSValueIsDateObject(ctx, value))
+        throw TypeMismatchException("Value is not Date Object");
+
+    JSObjectRef timeobj = NULL;
+    timeobj = JSUtil::JSValueToObject(ctx, value);
+    JSValueRef exception = NULL;
+    JSObjectRef getTime = NULL;
+    try{
+        getTime = JSUtil::JSValueToObject(ctx, getProperty(ctx, timeobj, "getTime"));
+    }catch( const TypeMismatchException& err){
+        throw TypeMismatchException("Value is not Date Object");
+    }
+
+    JSValueRef timevalue = JSObjectCallAsFunction(ctx, getTime, timeobj, 0, NULL, &exception);
+    if( exception != NULL )
+        throw TypeMismatchException("Value is not Date Object");
+
+    double millisecond = JSValueToDouble(ctx, timevalue);
+    time_t second = millisecond/1000;
+    return second;
+}
+
+tm JSUtil::JSValueToDateTm(JSContextRef ctx, JSValueRef value){
+    tm result = {0};
+
+    time_t second = JSUtil::JSValueToTimeT(ctx, value);
+
+       if(localtime_r(&second, &result) == NULL)
+               throw TypeMismatchException("Value is not Date Object");
+
+    return result;
+}
+
+tm JSUtil::JSValueToDateTmUTC(JSContextRef ctx, JSValueRef value){
+    tm result = {0};
+
+    time_t second = JSUtil::JSValueToTimeT(ctx, value);
+
+       if(gmtime_r(&second, &result) == NULL)
+               throw TypeMismatchException("Value is not Date Object");
+
+    return result;
+}
+
+JSObjectRef JSUtil::JSValueToObject(JSContextRef ctx, JSValueRef value){
+    JSValueRef exception = NULL;
+    JSObjectRef obj = ::JSValueToObject(ctx, value,&exception);
+    if( exception != NULL){
+        throw TypeMismatchException(ctx, exception);
+    }
+    return obj;
+}
+
+std::map<std::string, std::string> JSUtil::JSValueToStringMap(JSContextRef ctx, JSValueRef value){
+    std::map<std::string, std::string> result;
+    JSObjectRef obj = JSUtil::JSValueToObject(ctx, value);
+    JSPropertyNameArrayRef jsPropNames = JSObjectCopyPropertyNames(ctx, obj);
+    for (std::size_t i = 0; i < JSPropertyNameArrayGetCount(jsPropNames); ++i) {
+        std::string propName = JSUtil::JSStringToString(ctx, JSPropertyNameArrayGetNameAtIndex(jsPropNames, i));
+        std::string propValue = JSUtil::JSValueToString(ctx, JSUtil::getProperty(ctx, obj, propName.c_str(), NULL));
+        result.insert(std::make_pair(propName, propValue));
+    }
+    JSPropertyNameArrayRelease(jsPropNames);
+    return result;
+}
+
+JSObjectRef JSUtil::makeDateObject(JSContextRef ctx, const time_t value){
+    JSValueRef exception = NULL;
+    JSValueRef args[1];
+    double millisecond = value*1000.0;
+    args[0] = toJSValueRef(ctx, millisecond);
+    JSObjectRef result = JSObjectMakeDate(ctx, 1, args, &exception);
+    if( exception != NULL){
+        throw TypeMismatchException("Can't create Date object");
+    }
+    return result;
+}
+
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const string& str){
+    JSValueRef result = NULL;
+    JSStringRef jsString = JSStringCreateWithUTF8CString(str.c_str());
+    result = JSValueMakeString(ctx, jsString);
+    JSStringRelease(jsString);
+    return result;
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const unsigned long value){
+    return JSValueMakeNumber(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const long value){
+    return JSValueMakeNumber(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const unsigned long long value) {
+    return JSValueMakeNumber(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const long long value) {
+    return JSValueMakeNumber(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const double value){
+    return JSValueMakeNumber(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const signed char value){
+    return JSValueMakeNumber(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const unsigned char value){
+    return JSValueMakeNumber(ctx, value);
+}
+
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const bool value){
+    return JSValueMakeBoolean(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<std::string>& value){
+    return toJSValueRef_(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<long>& value){
+    return toJSValueRef_(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<double>& value){
+    return toJSValueRef_(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::vector<bool>& value){
+    return toJSValueRef_(ctx, value);
+}
+
+JSValueRef JSUtil::toJSValueRef(JSContextRef ctx, const std::map<std::string, std::string>& value){
+    JSObjectRef obj = JSObjectMake(ctx, NULL, NULL);
+
+    std::map<std::string, std::string>::const_iterator iter;
+    for (iter = value.begin(); iter != value.end(); ++iter) {
+        std::string propName = iter->first;
+        JSUtil::setProperty(ctx, obj, propName.c_str(), JSUtil::toJSValueRef(ctx, iter->second), kJSPropertyAttributeNone);
+    }
+
+    return obj;
+}
+
+vector<string> JSUtil::JSArrayToStringVector(JSContextRef ctx, JSValueRef value){
+    return JSArrayToType_<string>(ctx, value, JSUtil::JSValueToString);
+}
+vector<double> JSUtil::JSArrayToDoubleVector(JSContextRef ctx, JSValueRef value){
+    return JSArrayToType_<double>(ctx, value, JSUtil::JSValueToDouble);
+}
+vector<long> JSUtil::JSArrayToLongVector(JSContextRef ctx, JSValueRef value){
+    return JSArrayToType_<long>(ctx, value, JSUtil::JSValueToLong);
+}
+vector<time_t> JSUtil::JSArrayToTimeTVector(JSContextRef ctx, JSValueRef value){
+    return JSArrayToType_<time_t>(ctx, value, JSUtil::JSValueToTimeT);
+}
+vector<bool> JSUtil::JSArrayToBoolVector(JSContextRef ctx, JSValueRef value){
+    return JSArrayToType_<bool>(ctx, value, JSUtil::JSValueToBoolean);
+}
+
+vector<unsigned char> JSUtil::JSArrayToUCharVector(JSContextRef ctx, JSValueRef value){
+    return JSArrayToType_<unsigned char>(ctx, value, JSUtil::JSValueToOctet);
+}
+
+bool JSUtil::JSValueIsDateObject(JSContextRef ctx, JSValueRef jsValue) {
+    JSValueRef exception = NULL;
+
+    JSObjectRef globalObj = JSContextGetGlobalObject(ctx);
+
+    JSValueRef jsDate = getProperty(ctx, globalObj, "Date", &exception);
+    if(exception)
+        return false;
+
+    JSObjectRef jsDateObj = ::JSValueToObject(ctx, jsDate, &exception);
+    if(exception)
+        return false;
+
+    bool result = JSValueIsInstanceOfConstructor(ctx, jsValue, jsDateObj, &exception);
+    if(exception)
+        return false;
+
+    return result;
+}
+
+void JSUtil::addPropertyName(JSPropertyNameAccumulatorRef propertyNames,
+        const char* name)
+{
+    JSStringRef propertyName = NULL;
+    propertyName = JSStringCreateWithUTF8CString(name);
+    JSPropertyNameAccumulatorAddName(propertyNames, propertyName);
+    JSStringRelease(propertyName);
+}
+
+}
+}
diff --git a/src/Common/JSUtil.h b/src/Common/JSUtil.h
new file mode 100644 (file)
index 0000000..c5fb256
--- /dev/null
@@ -0,0 +1,604 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _JSUTIL_H_
+#define _JSUTIL_H_
+#include <JavaScriptCore/JavaScript.h>
+#include <string>
+#include <map>
+#include <vector>
+#include "PlatformException.h"
+#include <ctime>
+
+
+namespace DeviceAPI {
+namespace Common{
+
+class JSUtil{
+public:
+    /**
+     * @brief Gets a property from an object.
+     *
+     * @remarks
+     * if pass NULL in exception, when occurred error, it throw C++ exception(TypeMismatchException).
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] object The JSObject whose property you want to get.
+     * @param[in] name The name of property
+     * @param[out] exception A pointer to a JSValueRef in which to store an exception, if any.
+     *
+     * @exception TypeMismatchException
+     */
+    static JSValueRef getProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef *exception=NULL);
+
+    /**
+     * @brief Sets a property on an object.
+     *
+     * @remarks
+     * if pass NULL in exception, when occurred error, it throw C++ exception(TypeMismatchException).
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] object The JSObject whose property you want to set.
+     * @param[in] name The name of property
+     * @param[in] attributes A logically ORed set of JSPropertyAttributes to give to the property.
+     * @param[out] exception A pointer to a JSValueRef in which to store an exception, if any.
+     *
+     * @exception TypeMismatchException
+     */
+    static void setProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef value, JSPropertyAttributes attributes, JSValueRef *exception=NULL);
+
+    /**
+     * @brief Converts a JavaScript string to STL string
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSString to convert.
+     *
+     * @return A STL string with the result of conversion
+     */
+    static std::string JSStringToString(JSContextRef ctx, JSStringRef str);
+
+    /**
+     * @brief Converts a JavaScript value to STL string
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return A STL string with the result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static std::string JSValueToString(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to long number and returns the resulting long number.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static long JSValueToLong(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to unsigned long number and returns the resulting unsigned long number.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static unsigned long JSValueToULong(JSContextRef ctx, JSValueRef value);
+
+
+    /**
+     * @brief Converts a JavaScript value to long long number and returns the resulting long long number.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static long long JSValueToLongLong(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to unsigned long long number and returns the resulting unsigned long long number.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static unsigned long long JSValueToULongLong(JSContextRef ctx, JSValueRef value);
+
+
+    /**
+     * @brief Converts a JavaScript value to double number and returns the resulting double number.
+     *
+     * @remarks TypeMismatchException is thrown when the result of conversion was NaN(Not a Number).
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static double JSValueToDouble(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to number and returns the resulting number.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static double JSValueToNumber(JSContextRef ctx, JSValueRef value);
+
+
+    /**
+     * @brief Converts a JavaScript value to byte(signed) number and returns the resulting byte(signed) number.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static signed char JSValueToByte(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to Octet(unsigned) number and returns the resulting Octet(unsigned) number.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static unsigned char JSValueToOctet(JSContextRef ctx, JSValueRef value);
+
+
+    /**
+     * @brief Converts a JavaScript value to boolean and returns the resulting bollean
+     *
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     */
+    static bool JSValueToBoolean(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to time_t and returns the resulting time_t.
+     *
+     * @remarks TypeMismatchException is thrown when the value was not Date type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static time_t JSValueToTimeT(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to tm and returns the resulting tm.
+     *
+     * @remarks TypeMismatchException is thrown when the value was not Date type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static std::tm JSValueToDateTm(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to tm as UTC time and returns the resulting tm.
+     *
+     * @remarks TypeMismatchException is thrown when the value was not Date type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static std::tm JSValueToDateTmUTC(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to object and returns the resulting object.
+     *
+     * @remarks TypeMismatchException is thrown when the value was not Object type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The JSObject result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static JSObjectRef JSValueToObject(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to STL string vector and returns the resulting STL string vector
+     *
+     * @remarks TypeMismatchException is thrown when the array element could not converts to string.\n
+     * If the value is not Array object, Will return empty vector
+     *
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return A STL string vector
+     *
+     * @exception TypeMismatchException
+     */
+    static std::vector<std::string> JSArrayToStringVector(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to double number vector and returns the resulting double number vector
+     *
+     * @remarks TypeMismatchException is thrown when the array element could not converts to double.\n
+     * If the value is not Array object, Will return empty vector
+     *
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return A double number vector
+     *
+     * @exception TypeMismatchException
+     */
+    static std::vector<double> JSArrayToDoubleVector(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to long number vector and returns the resulting long number vector
+     *
+     * @remarks TypeMismatchException is thrown when the array element could not converts to long.\n
+     * If the value is not Array object, Will return empty vector
+     *
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return A long number vector
+     *
+     * @exception TypeMismatchException
+     */
+    static std::vector<long> JSArrayToLongVector(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to time_t vector and returns the resulting time_t vector
+     *
+     * @remarks TypeMismatchException is thrown when the array element could not converts to time_t.\n
+     * If the value is not Array object, Will return empty vector
+     *
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return A time_t vector
+     *
+     * @exception TypeMismatchException
+     */
+    static std::vector<time_t> JSArrayToTimeTVector(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to boolean vector and returns the resulting boolean vector
+     *
+     * @remarks If the value is not Array object, Will return empty vector
+     *
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return A boolean vector
+     */
+    static std::vector<bool> JSArrayToBoolVector(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to unsigned char vector and returns the resulting unsigned char vector
+     *
+     * @remarks If the value is not Array object, Will return empty vector
+     *
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return A unsigned char vector
+     */
+    static std::vector<unsigned char> JSArrayToUCharVector(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Converts a JavaScript value to map<string,string> and returns the resulting object.
+     *
+     * @remarks TypeMismatchException is thrown when the value was not Object type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The JSValue to convert.
+     *
+     * @return The JSObject result of conversion
+     *
+     * @exception TypeMismatchException
+     */
+    static std::map<std::string, std::string> JSValueToStringMap(JSContextRef ctx, JSValueRef value);
+
+    /**
+     * @brief Creates a JavaScript value of the string type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] str The STL string to assign to the newly created JSValue. The newly created JSValue retains string, and releases it upon garbage collection.
+     *
+     * @return A JSValue of the string type, representing the value of string.
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const std::string& str);
+
+    /**
+     * @brief Creates a JavaScript value of the number type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The long to assign to the newly created JSValue.
+     *
+     * @return A JSValue of the number type, representing the value of number.
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const long value);
+
+    /**
+     * @brief Creates a JavaScript value of the number type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The unsigned long to assign to the newly created JSValue.
+     *
+     * @return A JSValue of the number type, representing the value of number.
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const unsigned long value);
+
+    /**
+     * @brief Creates a JavaScript value of the number type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The long long to assign to the newly created JSValue.
+     *
+     * @return A JSValue of the number type, representing the value of number.
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const long long value);
+
+    /**
+     * @brief Creates a JavaScript value of the number type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The unsigned long long to assign to the newly created JSValue.
+     *
+     * @return A JSValue of the number type, representing the value of number.
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const unsigned long long value);
+    /**
+     * @brief Creates a JavaScript value of the number type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The double to assign to the newly created JSValue.
+     *
+     * @return A JSValue of the number type, representing the value of number.
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const double value);
+
+    /**
+     * @brief Creates a JavaScript value of the boolean type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The bool to assign to the newly created JSValue.
+     *
+     * @return A JSValue of the boolean type, representing the value of boolean.
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const bool value);
+
+    /**
+     * @brief Creates a JavaScript value of the number type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The signed char to assign to the newly created JSValue.
+     *
+     * @return A JSValue of the number type, representing the value of number.
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const signed char value);
+
+    /**
+     * @brief Creates a JavaScript value of the number type.
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The signed char to assign to the newly created JSValue.
+     *
+     * @return A JSValue of the number type, representing the value of number.
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const unsigned char value);
+
+
+
+    /**
+     * @brief Creates a JavaScript value of the string Array type.
+     *
+     * @remarks UnknownException is thrown when could not create Array object.\n
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The STL string vector to assign to the newly created JSArray
+     *
+     * @return A JSArray of the string type
+     *
+     * @exception UnknownException
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const std::vector<std::string>& value);
+
+
+    /**
+     * @brief Creates a JavaScript value of the number Array type.
+     *
+     * @remarks UnknownException is thrown when could not create Array object.\n
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The long vector to assign to the newly created JSArray
+     *
+     * @return A JSArray of the number type
+     *
+     * @exception UnknownException
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const std::vector<long>& value);
+
+    /**
+     * @brief Creates a JavaScript value of the number Array type.
+     *
+     * @remarks UnknownException is thrown when could not create Array object.\n
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The double vector to assign to the newly created JSArray
+     *
+     * @return A JSArray of the number type
+     *
+     * @exception UnknownException
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const std::vector<double>& value);
+
+
+    /**
+     * @brief Creates a JavaScript value of the boolean Array type.
+     *
+     * @remarks UnknownException is thrown when could not create Array object.\n
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The boolean vector to assign to the newly created JSArray
+     *
+     * @return A JSArray of the boolean type
+     *
+     * @exception UnknownException
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const std::vector<bool>& value);
+
+    /**
+     * @brief Creates a JavaScript value of the string map type.
+     *
+     * @remarks UnknownException is thrown when could not create Array object.\n
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The string map to assign to the newly created JSValue
+     *
+     * @return A JSValue of the string map type
+     *
+     * @exception UnknownException
+     */
+    static JSValueRef toJSValueRef(JSContextRef ctx, const std::map<std::string, std::string>& value);
+
+    /**
+     * @brief Creates a JavaScript Date object with time_t value
+     *
+     * @remarks TypeMismatchException is thrown when could not create Date object.\n
+     *
+     * @param[in] ctx The execution context to use.
+     * @param[in] value The time_t value to create
+     *
+     * @return A JSObject that is a Date.
+     *
+     * @exception TypeMismatchException
+     */
+    static JSObjectRef makeDateObject(JSContextRef ctx, const time_t value);
+
+
+    template<class T>
+    static std::vector<T> JSArrayToType_(JSContextRef ctx, JSValueRef value, T (*convert)(JSContextRef, JSValueRef)){
+        std::vector<T> result;
+        if( !JSIsArrayValue(ctx, value)){
+            return result;
+        }
+        JSObjectRef arrayobj = JSUtil::JSValueToObject(ctx, value);
+
+        for (std::size_t i = 0; i < JSGetArrayLength(ctx, arrayobj); ++i) {
+            JSValueRef element = JSGetArrayElement(ctx, arrayobj, i);
+            T v = convert(ctx, element);
+            result.push_back(v);
+        }
+        return result;
+    }
+
+    template<class T>
+    static JSValueRef toJSValueRef_(JSContextRef ctx, const std::vector<T>& value){
+        JSValueRef valueArray[value.size()];
+        for( unsigned int i = 0 ; i < value.size(); i++){
+            valueArray[i] = toJSValueRef(ctx,value[i]);
+        }
+        JSValueRef exception = NULL;
+        JSObjectRef jsResult = JSObjectMakeArray(ctx, value.size(), valueArray, &exception);
+        if (exception != NULL) {
+            throw UnknownException(ctx, exception);
+        }
+        return jsResult;
+    };
+
+    template<class T>
+    static JSValueRef toJSValueRef_(JSContextRef ctx, const std::vector<std::pair<std::string, std::vector<T>>>& value)
+    {
+        JSObjectRef js_result = JSCreateArrayObject(ctx, 0, NULL);
+        if (NULL == js_result) {
+            throw Common::UnknownException("Could not create js array object");
+        }
+
+        for (std::size_t i = 0; i < value.size(); ++i) {
+            JSValueRef tmp_val = toJSValueRef_(ctx, value[i].second);
+            if (!JSSetArrayElementInArrayList(ctx, js_result,
+                    value[i].first.c_str(), tmp_val)) {
+                throw Common::UnknownException("Could not insert value into js array");
+            }
+        }
+        return js_result;
+    }
+
+    /**
+     * @brief Adds property name to PropertyNameAccumulator
+     *
+     * @remarks Used in getPropertyNames\n
+     *
+     * @param[in] propertyNames PropertyNameAccumulator to be supplemented.
+     * @param[in] name The name of the property to be added.
+     */
+    static void addPropertyName(JSPropertyNameAccumulatorRef propertyNames,
+            const char* name);
+
+private:
+    static bool JSValueIsDateObject(JSContextRef ctx, JSValueRef jsValue);
+};
+
+}}
+
+#endif //_JSUTIL_H_
+
+
diff --git a/src/Common/JSVector.h b/src/Common/JSVector.h
new file mode 100644 (file)
index 0000000..e1114f2
--- /dev/null
@@ -0,0 +1,311 @@
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef __TIZEN_COMMON_JSVECTOR_H__
+#define __TIZEN_COMMON_JSVECTOR_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <vector>
+#include <memory>
+#include <exception>
+#include "JSUtil.h"
+#include "Logger.h"
+#include "GlobalContextManager.h"
+#include "JSArray.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+/** Generic class encapsulating recommended JSArray use.
+ *
+ *  It is highly recommended to use JSArray instead of std::vector only when
+ *  there is context available (using bare JSArray in cpp-layer class lead to
+ *  necessity of supplying context in it's constructor which is inconvenient).
+ *  This class encapsulates interchangeable use of std::vector and
+ *  JSArray. When constructed the class use std::vector and when context appears
+ *  second stage is entered - data is rewritten from std::vector to JSArray and
+ *  all methods change their behaviour correspondingly.
+ */
+template <class T>
+class JSVector {
+public:
+    JSVector(typename JSArray<T>::ToNativeFunction nativefun,
+        typename JSArray<T>::ToJSFunction jsfun):
+            mToNative(nativefun), mToJs(jsfun) {
+        LOGD("entered");
+    }
+
+    // copy constructor, populating only vector m_array since initial state of
+    // JSVector should be std::vector
+    JSVector(const JSVector<T>& arr,
+        typename JSArray<T>::ToNativeFunction nativefun,
+        typename JSArray<T>::ToJSFunction jsfun):
+            mToNative(nativefun), mToJs(jsfun) {
+        LOGD("entered, arr.size = %d, m_js_array = %s", arr.size(),
+            static_cast<bool>(m_js_array) ? "true" : "false");
+
+        m_array = arr;
+    }
+
+    JSVector(const std::vector<T>& vec,
+        typename JSArray<T>::ToNativeFunction nativefun,
+        typename JSArray<T>::ToJSFunction jsfun):
+            mToNative(nativefun), mToJs(jsfun) {
+        LOGD("entered, vec.size = %d, m_js_array = %s", vec.size(),
+            static_cast<bool>(m_js_array) ? "true" : "false");
+
+        m_array = vec;
+    }
+
+    JSVector<T>& operator =(const JSVector<T>& arr) {
+        LOGD("entered, arr.size = %d, m_js_array = %s, jsMode() = %s",
+            arr.size(), static_cast<bool>(m_js_array) ? "true" : "false",
+            jsMode() ? "true" : "false");
+
+        if (jsMode()){
+            // static_casting to vector to make deep copy of arr
+            *m_js_array = static_cast<std::vector<T>>(arr);
+        }
+        else {
+            m_array = arr;
+        }
+
+        return *this;
+    }
+
+    JSVector<T>& operator =(const std::vector<T>& vec) {
+        LOGD("entered, vec.size = %d, m_js_array = %s, jsMode() = %s",
+            vec.size(), static_cast<bool>(m_js_array) ? "true" : "false",
+            jsMode() ? "true" : "false");
+
+        if (jsMode()){
+            m_js_array = std::shared_ptr<JSArray<T>>(
+                    new JSArray<T>(getContext(), mToNative, mToJs));
+            *m_js_array = vec;
+        }
+        else {
+            m_array = vec;
+        }
+
+        return *this;
+    }
+
+    operator std::vector<T>() const
+    {
+        LOGD("entered, size = %d, m_js_array = %s, jsMode() = %s",
+            size(), static_cast<bool>(m_js_array) ? "true" : "false",
+            jsMode() ? "true" : "false");
+
+        if (jsMode()) {
+            return static_cast<std::vector<T>>(*m_js_array);
+        }
+        else {
+            return m_array;
+        }
+    }
+
+    // first use of getJSArray(JSContextRef) make current object move to jsMode
+    JSObjectRef getJSArray(JSContextRef global_ctx)
+    {
+        LOGD("entered, size = %d, m_js_array = %s, jsMode() = %s",
+            size(), static_cast<bool>(m_js_array) ? "true" : "false",
+            jsMode() ? "true" : "false");
+
+        // check if supplied context is the same as before
+        if (m_js_array && m_js_array->getContext() != global_ctx) {
+            LOGE("Wrong context supplied");
+            throw Common::UnknownException("Wrong context supplied");
+        }
+
+        // check if context is "alive" (not-null and global for current code)
+        if (!Common::GlobalContextManager::getInstance()
+                ->isAliveGlobalContext(global_ctx)) {
+            LOGE("Context is not alive");
+            throw Common::UnknownException("Context is not alive");
+        }
+
+        if (!m_js_array) {
+            // move data from m_array to m_js_array
+            m_js_array = std::shared_ptr<JSArray<T>>(
+                new JSArray<T>(global_ctx, mToNative, mToJs));
+            *m_js_array = m_array;
+            m_array.clear();
+        }
+
+        return *m_js_array;
+    }
+
+    size_t size() const {
+        if (jsMode()) {
+            return m_js_array->size();
+        }
+        else {
+            return m_array.size();
+        }
+    }
+
+    bool empty() const {
+        LOGD("entered, size = %d, m_js_array = %s, jsMode() = %s",
+            size(), static_cast<bool>(m_js_array) ? "true" : "false",
+            jsMode() ? "true" : "false");
+
+        return size() == 0;
+    }
+
+    void push_back(const T& val) {
+        LOGD("entered, size = %d, m_js_array = %s, jsMode() = %s",
+            size(), static_cast<bool>(m_js_array) ? "true" : "false",
+            jsMode() ? "true" : "false");
+
+        if (jsMode()) {
+            if (!m_js_array->append(val)) {
+                LOGE("jsarray alloc fail");
+                // if append fails throw same exception as vector does
+                throw std::bad_alloc();
+            }
+        }
+        else {
+            m_array.push_back(val);
+        }
+    }
+
+    void clear() {
+        LOGD("entered, size = %d, m_js_array = %s, jsMode() = %s",
+            size(), static_cast<bool>(m_js_array) ? "true" : "false",
+            jsMode() ? "true" : "false");
+
+        if (jsMode()) {
+            m_js_array->resize(0);
+        }
+        else {
+            m_array.clear();
+        }
+    }
+
+    JSContextRef getContext() {
+        return m_js_array ? m_js_array->getContext() : NULL;
+    }
+
+private:
+    std::vector<T> m_array;
+    std::shared_ptr<JSArray<T>> m_js_array;
+
+    typename JSArray<T>::ToNativeFunction mToNative;
+    typename JSArray<T>::ToJSFunction mToJs;
+
+    bool jsMode() const {
+        return m_js_array && Common::GlobalContextManager::getInstance()
+                ->isAliveGlobalContext(m_js_array->getContext());
+    }
+};
+
+
+class JSStringVector : public JSVector<std::string>{
+    static JSValueRef makeJSValue(JSContextRef ctx, std::string v){
+        return JSUtil::toJSValueRef(ctx, v);
+    }
+
+    public:
+        JSStringVector(const std::vector<std::string>& vec):
+            JSVector<std::string>(vec, JSUtil::JSValueToString, makeJSValue){}
+        JSStringVector():
+            JSVector<std::string>(JSUtil::JSValueToString, makeJSValue){}
+
+        JSStringVector& operator=( const std::vector<std::string>& list ){
+            JSVector<std::string>::operator=(list);
+            return *this;
+        }
+};
+
+
+class JSLongVector : public JSVector<long>{
+    static JSValueRef makeJSValue(JSContextRef ctx, long v){
+        return JSUtil::toJSValueRef(ctx, v);
+    }
+
+    public:
+        JSLongVector(const std::vector<long>& vec):
+            JSVector<long>(vec, JSUtil::JSValueToLong,
+                    makeJSValue){}
+        JSLongVector():
+            JSVector<long>(JSUtil::JSValueToLong, makeJSValue){}
+        void operator=( const std::vector<long>& list ){
+            JSVector<long>::operator=(list);
+        }
+
+};
+
+
+class JSLongLongVector : public JSVector<long long int>{
+    static JSValueRef makeJSValue(JSContextRef ctx, long long int v){
+        return JSUtil::toJSValueRef(ctx, v);
+    }
+
+    public:
+        JSLongLongVector(const std::vector<long long int>& vec):
+            JSVector<long long int>(vec, JSUtil::JSValueToLongLong,
+                    makeJSValue){}
+        JSLongLongVector():
+            JSVector<long long int>(JSUtil::JSValueToLongLong, makeJSValue){}
+        void operator=( const std::vector<long long int>& list ){
+            JSVector<long long int>::operator=(list);
+        }
+
+};
+
+
+template <class ObjectSharedPtr, class ObjectJSClass>
+class JSObjectVector : public JSVector<ObjectSharedPtr>{
+    static JSValueRef makeJSValue(JSContextRef ctx, ObjectSharedPtr v){
+        return ObjectJSClass::makeJSObject(ctx, v);
+    }
+    public:
+        JSObjectVector(const std::vector<ObjectSharedPtr>& vec):
+            JSVector<ObjectSharedPtr>(vec, ObjectJSClass::getPrivateObject,
+                makeJSValue){}
+        JSObjectVector():
+            JSVector<ObjectSharedPtr>(ObjectJSClass::getPrivateObject,
+                makeJSValue){}
+
+        JSObjectVector& operator=( const std::vector<ObjectSharedPtr>& list ){
+            JSVector<ObjectSharedPtr>::operator=(list);
+            return *this;
+        }
+};
+
+
+template <typename EnumT,
+         EnumT (*ToEnumFun)(const std::string&),
+         std::string (*ToStringFun)(EnumT)>
+class JSEnumVector : public JSVector<EnumT>{
+    static JSValueRef makeJSValue(JSContextRef ctx, EnumT v){
+        return JSUtil::toJSValueRef(ctx, ToStringFun(v));
+    }
+    static EnumT makeNative(JSContextRef ctx, JSValueRef v){
+        return ToEnumFun(JSUtil::JSValueToString(ctx, v));
+    }
+    public:
+        JSEnumVector(const std::vector<EnumT>& vec):
+            JSVector<EnumT>(vec, makeNative, makeJSValue){};
+        JSEnumVector():
+            JSVector<EnumT>(makeNative, makeJSValue){};
+
+        JSEnumVector& operator=( const std::vector<EnumT>& list ){
+            JSVector<EnumT>::operator=(list);
+            return *this;
+        }
+};
+
+} // Common
+} // DeviceAPI
+#endif // __TIZEN_COMMON_JSVECTOR_H__
diff --git a/src/Common/JSWebAPIError.cpp b/src/Common/JSWebAPIError.cpp
new file mode 100644 (file)
index 0000000..00963fb
--- /dev/null
@@ -0,0 +1,194 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSWebAPIError.h"
+
+#include <string>
+#include <map>
+#include "JSUtil.h"
+#include "Logger.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+namespace {
+const char* CLASS_NAME = "WebAPIError";
+const char* PROPERTY_CODE = "code";
+const char* PROPERTY_NAME = "name";
+const char* PROPERTY_TYPE = "type";
+const char* PROPERTY_MESSAGE = "message";
+
+const char* FUNCTION_TO_STRING = "toString";
+}
+
+JSClassRef JSWebAPIError::m_classRef = NULL;
+
+JSClassDefinition JSWebAPIError::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CLASS_NAME,
+        0,
+        m_properties,
+        m_function,
+        initialize,
+        finalize,
+        NULL, // hasProperty,
+        NULL, // getProperty,
+        NULL, // setProperty,
+        NULL, // deleteProperty,
+        NULL, // getPropertyNames,
+        NULL, // callAsFunction,
+        NULL, // callAsConstructor,
+        NULL, // hasInstance,
+        NULL, // convertToType,
+};
+
+JSStaticFunction JSWebAPIError::m_function[] = {
+        { FUNCTION_TO_STRING, toString, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+JSStaticValue JSWebAPIError::m_properties[] = {
+        { PROPERTY_CODE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { PROPERTY_NAME, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { PROPERTY_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { PROPERTY_MESSAGE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSWebAPIError::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSWebAPIError::getClassRef()
+{
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+bool JSWebAPIError::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+JSObjectRef JSWebAPIError::createJSObject(JSContextRef context,
+        WebAPIError* webapiError)
+{
+    JSObjectRef jsObjectRef = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(webapiError));
+    if (NULL == jsObjectRef) {
+        LOGE("object creation error");
+        return NULL;
+    }
+    return jsObjectRef;
+}
+
+WebAPIError* JSWebAPIError::getPriv(JSContextRef context, JSObjectRef object)
+{
+    if (!JSValueIsObjectOfClass(context, object, getClassRef())) {
+        return NULL;
+    }
+
+    return static_cast<WebAPIError*>(JSObjectGetPrivate(object));
+}
+
+JSObjectRef JSWebAPIError::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Illegal constructor");
+}
+
+void JSWebAPIError::initialize(JSContextRef /*context*/, JSObjectRef /*object*/)
+{
+}
+
+void JSWebAPIError::finalize(JSObjectRef object)
+{
+    WebAPIError* webapiErrObj = static_cast<WebAPIError*>(JSObjectGetPrivate(
+            object));
+    if (webapiErrObj) {
+        JSObjectSetPrivate(object, NULL);
+        delete webapiErrObj;
+    }
+}
+
+JSValueRef JSWebAPIError::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* /*exception*/)
+{
+    WebAPIError* webapiErrObj = getPriv(context, object);
+    if (!webapiErrObj) {
+        LOGE("Private object is not set.");
+        return JSValueMakeUndefined(context);
+    }
+
+    try {
+        std::string propertyNameStr = JSUtil::JSStringToString(context,
+                propertyName);
+
+        if (PROPERTY_CODE == propertyNameStr) {
+            return JSUtil::toJSValueRef(context,
+                    static_cast<long>(webapiErrObj->getCode()));
+        }
+        else if (PROPERTY_NAME == propertyNameStr) {
+            return JSUtil::toJSValueRef(context, webapiErrObj->getName());
+        }
+        else if (PROPERTY_TYPE == propertyNameStr) {
+            return JSUtil::toJSValueRef(context, webapiErrObj->getName());
+        }
+        else if (PROPERTY_MESSAGE == propertyNameStr) {
+            return JSUtil::toJSValueRef(context, webapiErrObj->getMessage());
+        }
+    }
+    catch (const BasePlatformException & err) {
+        LOGE("Exception: %s", err.getMessage().c_str());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSWebAPIError::toString(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    WebAPIError* webapiErrObj = getPriv(context, thisObject);
+    if (!webapiErrObj) {
+        LOGE("Private object is not set.");
+        return NULL;
+    }
+
+    std::string name = webapiErrObj->getName();
+    std::string message = webapiErrObj->getMessage();
+
+    std::string result = name + ": " + message;
+
+    return JSUtil::toJSValueRef(context, result);
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/JSWebAPIError.h b/src/Common/JSWebAPIError.h
new file mode 100644 (file)
index 0000000..2ac0ebd
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _JS_WEBAPI_ERROR_H_
+#define _JS_WEBAPI_ERROR_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "JSWebAPIErrorFactory.h"
+
+#include "WebAPIError.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+class JSWebAPIErrorFactory;
+
+class JSWebAPIError {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    static JSObjectRef createJSObject(JSContextRef context,
+            WebAPIError* webapiError);
+
+    static WebAPIError* getPriv(JSContextRef context, JSObjectRef object);
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef toString(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSClassDefinition m_classInfo;
+
+    static JSStaticValue m_properties[];
+
+    static JSClassRef m_classRef;
+
+    static JSStaticFunction m_function[];
+
+    friend class JSWebAPIErrorFactory;
+};
+
+} // Common
+} // DeviceAPI
+
+#endif // _JS_WEBAPI_ERROR_H_
diff --git a/src/Common/JSWebAPIErrorFactory.cpp b/src/Common/JSWebAPIErrorFactory.cpp
new file mode 100644 (file)
index 0000000..4341329
--- /dev/null
@@ -0,0 +1,340 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSWebAPIErrorFactory.h"
+#include <map>
+#include <assert.h>
+#include "JSStringRefWrapper.h"
+#include "JSWebAPIException.h"
+#include "JSWebAPIError.h"
+
+namespace {
+const char* INDEX_SIZE_ERROR_NAME_STR = "IndexSizeError";
+const char* DOMSTRING_SIZE_ERROR_NAME_STR = "DOMStringSizeError";
+const char* HIERARCHY_REQUEST_ERROR_NAME_STR = "HierarchyRequestError";
+const char* WRONG_DOCUMENT_ERROR_NAME_STR = "WrongDocumentError";
+const char* INVALID_CHARACTER_ERROR_NAME_STR = "InvalidCharacterError";
+const char* NO_DATA_ALLOWED_ERROR_NAME_STR = "NoDataAllowedError";
+const char* NO_MODIFICATION_ALLOWED_ERROR_NAME_STR = "NoModificationAllowedError";
+const char* NOT_FOUND_ERROR_NAME_STR = "NotFoundError";
+const char* NOT_SUPPORTED_ERROR_NAME_STR = "NotSupportedError";
+const char* INUSE_ATTRIBUTE_ERROR_NAME_STR = "InuseAttributeError";
+const char* INVALID_STATE_ERROR_NAME_STR = "InvalidStateError";
+const char* SYNTAX_ERROR_NAME_STR = "SyntaxError";
+const char* INVALID_MODIFICATION_ERROR_NAME_STR = "InvalidModificationError";
+const char* NAMESPACE_ERROR_NAME_STR = "NamespaceError";
+const char* INVALID_ACCESS_ERROR_NAME_STR = "InvalidAccessError";
+const char* VALIDATION_ERROR_NAME_STR = "ValidationError";
+const char* TYPE_MISMATCH_ERROR_NAME_STR = "TypeMismatchError";
+const char* SECURITY_ERROR_NAME_STR = "SecurityError";
+const char* NETWORK_ERROR_NAME_STR = "NetworkError";
+const char* ABORT_ERROR_NAME_STR = "AbortError";
+const char* URL_MISMATCH_ERROR_NAME_STR = "URLMismatchError";
+const char* QUOTA_EXCEEDED_ERROR_NAME_STR = "QuotaExceededError";
+const char* TIMEOUT_ERROR_NAME_STR = "TimeoutError";
+const char* INVALID_NODE_TYPE_ERROR_NAME_STR = "InvalidNodeTypeError";
+const char* DATA_CLONE_ERROR_NAME_STR = "DataCloneError";
+const char* ENCODING_ERROR_NAME_STR = "EncodingError";
+
+const char* UNKNOWN_ERROR_NAME_STR = "UnknownError";
+const char* INVALID_VALUES_ERROR_NAME_STR = "InvalidValuesError";
+const char* IO_ERROR_NAME_STR = "IOError";
+const char* PERMISSION_DENIED_ERROR_NAME_STR = "PermissionDeniedError";
+const char* SERVICE_NOT_AVAILABLE_ERROR_NAME_STR = "ServiceNotAvailableError";
+
+const char* ECMA_ERROR_NAME_STR = "Error";
+const char* ECMA_EVAL_ERROR_NAME_STR = "EvalError";
+const char* ECMA_RANGE_ERROR_NAME_STR = "RangeError";
+const char* ECMA_REFERENCE_ERROR_NAME_STR = "ReferenceError";
+const char* ECMA_SYNTAX_ERROR_NAME_STR = "SyntaxError";
+const char* ECMA_TYPE_ERROR_NAME_STR = "TypeError";
+const char* ECMA_URI_ERROR_NAME_STR = "URIError";
+
+const char* CUSTOM_ERROR_NAME_STR = "CustomError";
+}
+
+namespace DeviceAPI {
+namespace Common {
+
+enum ErrorClass {
+    ERROR_TYPE_DOM,
+    ERROR_TYPE_TIZEN,
+    ERROR_TYPE_ECMA,
+    ERROR_TYPE_CUSTOM
+};
+
+struct DeviceAPIErrorProperties {
+    const ErrorClass type;
+    const unsigned int code;
+    const char* name;
+};
+typedef std::map<std::string, DeviceAPIErrorProperties> DeviceAPIErrorPropertiesMap;
+
+static DeviceAPIErrorPropertiesMap s_errorProperties = {
+        { INDEX_SIZE_ERROR_NAME_STR, { ERROR_TYPE_DOM, 1,
+                INDEX_SIZE_ERROR_NAME_STR } },
+        { DOMSTRING_SIZE_ERROR_NAME_STR, { ERROR_TYPE_DOM, 2,
+                DOMSTRING_SIZE_ERROR_NAME_STR } },
+        { HIERARCHY_REQUEST_ERROR_NAME_STR, { ERROR_TYPE_DOM, 3,
+                HIERARCHY_REQUEST_ERROR_NAME_STR } },
+        { WRONG_DOCUMENT_ERROR_NAME_STR, { ERROR_TYPE_DOM, 4,
+                WRONG_DOCUMENT_ERROR_NAME_STR } },
+        { INVALID_CHARACTER_ERROR_NAME_STR, { ERROR_TYPE_DOM, 5,
+                INVALID_CHARACTER_ERROR_NAME_STR } },
+        { NO_DATA_ALLOWED_ERROR_NAME_STR, { ERROR_TYPE_DOM, 6,
+                NO_DATA_ALLOWED_ERROR_NAME_STR } },
+        { NO_MODIFICATION_ALLOWED_ERROR_NAME_STR, { ERROR_TYPE_DOM, 7,
+                NO_MODIFICATION_ALLOWED_ERROR_NAME_STR } },
+        { NOT_FOUND_ERROR_NAME_STR, { ERROR_TYPE_DOM, 8,
+                NOT_FOUND_ERROR_NAME_STR } },
+        { NOT_SUPPORTED_ERROR_NAME_STR, { ERROR_TYPE_DOM, 9,
+                NOT_SUPPORTED_ERROR_NAME_STR } },
+        { INUSE_ATTRIBUTE_ERROR_NAME_STR, { ERROR_TYPE_DOM, 10,
+                INUSE_ATTRIBUTE_ERROR_NAME_STR } },
+        { INVALID_STATE_ERROR_NAME_STR, { ERROR_TYPE_DOM, 11,
+                INVALID_STATE_ERROR_NAME_STR } },
+        { SYNTAX_ERROR_NAME_STR, { ERROR_TYPE_DOM, 12,
+                SYNTAX_ERROR_NAME_STR } },
+        { INVALID_MODIFICATION_ERROR_NAME_STR, { ERROR_TYPE_DOM, 13,
+                INVALID_MODIFICATION_ERROR_NAME_STR } },
+        { NAMESPACE_ERROR_NAME_STR, { ERROR_TYPE_DOM, 14,
+                NAMESPACE_ERROR_NAME_STR } },
+        { INVALID_ACCESS_ERROR_NAME_STR, { ERROR_TYPE_DOM, 15,
+                INVALID_ACCESS_ERROR_NAME_STR } },
+        { VALIDATION_ERROR_NAME_STR, { ERROR_TYPE_DOM, 16,
+                VALIDATION_ERROR_NAME_STR } },
+        { TYPE_MISMATCH_ERROR_NAME_STR, { ERROR_TYPE_DOM, 17,
+                TYPE_MISMATCH_ERROR_NAME_STR } },
+        { SECURITY_ERROR_NAME_STR, { ERROR_TYPE_DOM, 18,
+                SECURITY_ERROR_NAME_STR } },
+        { NETWORK_ERROR_NAME_STR, { ERROR_TYPE_DOM, 19,
+                NETWORK_ERROR_NAME_STR } },
+        { ABORT_ERROR_NAME_STR, { ERROR_TYPE_DOM, 20,
+                ABORT_ERROR_NAME_STR } },
+        { URL_MISMATCH_ERROR_NAME_STR, { ERROR_TYPE_DOM, 21,
+                URL_MISMATCH_ERROR_NAME_STR } },
+        { QUOTA_EXCEEDED_ERROR_NAME_STR, { ERROR_TYPE_DOM, 22,
+                QUOTA_EXCEEDED_ERROR_NAME_STR } },
+        { TIMEOUT_ERROR_NAME_STR, { ERROR_TYPE_DOM, 23,
+                TIMEOUT_ERROR_NAME_STR } },
+        { INVALID_NODE_TYPE_ERROR_NAME_STR, { ERROR_TYPE_DOM, 24,
+                INVALID_NODE_TYPE_ERROR_NAME_STR } },
+        { DATA_CLONE_ERROR_NAME_STR, { ERROR_TYPE_DOM, 25,
+                DATA_CLONE_ERROR_NAME_STR } },
+        { ENCODING_ERROR_NAME_STR, { ERROR_TYPE_DOM, 0,
+                ENCODING_ERROR_NAME_STR } },
+        { UNKNOWN_ERROR_NAME_STR, { ERROR_TYPE_TIZEN, 0,
+                UNKNOWN_ERROR_NAME_STR } },
+        { INVALID_VALUES_ERROR_NAME_STR, { ERROR_TYPE_TIZEN, 0,
+                INVALID_VALUES_ERROR_NAME_STR } },
+        { IO_ERROR_NAME_STR, { ERROR_TYPE_TIZEN, 0,
+                IO_ERROR_NAME_STR } },
+        { PERMISSION_DENIED_ERROR_NAME_STR, { ERROR_TYPE_TIZEN, 0,
+                PERMISSION_DENIED_ERROR_NAME_STR } },
+        { SERVICE_NOT_AVAILABLE_ERROR_NAME_STR, { ERROR_TYPE_TIZEN, 0,
+                SERVICE_NOT_AVAILABLE_ERROR_NAME_STR } },
+};
+
+static DeviceAPIErrorProperties s_customErrorProperties = {
+        ERROR_TYPE_CUSTOM,
+        0,
+        CUSTOM_ERROR_NAME_STR };
+
+const std::string JSWebAPIErrorFactory::INDEX_SIZE_ERROR =
+        INDEX_SIZE_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::DOMSTRING_SIZE_ERROR =
+        DOMSTRING_SIZE_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::HIERARCHY_REQUEST_ERROR =
+        HIERARCHY_REQUEST_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::WRONG_DOCUMENT_ERROR =
+        WRONG_DOCUMENT_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::INVALID_CHARACTER_ERROR =
+        INVALID_CHARACTER_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::NO_DATA_ALLOWED_ERROR =
+        NO_DATA_ALLOWED_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::NO_MODIFICATION_ALLOWED_ERROR =
+        NO_MODIFICATION_ALLOWED_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::NOT_FOUND_ERROR =
+        NOT_FOUND_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR =
+        NOT_SUPPORTED_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::INUSE_ATTRIBUTE_ERROR =
+        INUSE_ATTRIBUTE_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::INVALID_STATE_ERROR =
+        INVALID_STATE_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::SYNTAX_ERROR =
+        SYNTAX_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::INVALID_MODIFICATION_ERROR =
+        INVALID_MODIFICATION_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::NAMESPACE_ERROR =
+        NAMESPACE_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::INVALID_ACCESS_ERROR =
+        INVALID_ACCESS_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::VALIDATION_ERROR =
+        VALIDATION_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR =
+        TYPE_MISMATCH_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::SECURITY_ERROR =
+        SECURITY_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::NETWORK_ERROR =
+        NETWORK_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::ABORT_ERROR =
+        ABORT_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::URL_MISMATCH_ERROR =
+        URL_MISMATCH_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::QUOTA_EXCEEDED_ERROR =
+        QUOTA_EXCEEDED_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::TIMEOUT_ERROR =
+        TIMEOUT_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::INVALID_NODE_TYPE_ERROR =
+        INVALID_NODE_TYPE_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::DATA_CLONE_ERROR =
+        DATA_CLONE_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::ENCODING_ERROR =
+        ENCODING_ERROR_NAME_STR;
+
+const std::string JSWebAPIErrorFactory::UNKNOWN_ERROR =
+        UNKNOWN_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::INVALID_VALUES_ERROR =
+        INVALID_VALUES_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::IO_ERROR =
+        IO_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::PERMISSION_DENIED_ERROR =
+        PERMISSION_DENIED_ERROR_NAME_STR;
+const std::string JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR =
+        SERVICE_NOT_AVAILABLE_ERROR_NAME_STR;
+
+JSWebAPIErrorFactory::JSWebAPIErrorFactory()
+{
+}
+
+JSWebAPIErrorFactory::~JSWebAPIErrorFactory()
+{
+}
+
+JSObjectRef JSWebAPIErrorFactory::makeErrorObject(JSContextRef context,
+        const std::string& name,
+        const std::string& message)
+{
+    return createErrorObject(context, name, message, false);
+}
+
+JSObjectRef JSWebAPIErrorFactory::makeErrorObject(JSContextRef context,
+        const BasePlatformException& error)
+{
+    return createErrorObject(context, error.getName(), error.getMessage(), false);
+}
+
+JSObjectRef JSWebAPIErrorFactory::postException(JSContextRef context,
+        JSValueRef* exception,
+        const std::string& name,
+        const std::string& message)
+{
+    assert(exception && "Exception object can't be NULL.");
+
+    JSObjectRef exceptionObj = createErrorObject(context, name, message, true);
+
+    *exception = exceptionObj;
+
+    return exceptionObj;
+}
+
+JSObjectRef JSWebAPIErrorFactory::postException(JSContextRef context,
+        JSValueRef* exception,
+        const BasePlatformException& error)
+{
+    assert(exception && "Exception object can't be NULL.");
+
+    return postException(context, exception, error.getName(), error.getMessage());
+}
+
+JSObjectRef JSWebAPIErrorFactory::createErrorObject(JSContextRef context,
+        const std::string& name,
+        const std::string& message,
+        const bool isException)
+{
+    JSObjectRef jsErrorObject = NULL;
+
+    DeviceAPIErrorProperties *properties;
+
+    DeviceAPIErrorPropertiesMap::iterator iter = s_errorProperties.find(name);
+    if (iter != s_errorProperties.end()) {
+        properties = &(iter->second);
+    }
+    else {
+        properties = &s_customErrorProperties;
+    }
+
+    if (ERROR_TYPE_ECMA == properties->type) {
+        return createECMAErrorObject(context, properties->name, message);
+    }
+
+    WebAPIError *errorObject = NULL;
+    switch (properties->type) {
+        case ERROR_TYPE_DOM:
+        case ERROR_TYPE_TIZEN:
+            errorObject = new WebAPIError(properties->code, properties->name,
+                    message);
+            break;
+        case ERROR_TYPE_CUSTOM:
+            errorObject = new WebAPIError(0, name, message);
+            break;
+        case ERROR_TYPE_ECMA: // Cannot happen
+        default:
+            errorObject = new WebAPIError(0, "Error", message);
+            break;
+    }
+
+    if (isException) {
+        jsErrorObject = JSWebAPIException::createJSObject(context, errorObject);
+    }
+    else {
+        jsErrorObject = JSWebAPIError::createJSObject(context, errorObject);
+    }
+
+    return jsErrorObject;
+}
+
+JSObjectRef JSWebAPIErrorFactory::createECMAErrorObject(JSContextRef context,
+        const std::string& name,
+        const std::string& message)
+{
+    assert( (name == ECMA_ERROR_NAME_STR || name == ECMA_EVAL_ERROR_NAME_STR
+            || name == ECMA_RANGE_ERROR_NAME_STR
+            || name == ECMA_REFERENCE_ERROR_NAME_STR
+            || name == ECMA_SYNTAX_ERROR_NAME_STR
+            || name == ECMA_TYPE_ERROR_NAME_STR
+            || name == ECMA_URI_ERROR_NAME_STR )
+            && "Name MUST be one of NativeError objects.");
+
+    std::string jsCodeStr;
+    jsCodeStr = "new " + name + "(";
+    if (!message.empty()) {
+        jsCodeStr += "\"" + message + "\"";
+    }
+    jsCodeStr += ");";
+
+    JSStringRefWrapper jsCode(jsCodeStr);
+
+    JSValueRef errValue = JSEvaluateScript(context, jsCode.get(), NULL, NULL, 0,
+            NULL);
+
+    return JSValueToObject(context, errValue, NULL);
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/JSWebAPIErrorFactory.h b/src/Common/JSWebAPIErrorFactory.h
new file mode 100644 (file)
index 0000000..a56ea1b
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _JS_WEBAPI_ERROR_FACTORY_H_
+#define _JS_WEBAPI_ERROR_FACTORY_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+#include "PlatformException.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+class JSWebAPIErrorFactory {
+public:
+    JSWebAPIErrorFactory();
+    virtual ~JSWebAPIErrorFactory();
+
+    static JSObjectRef makeErrorObject(JSContextRef context,
+            const std::string& name,
+            const std::string& message = std::string());
+
+    static JSObjectRef makeErrorObject(JSContextRef context,
+            const BasePlatformException& error);
+
+    static JSObjectRef postException(JSContextRef context,
+            JSValueRef* exception,
+            const std::string& name,
+            const std::string& message = std::string());
+
+    static JSObjectRef postException(JSContextRef context,
+            JSValueRef* exception,
+            const BasePlatformException& error);
+
+    static const std::string INDEX_SIZE_ERROR;
+    static const std::string DOMSTRING_SIZE_ERROR;
+    static const std::string HIERARCHY_REQUEST_ERROR;
+    static const std::string WRONG_DOCUMENT_ERROR;
+    static const std::string INVALID_CHARACTER_ERROR;
+    static const std::string NO_DATA_ALLOWED_ERROR;
+    static const std::string NO_MODIFICATION_ALLOWED_ERROR;
+    static const std::string NOT_FOUND_ERROR;
+    static const std::string NOT_SUPPORTED_ERROR;
+    static const std::string INUSE_ATTRIBUTE_ERROR;
+    static const std::string INVALID_STATE_ERROR;
+    static const std::string SYNTAX_ERROR;
+    static const std::string INVALID_MODIFICATION_ERROR;
+    static const std::string NAMESPACE_ERROR;
+    static const std::string INVALID_ACCESS_ERROR;
+    static const std::string VALIDATION_ERROR;
+    static const std::string TYPE_MISMATCH_ERROR;
+    static const std::string SECURITY_ERROR;
+    static const std::string NETWORK_ERROR;
+    static const std::string ABORT_ERROR;
+    static const std::string URL_MISMATCH_ERROR;
+    static const std::string QUOTA_EXCEEDED_ERROR;
+    static const std::string TIMEOUT_ERROR;
+    static const std::string INVALID_NODE_TYPE_ERROR;
+    static const std::string DATA_CLONE_ERROR;
+    static const std::string ENCODING_ERROR;
+
+    static const std::string UNKNOWN_ERROR;
+    static const std::string INVALID_VALUES_ERROR;
+    static const std::string IO_ERROR;
+    static const std::string PERMISSION_DENIED_ERROR;
+    static const std::string SERVICE_NOT_AVAILABLE_ERROR;
+
+private:
+    static JSObjectRef createErrorObject(JSContextRef context,
+            const std::string& name,
+            const std::string& message,
+            const bool isException);
+
+    static JSObjectRef createECMAErrorObject(JSContextRef context,
+            const std::string& name,
+            const std::string& message);
+};
+
+} // Common
+} // DeviceAPI
+
+#endif // _JS_WEBAPI_ERROR_FACTORY_H_
diff --git a/src/Common/JSWebAPIException.cpp b/src/Common/JSWebAPIException.cpp
new file mode 100644 (file)
index 0000000..b732398
--- /dev/null
@@ -0,0 +1,330 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSWebAPIException.h"
+#include <string>
+#include <map>
+#include "JSUtil.h"
+#include "JSStringRefWrapper.h"
+#include "Logger.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+namespace {
+const char* CLASS_NAME = "WebAPIException";
+
+const char* PROPERTY_CODE = "code";
+const char* PROPERTY_NAME ="name";
+const char* PROPERTY_TYPE ="type";
+const char* PROPERTY_MESSAGE ="message";
+
+const char* PROPERTY_INDEX_SIZE_ERR = "INDEX_SIZE_ERR";
+const char* PROPERTY_DOMSTRING_SIZE_ERR = "DOMSTRING_SIZE_ERR";
+const char* PROPERTY_HIERARCHY_REQUEST_ERR = "HIERARCHY_REQUEST_ERR";
+const char* PROPERTY_WRONG_DOCUMENT_ERR = "WRONG_DOCUMENT_ERR";
+const char* PROPERTY_INVALID_CHARACTER_ERR = "INVALID_CHARACTER_ERR";
+const char* PROPERTY_NO_DATA_ALLOWED_ERR = "NO_DATA_ALLOWED_ERR";
+const char* PROPERTY_NO_MODIFICATION_ALLOWED_ERR = "NO_MODIFICATION_ALLOWED_ERR";
+const char* PROPERTY_NOT_FOUND_ERR = "NOT_FOUND_ERR";
+const char* PROPERTY_NOT_SUPPORTED_ERR = "NOT_SUPPORTED_ERR";
+const char* PROPERTY_INUSE_ATTRIBUTE_ERR = "INUSE_ATTRIBUTE_ERR";
+const char* PROPERTY_INVALID_STATE_ERR = "INVALID_STATE_ERR";
+const char* PROPERTY_SYNTAX_ERR = "SYNTAX_ERR";
+const char* PROPERTY_INVALID_MODIFICATION_ERR = "INVALID_MODIFICATION_ERR";
+const char* PROPERTY_NAMESPACE_ERR = "NAMESPACE_ERR";
+const char* PROPERTY_INVALID_ACCESS_ERR = "INVALID_ACCESS_ERR";
+const char* PROPERTY_VALIDATION_ERR = "VALIDATION_ERR";
+const char* PROPERTY_TYPE_MISMATCH_ERR = "TYPE_MISMATCH_ERR";
+const char* PROPERTY_SECURITY_ERR = "SECURITY_ERR";
+const char* PROPERTY_NETWORK_ERR = "NETWORK_ERR";
+const char* PROPERTY_ABORT_ERR = "ABORT_ERR";
+const char* PROPERTY_URL_MISMATCH_ERR = "URL_MISMATCH_ERR";
+const char* PROPERTY_QUOTA_EXCEEDED_ERR = "QUOTA_EXCEEDED_ERR";
+const char* PROPERTY_TIMEOUT_ERR = "TIMEOUT_ERR";
+const char* PROPERTY_INVALID_NODE_TYPE_ERR = "INVALID_NODE_TYPE_ERR";
+const char* PROPERTY_DATA_CLONE_ERR = "DATA_CLONE_ERR";
+
+const char* FUNCTION_TO_STRING = "toString";
+}
+
+typedef std::map<std::string, int> DeviceAPIErrorCodeMap;
+
+static DeviceAPIErrorCodeMap errorCodes = {
+        { PROPERTY_INDEX_SIZE_ERR, 1 },
+        { PROPERTY_DOMSTRING_SIZE_ERR, 2 },
+        { PROPERTY_HIERARCHY_REQUEST_ERR, 3 },
+        { PROPERTY_WRONG_DOCUMENT_ERR, 4 },
+        { PROPERTY_INVALID_CHARACTER_ERR, 5 },
+        { PROPERTY_NO_DATA_ALLOWED_ERR, 6 },
+        { PROPERTY_NO_MODIFICATION_ALLOWED_ERR, 7 },
+        { PROPERTY_NOT_FOUND_ERR, 8 },
+        { PROPERTY_NOT_SUPPORTED_ERR, 9 },
+        { PROPERTY_INUSE_ATTRIBUTE_ERR, 10 },
+        { PROPERTY_INVALID_STATE_ERR, 11 },
+        { PROPERTY_SYNTAX_ERR, 12 },
+        { PROPERTY_INVALID_MODIFICATION_ERR, 13 },
+        { PROPERTY_NAMESPACE_ERR, 14 },
+        { PROPERTY_INVALID_ACCESS_ERR, 15 },
+        { PROPERTY_VALIDATION_ERR, 16 },
+        { PROPERTY_TYPE_MISMATCH_ERR, 17 },
+        { PROPERTY_SECURITY_ERR, 18 },
+        { PROPERTY_NETWORK_ERR, 19 },
+        { PROPERTY_ABORT_ERR, 20 },
+        { PROPERTY_URL_MISMATCH_ERR, 21 },
+        { PROPERTY_QUOTA_EXCEEDED_ERR, 22 },
+        { PROPERTY_TIMEOUT_ERR, 23 },
+        { PROPERTY_INVALID_NODE_TYPE_ERR, 24 },
+        { PROPERTY_DATA_CLONE_ERR, 25 } };
+
+JSClassRef JSWebAPIException::m_classRef = NULL;
+
+JSClassDefinition JSWebAPIException::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CLASS_NAME,
+        0,
+        m_properties,
+        m_function,
+        initialize,
+        finalize,
+        NULL, // hasProperty,
+        NULL, // getProperty,
+        NULL, // setProperty,
+        NULL, // deleteProperty,
+        NULL, // getPropertyNames,
+        NULL, // callAsFunction,
+        NULL, // callAsConstructor,
+        NULL, // hasInstance,
+        NULL, // convertToType,
+};
+
+JSStaticFunction JSWebAPIException::m_function[] = {
+        { FUNCTION_TO_STRING, toString, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+JSStaticValue JSWebAPIException::m_properties[] = {
+        { PROPERTY_CODE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { PROPERTY_NAME, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { PROPERTY_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { PROPERTY_MESSAGE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { PROPERTY_INDEX_SIZE_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_DOMSTRING_SIZE_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_HIERARCHY_REQUEST_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_WRONG_DOCUMENT_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_INVALID_CHARACTER_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_NO_DATA_ALLOWED_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_NO_MODIFICATION_ALLOWED_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_NOT_FOUND_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_NOT_SUPPORTED_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_INUSE_ATTRIBUTE_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_INVALID_STATE_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_SYNTAX_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_INVALID_MODIFICATION_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_NAMESPACE_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_INVALID_ACCESS_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_VALIDATION_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_TYPE_MISMATCH_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_SECURITY_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_NETWORK_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_ABORT_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_URL_MISMATCH_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_QUOTA_EXCEEDED_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_TIMEOUT_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_INVALID_NODE_TYPE_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { PROPERTY_DATA_CLONE_ERR, getStaticProperty, NULL,
+                kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSWebAPIException::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSWebAPIException::getClassRef()
+{
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+bool JSWebAPIException::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+JSObjectRef JSWebAPIException::createJSObject(JSContextRef context,
+        WebAPIError* webapiError)
+{
+    JSObjectRef jsObjectRef = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(webapiError));
+    if (NULL == jsObjectRef) {
+        LOGE("object creation error");
+        return NULL;
+    }
+    return jsObjectRef;
+}
+
+WebAPIError* JSWebAPIException::getPriv(JSContextRef context,
+        JSObjectRef object)
+{
+    if (!JSValueIsObjectOfClass(context, object, getClassRef())) {
+        return NULL;
+    }
+
+    return static_cast<WebAPIError*>(JSObjectGetPrivate(object));
+}
+
+JSObjectRef JSWebAPIException::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Illegal constructor");
+}
+
+void JSWebAPIException::initializeConstructor(JSContextRef context,
+        JSObjectRef constructor)
+{
+    for (DeviceAPIErrorCodeMap::iterator iter = errorCodes.begin();
+            iter != errorCodes.end(); iter++) {
+        JSStringRefWrapper name(iter->first);
+        JSValueRef value = JSValueMakeNumber(context,
+                static_cast<double>(iter->second));
+        JSObjectSetProperty(context, constructor, name.get(), value,
+                kJSPropertyAttributeReadOnly, NULL);
+    }
+}
+
+void JSWebAPIException::initialize(JSContextRef /*context*/,
+        JSObjectRef /*object*/)
+{
+}
+
+void JSWebAPIException::finalize(JSObjectRef /*object*/)
+{
+}
+
+JSValueRef JSWebAPIException::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* /*exception*/)
+{
+    WebAPIError* webapiErrObj = getPriv(context, object);
+    if (!webapiErrObj) {
+        LOGE("Private object is not set.");
+        return JSValueMakeUndefined(context);
+    }
+
+    try {
+        std::string propertyNameStr = JSUtil::JSStringToString(context,
+                propertyName);
+
+        if (PROPERTY_CODE == propertyNameStr) {
+            return JSUtil::toJSValueRef(context,
+                    static_cast<long>(webapiErrObj->getCode()));
+        }
+        else if (PROPERTY_NAME == propertyNameStr) {
+            return JSUtil::toJSValueRef(context, webapiErrObj->getName());
+        }
+        else if (PROPERTY_TYPE == propertyNameStr) {
+            return JSUtil::toJSValueRef(context, webapiErrObj->getName());
+        }
+        else if (PROPERTY_MESSAGE == propertyNameStr) {
+            return JSUtil::toJSValueRef(context, webapiErrObj->getMessage());
+        }
+    }
+    catch (const BasePlatformException & err) {
+        LOGE("Exception: %s", err.getMessage().c_str());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSWebAPIException::getStaticProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* /*exception*/)
+{
+    try {
+        std::string propertyNameStr = JSUtil::JSStringToString(context,
+                propertyName);
+
+        DeviceAPIErrorCodeMap::iterator iter = errorCodes.find(propertyNameStr);
+        if (iter != errorCodes.end()) {
+            return JSUtil::toJSValueRef(context, static_cast<long>(iter->second));
+        }
+    }
+    catch (const BasePlatformException & err) {
+        LOGE("Exception: %s", err.getMessage().c_str());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSWebAPIException::toString(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    WebAPIError* webapiErrObj = getPriv(context, thisObject);
+    if (!webapiErrObj) {
+        LOGE("Private object is not set.");
+        return NULL;
+    }
+
+    std::string name = webapiErrObj->getName();
+    std::string message = webapiErrObj->getMessage();
+
+    std::string result = name + ": " + message;
+
+    return JSUtil::toJSValueRef(context, result);
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/JSWebAPIException.h b/src/Common/JSWebAPIException.h
new file mode 100644 (file)
index 0000000..288c36d
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _JS_WEBAPI_EXCEPTION_H_
+#define _JS_WEBAPI_EXCEPTION_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "JSWebAPIErrorFactory.h"
+
+#include "WebAPIError.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+class JSWebAPIErrorFactory;
+
+class JSWebAPIException {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static void initializeConstructor(JSContextRef context,
+            JSObjectRef constructor);
+
+private:
+    static JSObjectRef createJSObject(JSContextRef context,
+            WebAPIError* webapiError);
+
+    static WebAPIError* getPriv(JSContextRef context, JSObjectRef object);
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getStaticProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef toString(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSClassDefinition m_classInfo;
+
+    static JSStaticValue m_properties[];
+
+    static JSClassRef m_classRef;
+
+    static JSStaticFunction m_function[];
+
+    friend class JSWebAPIErrorFactory;
+};
+
+} // Common
+} // DeviceAPI
+
+#endif // _JS_WEBAPI_EXCEPTION_H_
diff --git a/src/Common/Logger.h b/src/Common/Logger.h
new file mode 100755 (executable)
index 0000000..2821398
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_COMMON_LOGGER_H__
+#define __TIZEN_COMMON_LOGGER_H__
+
+#include <dlog.h>
+#include <sstream>
+
+#undef LOG_TAG
+#define LOG_TAG "WRT_PLUGINS/TIZEN"
+
+#define _LOGGER(prio, fmt, args...) \
+    do { \
+        std::ostringstream platformLog; \
+        platformLog << "%s: %s(%d) > "; \
+        platformLog << fmt; \
+        print_log(prio, LOG_TAG, platformLog.str().c_str(), __MODULE__, __func__, __LINE__, ##args); \
+    } while(0)
+
+#define LoggerD(fmt, args...)   _LOGGER(DLOG_DEBUG, fmt, ##args)
+
+#define LoggerI(fmt, args...)   _LOGGER(DLOG_INFO, fmt, ##args)
+#define LoggerW(fmt, args...)   _LOGGER(DLOG_WARN, fmt, ##args)
+#define LoggerE(fmt, args...)   _LOGGER(DLOG_ERROR, fmt, ##args)
+
+
+
+#define _SLOGGER(prio, fmt, args...) \
+    do { \
+        std::ostringstream platformLog; \
+        platformLog << "%s: %s(%d) > [SECURE_LOG] "; \
+        platformLog << fmt; \
+        print_log(prio, LOG_TAG, platformLog.str().c_str(), __MODULE__, __func__, __LINE__, ##args); \
+    } while(0)
+
+#define SLoggerD(fmt, args...)  _SLOGGER(DLOG_DEBUG, fmt, ##args)
+#define SLoggerI(fmt, args...)  _SLOGGER(DLOG_INFO, fmt, ##args)
+#define SLoggerE(fmt, args...)  _SLOGGER(DLOG_ERROR, fmt, ##args)
+
+#endif // __TIZEN_COMMON_LOGGER_H__
diff --git a/src/Common/MultiCallbackUserData.cpp b/src/Common/MultiCallbackUserData.cpp
new file mode 100755 (executable)
index 0000000..73328e1
--- /dev/null
@@ -0,0 +1,169 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MultiCallbackUserData.h"
+#include "GlobalContextManager.h"
+#include "PlatformException.h"
+#include "WebKitProxy.h"
+#include "JSUtil.h"
+#include "Logger.h"
+
+using namespace std;
+
+namespace DeviceAPI {
+namespace Common {
+
+MultiCallbackUserData::MultiCallbackUserData(JSContextRef global_ctx) :
+        m_context(global_ctx),
+        m_object(NULL)
+{
+}
+
+MultiCallbackUserData::MultiCallbackUserData(JSContextRef global_ctx,
+        JSObjectRef object) :
+    m_context(global_ctx),
+    m_object(object)
+{
+    if(m_object) {
+        JSValueProtect(m_context, m_object);
+    }
+}
+
+MultiCallbackUserData::~MultiCallbackUserData()
+{
+    if(!GlobalContextManager::getInstance()->isAliveGlobalContext(m_context)) {
+        //Remove Callback functions in Native Map
+        CallbackMapT::iterator itr;
+        for(itr = m_callbacks.begin(); itr != m_callbacks.end(); ++itr) {
+            if(itr->second) {
+                JSValueUnprotect(m_context, itr->second);
+            }
+        }
+
+        //Remove Callback Object
+        if(m_object) {
+            JSValueUnprotect(m_context, m_object);
+        }
+    }
+}
+
+void MultiCallbackUserData::setCallback(const string &key, JSObjectRef callback)
+{
+    // Callback Object Case
+    if(m_object) {
+        JSUtil::setProperty(m_context, m_object, key.c_str(), callback,
+                kJSPropertyAttributeNone);
+        return;
+    }
+
+    // Callback function Case
+    CallbackMapT::iterator itr = m_callbacks.find(key);
+    if(itr != m_callbacks.end() && itr->second) {
+        JSValueUnprotect(m_context, itr->second);
+    }
+
+    if(callback) {
+        JSValueProtect(m_context, callback);
+    }
+
+    m_callbacks[key] = callback;
+}
+
+
+void MultiCallbackUserData::invokeCallback(const std::string &key, int count,
+        JSValueRef obj[])
+{
+    if(!GlobalContextManager::getInstance()->isAliveGlobalContext(m_context)) {
+        LOGE("context was closed");
+        return;
+    }
+
+    // Callback Object case
+    if(m_object) {
+        try {
+            // Getting callback value
+            JSValueRef callbackValue = JSUtil::getProperty(m_context, m_object,
+                     key.c_str());
+
+            // Testing existing
+            if(JSValueIsUndefined(m_context, callbackValue)) {
+                LOGE("There is no such callback: [%s]", key.c_str());
+                return;
+            }
+
+            JSObjectRef callbackObject = JSUtil::JSValueToObject(m_context, callbackValue);
+
+            // Testing type validation
+            if(!JSObjectIsFunction(m_context, callbackObject)) {
+                LOGE("[%s] is not function", key.c_str());
+                return;
+            }
+
+            JSValueRef exception = NULL;
+            JSObjectCallAsFunction(m_context, callbackObject, NULL, count, obj,
+                     &exception);
+
+            if(exception){
+                WebKitProxy::reportException(m_context, exception);
+            }
+            // check Exception in function call
+            if(exception != NULL) {
+                throw UnknownException(m_context, exception);
+            }
+        } catch(const BasePlatformException& err) {
+            LOGE("Error in Callback invoke - %s:%s", err.getName().c_str(),
+                    err.getMessage().c_str());
+        }
+        return;
+    }
+
+    // Callback function case
+    CallbackMapT::iterator itr = m_callbacks.find(key);
+    if(itr == m_callbacks.end()) {
+        LOGE("There is no such callback: [%s]", key.c_str());
+        return;
+    }
+
+    if(itr->second) {
+        JSValueRef exception = NULL;
+        JSObjectCallAsFunction(m_context, itr->second , NULL, count, obj, &exception);
+        if(exception)
+            WebKitProxy::reportException(m_context, exception);
+    }
+    else {
+        LOGE("The callback: [%s] is NULL", key.c_str());
+    }
+}
+
+void MultiCallbackUserData::invokeCallback(const std::string &key, JSValueRef obj)
+{
+    JSValueRef args[1] = {obj};
+    invokeCallback(key, 1, args);
+}
+
+void MultiCallbackUserData::invokeCallback(const std::string &key)
+{
+    invokeCallback(key, 0, NULL);
+}
+
+JSContextRef MultiCallbackUserData::getContext() const
+{
+    return m_context;
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/MultiCallbackUserData.h b/src/Common/MultiCallbackUserData.h
new file mode 100755 (executable)
index 0000000..22a5b18
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_COMMON_MULTI_CALLBACK_USER_DATA_H__
+#define __TIZEN_COMMON_MULTI_CALLBACK_USER_DATA_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <string>
+#include <map>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Common {
+
+class MultiCallbackUserData;
+typedef std::shared_ptr<MultiCallbackUserData> MultiCallbackUserDataPtr;
+
+class MultiCallbackUserData {
+public:
+    MultiCallbackUserData(JSContextRef global_ctx);
+    MultiCallbackUserData(JSContextRef global_ctx, JSObjectRef object);
+    virtual ~MultiCallbackUserData();
+
+    JSContextRef getContext() const;
+    void setCallback(const std::string &key, JSObjectRef callback);
+
+    void invokeCallback(const std::string &key);
+    void invokeCallback(const std::string &key, JSValueRef obj);
+    void invokeCallback(const std::string &key, int count, JSValueRef obj[]);
+
+private:
+    JSContextRef m_context;
+    JSObjectRef m_object;
+    typedef std::map<const std::string, JSObjectRef> CallbackMapT;
+    CallbackMapT m_callbacks;
+};
+
+} // Common
+} // DeviceAPI
+
+#endif //__TIZEN_COMMON_MULTI_CALLBACK_USER_DATA_H__
diff --git a/src/Common/PlatformException.cpp b/src/Common/PlatformException.cpp
new file mode 100644 (file)
index 0000000..531d6f4
--- /dev/null
@@ -0,0 +1,223 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PlatformException.h"
+#include "JSUtil.h"
+#include "JSWebAPIErrorFactory.h"
+#include <CommonsJavaScript/Converter.h>
+#include "Logger.h"
+
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Common {
+
+namespace {
+
+const char* PROPERTY_MESSAGE = "message";
+const char* PROPERTY_NAME = "name";
+
+}
+
+BasePlatformException::BasePlatformException(const char* name,
+        const char* message) :
+        mName(name), mMessage(message)
+{
+}
+
+BasePlatformException::BasePlatformException(JSContextRef context,
+        JSValueRef value)
+{
+    JSObjectRef object = JSValueToObject(context, value, NULL);
+    if (!object) {
+        return;
+    }
+
+    JSValueRef message = JSUtil::getProperty(context, object, PROPERTY_MESSAGE);
+    JSValueRef name = JSUtil::getProperty(context, object, PROPERTY_NAME);
+
+    try {
+        Converter convert(context);
+        if (!JSValueIsUndefined(context, message)) {
+            mMessage = convert.toString(message);
+        }
+        if (!JSValueIsUndefined(context, name)) {
+            mName = convert.toString(name);
+        }
+    }
+    catch (const ConversionException& err) {
+        LOGE("Cannot convert name or message");
+    }
+}
+
+BasePlatformException::~BasePlatformException()
+{
+}
+
+std::string BasePlatformException::getName() const
+{
+    return mName;
+}
+
+std::string BasePlatformException::getMessage() const
+{
+    return mMessage;
+}
+
+TypeMismatchException::TypeMismatchException(const char* message) :
+        BasePlatformException(JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR.c_str(),
+            message)
+{
+}
+TypeMismatchException::TypeMismatchException(JSContextRef ctx,
+        JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR.c_str();
+}
+
+InvalidValuesException::InvalidValuesException(const char* message) :
+        BasePlatformException(JSWebAPIErrorFactory::INVALID_VALUES_ERROR.c_str(),
+            message)
+{
+}
+InvalidValuesException::InvalidValuesException(JSContextRef ctx,
+        JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::INVALID_VALUES_ERROR.c_str();
+}
+
+IOException::IOException(const char* message) :
+        BasePlatformException(JSWebAPIErrorFactory::IO_ERROR.c_str(), message)
+{
+}
+IOException::IOException(JSContextRef ctx, JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::IO_ERROR.c_str();
+}
+
+UnknownException::UnknownException(const char* message) :
+        BasePlatformException(JSWebAPIErrorFactory::UNKNOWN_ERROR.c_str(),
+            message)
+{
+}
+UnknownException::UnknownException(JSContextRef ctx, JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::UNKNOWN_ERROR.c_str();
+}
+
+ServiceNotAvailableException::ServiceNotAvailableException(const char* message) :
+        BasePlatformException(
+            JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR.c_str(), message)
+{
+}
+ServiceNotAvailableException::ServiceNotAvailableException(JSContextRef ctx,
+        JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR.c_str();
+}
+
+SecurityException::SecurityException(const char* message) :
+        BasePlatformException(JSWebAPIErrorFactory::SECURITY_ERROR.c_str(), message)
+{
+}
+SecurityException::SecurityException(JSContextRef ctx, JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::SECURITY_ERROR.c_str();
+}
+
+NotSupportedException::NotSupportedException(const char* message) :
+        BasePlatformException(JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR.c_str(),
+            message)
+{
+}
+NotSupportedException::NotSupportedException(JSContextRef ctx,
+        JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR.c_str();
+}
+
+NotFoundException::NotFoundException(const char* message) :
+        BasePlatformException(JSWebAPIErrorFactory::NOT_FOUND_ERROR.c_str(),
+            message)
+{
+}
+NotFoundException::NotFoundException(JSContextRef ctx, JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::NOT_FOUND_ERROR.c_str();
+}
+
+InvalidAccessException::InvalidAccessException(const char* message) :
+        BasePlatformException(JSWebAPIErrorFactory::INVALID_ACCESS_ERROR.c_str(),
+            message)
+{
+}
+InvalidAccessException::InvalidAccessException(JSContextRef ctx,
+        JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::INVALID_ACCESS_ERROR.c_str();
+}
+
+QuotaExceededException::QuotaExceededException(const char* message) :
+        BasePlatformException(JSWebAPIErrorFactory::QUOTA_EXCEEDED_ERROR.c_str(),
+            message)
+{
+}
+QuotaExceededException::QuotaExceededException(JSContextRef ctx,
+        JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::QUOTA_EXCEEDED_ERROR.c_str();
+}
+
+InvalidModificationException::InvalidModificationException(const char* message) :
+        BasePlatformException(
+            JSWebAPIErrorFactory::INVALID_MODIFICATION_ERROR.c_str(), message)
+{
+}
+
+InvalidModificationException::InvalidModificationException(JSContextRef ctx,
+        JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::INVALID_MODIFICATION_ERROR.c_str();
+}
+
+InvalidStateException::InvalidStateException(const char* message) :
+        BasePlatformException(
+            JSWebAPIErrorFactory::INVALID_STATE_ERROR.c_str(), message)
+{
+}
+
+InvalidStateException::InvalidStateException(JSContextRef ctx,
+        JSValueRef exception) :
+        BasePlatformException(ctx, exception)
+{
+    mName = JSWebAPIErrorFactory::INVALID_STATE_ERROR.c_str();
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/PlatformException.h b/src/Common/PlatformException.h
new file mode 100644 (file)
index 0000000..1492d06
--- /dev/null
@@ -0,0 +1,116 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _PLATFORM_EXCEPTION_H_
+#define _PLATFORM_EXCEPTION_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Common {
+
+class BasePlatformException {
+public:
+    BasePlatformException(const char* name, const char* message);
+    BasePlatformException(JSContextRef ctx, JSValueRef exception);
+    virtual ~BasePlatformException();
+
+    virtual std::string getName() const;
+    virtual std::string getMessage() const;
+
+protected:
+    std::string mName;
+    std::string mMessage;
+};
+
+class TypeMismatchException: public BasePlatformException {
+public:
+    TypeMismatchException(const char* message);
+    TypeMismatchException(JSContextRef ctx, JSValueRef exception);
+};
+
+class InvalidValuesException: public BasePlatformException {
+public:
+    InvalidValuesException(const char* message);
+    InvalidValuesException(JSContextRef ctx, JSValueRef exception);
+};
+
+class IOException: public BasePlatformException {
+public:
+    IOException(const char* message);
+    IOException(JSContextRef ctx, JSValueRef exception);
+};
+
+class UnknownException: public BasePlatformException {
+public:
+    UnknownException(const char* message);
+    UnknownException(JSContextRef ctx, JSValueRef exception);
+};
+
+class ServiceNotAvailableException: public BasePlatformException {
+public:
+    ServiceNotAvailableException(const char* message);
+    ServiceNotAvailableException(JSContextRef ctx, JSValueRef exception);
+};
+
+class SecurityException: public BasePlatformException {
+public:
+    SecurityException(const char* message);
+    SecurityException(JSContextRef ctx, JSValueRef exception);
+};
+
+class NotSupportedException: public BasePlatformException {
+public:
+    NotSupportedException(const char* message);
+    NotSupportedException(JSContextRef ctx, JSValueRef exception);
+};
+
+class NotFoundException: public BasePlatformException {
+public:
+    NotFoundException(const char* message);
+    NotFoundException(JSContextRef ctx, JSValueRef exception);
+};
+
+class InvalidAccessException: public BasePlatformException {
+public:
+    InvalidAccessException(const char* message);
+    InvalidAccessException(JSContextRef ctx, JSValueRef exception);
+};
+
+class QuotaExceededException: public BasePlatformException {
+public:
+    QuotaExceededException(const char* message);
+    QuotaExceededException(JSContextRef ctx, JSValueRef exception);
+};
+
+class InvalidModificationException: public BasePlatformException {
+public:
+    InvalidModificationException(const char* message);
+    InvalidModificationException(JSContextRef ctx, JSValueRef exception);
+};
+
+class InvalidStateException: public BasePlatformException {
+public:
+    InvalidStateException(const char* message);
+    InvalidStateException(JSContextRef ctx, JSValueRef exception);
+};
+
+}
+}
+
+#endif //_PLATFORM_EXCEPTION_H_
diff --git a/src/Common/PropertyBag.cpp b/src/Common/PropertyBag.cpp
new file mode 100755 (executable)
index 0000000..2572745
--- /dev/null
@@ -0,0 +1,261 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PropertyBag.h"
+#include "Logger.h"
+#include "JSUtil.h"
+#include "GlobalContextManager.h"
+#include "PlatformException.h"
+#include <cmath>
+
+using namespace std;
+
+namespace DeviceAPI {
+namespace Common {
+
+PropertyBag::PropertyBag(){
+}
+
+PropertyBag::~PropertyBag(){
+    contextMapT::iterator contextItr;
+    for( contextItr = mContextMap.begin() ; contextItr != mContextMap.end() ; ++contextItr){
+        propertyBagT::iterator propertyItr;
+        propertyBagT * bag = contextItr->second;
+        for( propertyItr = bag->begin(); propertyItr != bag->end(); ++propertyItr){
+            JSValueRef v = propertyItr->second;
+            if( v != NULL )
+                JSValueUnprotect(contextItr->first, v);
+        }
+        delete bag;
+    }
+}
+
+std::map<const std::string, JSValueRef> * PropertyBag::getBag(JSContextRef globalCtx){
+    //find property bag for the context
+    contextMapT::iterator itr;
+    itr = mContextMap.find(globalCtx);
+    propertyBagT *bag = NULL;
+
+    if( itr == mContextMap.end() ){
+        bag = new propertyBagT();
+        mContextMap[globalCtx] = bag;
+    }else{
+        bag = mContextMap[globalCtx];
+    }
+    return bag;
+}
+
+void PropertyBag::removeItem(JSContextRef globalCtx, propertyBagT *bag, const std::string& propertyName){
+    if( bag == NULL )
+        return;
+    propertyBagT::iterator item = bag->find(propertyName);
+    if( item != bag->end() && item->second != NULL){
+        JSValueUnprotect(globalCtx, item->second);
+        bag->erase(item);
+    }
+}
+
+void PropertyBag::deleteProperty(JSContextRef ctx, const std::string& propertyName){
+    JSContextRef globalCtx = GlobalContextManager::getInstance()->getGlobalContext(ctx);
+    if( globalCtx == NULL ){
+        LOGE("Cannot found global context!");
+        return;
+    }
+    propertyBagT *bag = getBag(globalCtx);
+    removeItem(globalCtx, bag, propertyName);
+}
+void PropertyBag::deleteProperty(JSContextRef ctx, JSStringRef propertyName){
+    deleteProperty(ctx, JSUtil::JSStringToString(ctx, propertyName));
+}
+
+
+bool PropertyBag::setProperty(JSContextRef ctx, const std::string& propertyName, JSValueRef value){
+    JSContextRef globalCtx = GlobalContextManager::getInstance()->getGlobalContext(ctx);
+    if( globalCtx == NULL ){
+        LOGE("Cannot found global context!");
+        return false;
+    }
+    propertyBagT *bag = getBag(globalCtx);
+    if( bag == NULL)
+        return false;
+    removeItem(globalCtx, bag, propertyName);
+    if( value != NULL )
+        JSValueProtect(globalCtx, value);
+    (*bag)[propertyName] = value;
+    return true;
+}
+
+bool PropertyBag::setProperty(JSContextRef ctx, const std::string& propertyName, double number){
+    JSValueRef value = JSUtil::toJSValueRef(ctx, number);
+    return setProperty(ctx, propertyName, value);
+}
+
+bool PropertyBag::setProperty(JSContextRef ctx, const std::string& propertyName, std::string& str){
+    JSValueRef value = JSUtil::toJSValueRef(ctx, str);
+    return setProperty(ctx, propertyName, value);
+}
+
+bool PropertyBag::setProperty(JSContextRef ctx, const std::string& propertyName, const char *str){
+    string strvalue = string(str);
+    JSValueRef value = JSUtil::toJSValueRef(ctx, strvalue);
+    return setProperty(ctx, propertyName, value);
+}
+
+bool PropertyBag::setProperty(JSContextRef ctx, const std::string& propertyName, bool boolean){
+    JSValueRef value = JSUtil::toJSValueRef(ctx, boolean);
+    return setProperty(ctx, propertyName, value);
+}
+
+
+bool PropertyBag::setProperty(JSContextRef ctx, const std::string& propertyName, JSValueRef value, JSClassRef classRef){
+    if( !JSValueIsObjectOfClass( ctx, value, classRef) ){
+        LOGE("The value is incorrect type");
+        return true;    //ignore set property
+    }
+    return setProperty(ctx, propertyName, value);
+}
+
+
+bool PropertyBag::setFunctionProperty(JSContextRef ctx, const std::string& propertyName, JSValueRef function){
+    JSObjectRef obj = JSUtil::JSValueToObject(ctx, function);
+    if( !JSObjectIsFunction( ctx, obj) ){
+        LOGE("The value is incorrect type");
+        return true;    //ignore set property
+    }
+    return setProperty(ctx, propertyName, function);
+}
+
+bool PropertyBag::setArrayProperty(JSContextRef ctx, const std::string& propertyName, JSValueRef array){
+    if( !JSIsArrayValue(ctx, array)){
+        LOGE("The value is not Array type");
+        return true;    //ignore set property
+    }
+    return setProperty(ctx, propertyName, array);
+}
+
+
+bool PropertyBag::setProperty(JSContextRef ctx, JSStringRef propertyName, JSValueRef value){
+    return setProperty(ctx, JSUtil::JSStringToString(ctx, propertyName), value);
+}
+bool PropertyBag::setProperty(JSContextRef ctx, JSStringRef propertyName, double number){
+    return setProperty(ctx, JSUtil::JSStringToString(ctx, propertyName), number);
+}
+bool PropertyBag::setProperty(JSContextRef ctx, JSStringRef propertyName, std::string& str){
+    return setProperty(ctx, JSUtil::JSStringToString(ctx, propertyName), str);
+}
+bool PropertyBag::setProperty(JSContextRef ctx, JSStringRef propertyName, const char * str){
+    return setProperty(ctx, JSUtil::JSStringToString(ctx, propertyName), str);
+}
+bool PropertyBag::setProperty(JSContextRef ctx, JSStringRef propertyName, bool boolean){
+    return setProperty(ctx, JSUtil::JSStringToString(ctx, propertyName), boolean);
+}
+bool PropertyBag::setProperty(JSContextRef ctx, JSStringRef propertyName, JSValueRef value, JSClassRef classRef){
+    return setProperty(ctx, JSUtil::JSStringToString(ctx, propertyName),value, classRef);
+}
+bool PropertyBag::setFunctionProperty(JSContextRef ctx, JSStringRef propertyName, JSValueRef function){
+    return setFunctionProperty(ctx, JSUtil::JSStringToString(ctx, propertyName),function);
+}
+bool PropertyBag::setArrayProperty(JSContextRef ctx, JSStringRef propertyName, JSValueRef array){
+    return setArrayProperty(ctx, JSUtil::JSStringToString(ctx, propertyName),array);
+}
+
+
+
+JSValueRef PropertyBag::getProperty(JSContextRef ctx, const std::string& propertyName){
+    JSContextRef globalCtx = GlobalContextManager::getInstance()->getGlobalContext(ctx);
+    if( globalCtx == NULL ){
+        LOGE("Cannot found global context!");
+        return NULL;
+    }
+
+    propertyBagT *bag = getBag(globalCtx);
+    if( bag == NULL)
+        return NULL;
+
+    propertyBagT::iterator item = bag->find(propertyName);
+    if( item == bag->end()){
+        LOGE("Cannot found item");
+        return NULL;
+    }
+    return item->second;
+}
+
+double PropertyBag::getNumberProperty(JSContextRef ctx, const std::string& propertyName){
+    JSValueRef value = getProperty(ctx, propertyName);
+    if( value == NULL )
+        return 0.0;
+    try{
+        return JSUtil::JSValueToDouble(ctx, value);
+    }catch(const BasePlatformException& err){
+        LOGE("Cannot convert to number");
+    }
+    return std::nan("not number");
+}
+
+double PropertyBag::getDoubleProperty(JSContextRef ctx, const std::string& propertyName){
+    JSValueRef value = getProperty(ctx, propertyName);
+    if( value == NULL )
+        return 0;
+    return JSUtil::JSValueToDouble(ctx, value);
+}
+
+bool PropertyBag::getBooleanProperty(JSContextRef ctx, const std::string& propertyName){
+    JSValueRef value = getProperty(ctx, propertyName);
+    if( value == NULL )
+        return false;
+    return JSUtil::JSValueToBoolean(ctx, value);
+}
+
+std::string PropertyBag::getStringProperty(JSContextRef ctx, const std::string& propertyName){
+    JSValueRef value = getProperty(ctx, propertyName);
+    if( value == NULL )
+        return "undefined";
+    return JSUtil::JSValueToString(ctx, value);
+}
+
+JSObjectRef PropertyBag::getObjectProperty(JSContextRef ctx, const std::string& propertyName){
+    JSValueRef value = getProperty(ctx, propertyName);
+    if( value == NULL )
+        return NULL;
+    if( !JSValueIsObject(ctx, value) )
+        return NULL;
+    return JSUtil::JSValueToObject(ctx, value);
+}
+
+double PropertyBag::getNumberProperty(JSContextRef ctx, JSStringRef propertyName){
+    return getNumberProperty(ctx, JSUtil::JSStringToString(ctx, propertyName));
+}
+double PropertyBag::getDoubleProperty(JSContextRef ctx, JSStringRef propertyName){
+    return getDoubleProperty(ctx, JSUtil::JSStringToString(ctx, propertyName));
+}
+bool PropertyBag::getBooleanProperty(JSContextRef ctx, JSStringRef propertyName){
+    return getBooleanProperty(ctx, JSUtil::JSStringToString(ctx, propertyName));
+}
+std::string PropertyBag::getStringProperty(JSContextRef ctx, JSStringRef propertyName){
+    return getStringProperty(ctx, JSUtil::JSStringToString(ctx, propertyName));
+}
+JSObjectRef PropertyBag::getObjectProperty(JSContextRef ctx, JSStringRef propertyName){
+    return getObjectProperty(ctx, JSUtil::JSStringToString(ctx, propertyName));
+}
+JSValueRef PropertyBag::getProperty(JSContextRef ctx, JSStringRef propertyName){
+    return getProperty(ctx, JSUtil::JSStringToString(ctx,propertyName));
+}
+
+
+
+} //Common
+} //DeviceAPI
diff --git a/src/Common/PropertyBag.h b/src/Common/PropertyBag.h
new file mode 100755 (executable)
index 0000000..71709da
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_COMMON_PROPERTY_BAG_H__
+#define __TIZEN_COMMON_PROPERTY_BAG_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <string>
+#include <map>
+
+namespace DeviceAPI {
+namespace Common{
+
+class PropertyBag{
+public:
+    PropertyBag();
+    virtual ~PropertyBag();
+
+    void deleteProperty(JSContextRef ctx, const std::string& propertyName);
+    void deleteProperty(JSContextRef ctx, JSStringRef propertyName);
+
+
+    bool setProperty(JSContextRef ctx, const std::string& propertyName, JSValueRef value);
+    bool setProperty(JSContextRef ctx, JSStringRef propertyName, JSValueRef value);
+
+    bool setProperty(JSContextRef ctx, const std::string& propertyName, double number);
+    bool setProperty(JSContextRef ctx, JSStringRef propertyName, double number);
+
+    bool setProperty(JSContextRef ctx, const std::string& propertyName, std::string& str);
+    bool setProperty(JSContextRef ctx, JSStringRef propertyName, std::string& str);
+
+    bool setProperty(JSContextRef ctx, const std::string& propertyName, const char *str);
+    bool setProperty(JSContextRef ctx, JSStringRef propertyName, const char * str);
+
+    bool setProperty(JSContextRef ctx, const std::string& propertyName, bool boolean);
+    bool setProperty(JSContextRef ctx, JSStringRef propertyName, bool boolean);
+
+    bool setProperty(JSContextRef ctx, const std::string& propertyName, JSValueRef value, JSClassRef classRef);
+    bool setProperty(JSContextRef ctx, JSStringRef propertyName, JSValueRef value, JSClassRef classRef);
+
+    bool setFunctionProperty(JSContextRef ctx, const std::string& propertyName, JSValueRef function);
+    bool setFunctionProperty(JSContextRef ctx, JSStringRef propertyName, JSValueRef function);
+
+    bool setArrayProperty(JSContextRef ctx, const std::string& propertyName, JSValueRef array);
+    bool setArrayProperty(JSContextRef ctx, JSStringRef propertyName, JSValueRef array);
+
+    JSValueRef getProperty(JSContextRef ctx, const std::string& propertyName);
+    JSValueRef getProperty(JSContextRef ctx, JSStringRef propertyName);
+
+    double getNumberProperty(JSContextRef ctx, const std::string& propertyName);
+    double getNumberProperty(JSContextRef ctx, JSStringRef propertyName);
+
+    double getDoubleProperty(JSContextRef ctx, const std::string& propertyName);
+    double getDoubleProperty(JSContextRef ctx, JSStringRef propertyName);
+
+    bool getBooleanProperty(JSContextRef ctx, const std::string& propertyName);
+    bool getBooleanProperty(JSContextRef ctx, JSStringRef propertyName);
+
+    std::string getStringProperty(JSContextRef ctx, const std::string& propertyName);
+    std::string getStringProperty(JSContextRef ctx, JSStringRef propertyName);
+
+    JSObjectRef getObjectProperty(JSContextRef ctx, const std::string& propertyName);
+    JSObjectRef getObjectProperty(JSContextRef ctx, JSStringRef propertyName);
+
+private:
+    typedef std::map<const std::string, JSValueRef> propertyBagT;
+    typedef std::map<JSContextRef, propertyBagT*> contextMapT;
+    std::map<JSContextRef, propertyBagT*> mContextMap;
+
+    std::map<const std::string, JSValueRef> * getBag(JSContextRef globalCtx);
+    void removeItem(JSContextRef globalCtx, propertyBagT *bag, const std::string& propertyName);
+
+};
+
+
+} //Common
+} //DeviceAPI
+
+
+#endif //__TIZEN_COMMON_PROPERTY_BAG_H__
diff --git a/src/Common/Security.h b/src/Common/Security.h
new file mode 100644 (file)
index 0000000..3b293d5
--- /dev/null
@@ -0,0 +1,152 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_COMMON_SECURITY_H__
+#define __TIZEN_COMMON_SECURITY_H__
+
+#include <Commons/FunctionDeclaration.h>
+#include "SecurityAccessor.h"
+#include "JSTizenSecurityObject.h"
+#include "JSWebAPIErrorFactory.h"
+
+#if defined(DISABLE_ACE_ACCESS_CHECK)
+    #define ACE_ACCESS_CHECK(...) LOGD("Disabled ACE check");
+#else
+    #define ACE_ACCESS_CHECK(...) __VA_ARGS__
+#endif
+
+#define DEFINE_GLOBAL_SECURITY_ACCESSOR_EXT(Variable_Name, SecurityAccessorClass) \
+    SecurityAccessorClass* Variable_Name = NULL
+
+#define DEFINE_GLOBAL_SECURITY_ACCESSOR(Variable_Name) \
+    DEFINE_GLOBAL_SECURITY_ACCESSOR_EXT(Variable_Name, DeviceAPI::Common::SecurityAccessor)
+
+#define INITAILIZE_GLOBAL_SECURITY_ACCESSOR_EXT(Variable_Name, SecurityAccessorClass, ...) \
+    do { \
+        Variable_Name = new SecurityAccessorClass(__VA_ARGS__); \
+    } while(0)
+
+#define INITAILIZE_GLOBAL_SECURITY_ACCESSOR(Variable_Name, AceCheckAccessFunction_Name) \
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR_EXT(Variable_Name, DeviceAPI::Common::SecurityAccessor, &AceCheckAccessFunction_Name)
+
+#define FINALIZE_GLOBAL_SECURITY_ACCESSOR(Variable_Name) \
+    do { \
+        if(Variable_Name) { \
+            delete Variable_Name; \
+            Variable_Name = NULL; \
+        } \
+    } while(0)
+
+#define DEFINE_JSOBJECT_SECURITY_ACCESSOR_SETTER(Function_Name, SecurityAccessor_Object) \
+    void Function_Name(java_script_context_t ctx, \
+            js_object_instance_t, \
+            js_object_instance_t obj) \
+    { \
+        DeviceAPI::Common::JSObjectSetSecurityAccessor(static_cast<JSContextRef>(ctx), \
+                static_cast<JSObjectRef>(obj), SecurityAccessor_Object); \
+    }
+
+#define DEFINE_SECURITY_ACCESSOR_SETTER_EXT(Function_Name, PrivObjectType, \
+        SecurityAccessor_Object, SecurityAccessorClass) \
+    void Function_Name(java_script_context_t, \
+            js_object_instance_t, \
+            js_object_instance_t object) \
+    { \
+        PrivObjectType* priv = \
+                static_cast<PrivObjectType*>(JSObjectGetPrivate(static_cast<JSObjectRef>(object))); \
+        SecurityAccessorClass* accessor = \
+                static_cast<SecurityAccessorClass*>(priv); \
+        accessor->copyAceCheckAccessFunction(SecurityAccessor_Object); \
+    }
+
+#define DEFINE_SECURITY_ACCESSOR_SETTER(Function_Name, PrivObjectType, SecurityAccessor_Object) \
+        DEFINE_SECURITY_ACCESSOR_SETTER_EXT(Function_Name, PrivObjectType, \
+                SecurityAccessor_Object, DeviceAPI::Common::SecurityAccessor)
+
+/**
+ * To support 0 additional params in accessorCheckfunction ##_VA_ARGS__ expression is used.
+ * Please see gcc page: http://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html for details.
+ */
+#if defined(DISABLE_ACE_ACCESS_CHECK)
+#define TIZEN_CHECK_ACCESS_EXT(context, exception, privateObject, functionName, \
+        customSecurityAccessorClass, accessorCheckfunction, ...) LOGD("Disabled ACE check");
+#else
+#define TIZEN_CHECK_ACCESS_EXT(context, exception, privateObject, functionName, \
+        customSecurityAccessorClass , accessorCheckfunction, ...) \
+    do { \
+        using namespace WrtDeviceApis::Commons; \
+        customSecurityAccessorClass* accessor = \
+                static_cast<customSecurityAccessorClass*>(privateObject); \
+        if(accessor->isInitialized() == false) { \
+            return JSWebAPIErrorFactory::postException(context, exception, \
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal security error"); \
+        } \
+        \
+        AceSecurityStatus status = accessor->accessorCheckfunction(functionName, ##__VA_ARGS__); \
+        switch (status) { \
+        case AceSecurityStatus::InternalError: \
+            return JSWebAPIErrorFactory::postException(context, exception, \
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error"); \
+            break; \
+        case AceSecurityStatus::PrivacyDenied: \
+            return JSWebAPIErrorFactory::postException(context, exception, \
+                    JSWebAPIErrorFactory::SECURITY_ERROR, "The user blocks an application from calling this method."); \
+            break; \
+        case AceSecurityStatus::AccessDenied: \
+            return JSWebAPIErrorFactory::postException(context, exception, \
+                    JSWebAPIErrorFactory::SECURITY_ERROR, "The application does not have the privilege to call this method."); \
+            break; \
+        default: \
+            break; \
+        } \
+    } while(0)
+#endif
+
+#define TIZEN_CHECK_ACCESS(context, exception, privateObject, functionName) \
+    TIZEN_CHECK_ACCESS_EXT(context, exception, privateObject, functionName, \
+            DeviceAPI::Common::SecurityAccessor, invokeAceCheckAccessFunction)
+
+#define TIZEN_ASYNC_CBM_ACCESS(context, privateObject, cbm, functionName) \
+    do { \
+        using namespace WrtDeviceApis::Commons; \
+        DeviceAPI::Common::SecurityAccessor* accessor = \
+                static_cast<DeviceAPI::Common::SecurityAccessor*>(privateObject); \
+        if(accessor->isInitialized() == false) { \
+            cbm->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, \
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal security error")); \
+            return JSValueMakeNull(context); \
+        } \
+        AceSecurityStatus status = accessor->invokeAceCheckAccessFunction(functionName); \
+        switch (status) { \
+        case AceSecurityStatus::InternalError: \
+            cbm->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, \
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error")); \
+            return JSValueMakeNull(context); \
+        case AceSecurityStatus::PrivacyDenied: \
+            cbm->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, \
+                    JSWebAPIErrorFactory::SECURITY_ERROR, "The user blocks an application from calling this method.")); \
+            return JSValueMakeNull(context); \
+        case AceSecurityStatus::AccessDenied: \
+            cbm->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, \
+                    JSWebAPIErrorFactory::SECURITY_ERROR, "The application does not have the privilege to call this method.")); \
+            return JSValueMakeNull(context); \
+        default: \
+            break; \
+        } \
+    } while (0)
+
+#endif // __TIZEN_COMMON_SECURITY_H__
diff --git a/src/Common/SecurityAccessor.cpp b/src/Common/SecurityAccessor.cpp
new file mode 100644 (file)
index 0000000..65912bb
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SecurityAccessor.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+SecurityAccessor::SecurityAccessor() :
+        m_aceCheckAccessFunc(NULL),
+        m_aceCheckAccessFuncInited(false)
+{
+}
+
+SecurityAccessor::SecurityAccessor(const AceCheckAccessFunction aceCheckAccessFunc) :
+        m_aceCheckAccessFunc(aceCheckAccessFunc),
+        m_aceCheckAccessFuncInited(true)
+{
+}
+
+SecurityAccessor::SecurityAccessor(const SecurityAccessor &securityAccessor) :
+        m_aceCheckAccessFunc(securityAccessor.m_aceCheckAccessFunc),
+        m_aceCheckAccessFuncInited(true)
+{
+}
+
+SecurityAccessor::SecurityAccessor(const SecurityAccessor *securityAccessor) :
+        m_aceCheckAccessFunc(securityAccessor->m_aceCheckAccessFunc),
+        m_aceCheckAccessFuncInited(true)
+{
+}
+
+SecurityAccessor::~SecurityAccessor()
+{
+}
+
+void SecurityAccessor::copyAceCheckAccessFunction(const SecurityAccessor &securityAccessor)
+{
+    setAceCheckAccessFunction(securityAccessor.m_aceCheckAccessFunc);
+}
+
+void SecurityAccessor::copyAceCheckAccessFunction(const SecurityAccessor *securityAccessor)
+{
+    setAceCheckAccessFunction(securityAccessor->m_aceCheckAccessFunc);
+}
+
+bool SecurityAccessor::isInitialized() const
+{
+    return m_aceCheckAccessFuncInited;
+}
+
+WrtDeviceApis::Commons::AceSecurityStatus SecurityAccessor::invokeAceCheckAccessFunction(const char *functionName) const
+{
+    if(m_aceCheckAccessFuncInited)
+        return m_aceCheckAccessFunc(functionName);
+    else
+        return WrtDeviceApis::Commons::AceSecurityStatus::InternalError;
+}
+
+void SecurityAccessor::setAceCheckAccessFunction(const AceCheckAccessFunction aceCheckAccessFunc)
+{
+    if(!m_aceCheckAccessFuncInited)
+    {
+        m_aceCheckAccessFunc = aceCheckAccessFunc;
+        m_aceCheckAccessFuncInited = true;
+    }
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/SecurityAccessor.h b/src/Common/SecurityAccessor.h
new file mode 100644 (file)
index 0000000..2c6660c
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_COMMON_SECURITY_ACCESSOR_H__
+#define __TIZEN_COMMON_SECURITY_ACCESSOR_H__
+
+#include <Commons/FunctionDeclaration.h>
+#include "JSWebAPIErrorFactory.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+typedef WrtDeviceApis::Commons::AceSecurityStatus (*AceCheckAccessFunction)(const char *);
+
+class SecurityAccessor
+{
+public:
+    SecurityAccessor();
+    SecurityAccessor(const AceCheckAccessFunction aceCheckAccessFunc);
+    SecurityAccessor(const SecurityAccessor &securityAccessor);
+    SecurityAccessor(const SecurityAccessor *securityAccessor);
+    virtual ~SecurityAccessor();
+
+    virtual void copyAceCheckAccessFunction(const SecurityAccessor &securityAccessor);
+    virtual void copyAceCheckAccessFunction(const SecurityAccessor *securityAccessor);
+
+    virtual bool isInitialized() const;
+
+    virtual WrtDeviceApis::Commons::AceSecurityStatus invokeAceCheckAccessFunction(const char *functionName) const;
+
+private:
+    AceCheckAccessFunction m_aceCheckAccessFunc;
+    bool m_aceCheckAccessFuncInited;
+
+    void setAceCheckAccessFunction(const AceCheckAccessFunction aceCheckAccessFunc);
+};
+
+} // Common
+} // DeviceAPI
+
+#endif // __TIZEN_COMMON_SECURITY_ACCESSOR_H__
diff --git a/src/Common/SecurityExceptions.h b/src/Common/SecurityExceptions.h
new file mode 100644 (file)
index 0000000..9d55577
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_COMMONS_JS_SECURITYEXCEPTIONS_H_
+#define TIZENAPIS_COMMONS_JS_SECURITYEXCEPTIONS_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "JSWebAPIErrorFactory.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+/**
+ * synchronously checks access status and throws JS Security exception if
+ * necessary
+ */
+#define TIZEN_SYNC_ACCESS_HANDLER(status, context, exception) \
+    do { \
+        switch (status) { \
+        case AceSecurityStatus::InternalError: \
+            return JSWebAPIErrorFactory::postException(context, exception, \
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error"); \
+            break; \
+        case AceSecurityStatus::PrivacyDenied: \
+            return JSWebAPIErrorFactory::postException(context, exception, \
+                    JSWebAPIErrorFactory::SECURITY_ERROR, \
+                    "The user blocks an application from calling this method."); \
+            break; \
+        case AceSecurityStatus::AccessDenied: \
+            return JSWebAPIErrorFactory::postException(context, exception, \
+                    JSWebAPIErrorFactory::SECURITY_ERROR, \
+                    "The application does not have the privilege to call this method."); \
+            break; \
+        default: \
+            break; \
+        } \
+    } while (0)
+
+/**
+ * checks access status and returns an error through JSCallbackManager if
+ * necessary
+ */
+#define TIZEN_ASYNC_CBM_ACCESS_HANDLER(status, context, cbm) \
+    do { \
+        switch (status) { \
+        case AceSecurityStatus::InternalError: \
+            cbm->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, \
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error")); \
+            return JSValueMakeNull(context); \
+        case AceSecurityStatus::PrivacyDenied: \
+            cbm->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, \
+                    JSWebAPIErrorFactory::SECURITY_ERROR, \
+                    "The user blocks an application from calling this method.")); \
+            return JSValueMakeNull(context); \
+        case AceSecurityStatus::AccessDenied: \
+            cbm->callOnError(JSWebAPIErrorFactory::makeErrorObject(context, \
+                    JSWebAPIErrorFactory::SECURITY_ERROR, \
+                    "The application does not have the privilege to call this method.")); \
+            return JSValueMakeNull(context); \
+        default: \
+            break; \
+        } \
+    } while (0)
+
+} // Common
+} // DeviceAPI
+#endif /*TIZENAPIS_COMMONS_JS_SECURITYEXCEPTIONS_H_ */
+
diff --git a/src/Common/Singleton.h b/src/Common/Singleton.h
new file mode 100644 (file)
index 0000000..75aaaf0
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Singleton.h
+ * @version     0.1
+ * @brief
+ */
+
+#include "Export.h"
+
+#ifndef _TIZEN_COMMONS_SINGLETON_H_
+#define _TIZEN_COMMONS_SINGLETON_H_
+
+#define SINGLETON_DEFINITION(CLASSNAME) \
+    class DLL_EXPORT CLASSNAME##Singleton : private CLASSNAME { \
+    private: \
+        CLASSNAME##Singleton() {} \
+        static CLASSNAME##Singleton &InternalInstance(); \
+    public: \
+        virtual ~CLASSNAME##Singleton() {} \
+        static CLASSNAME &Instance(); \
+    };
+
+#define SINGLETON_IMPLEMENTATION(CLASSNAME) \
+    CLASSNAME##Singleton& CLASSNAME##Singleton::InternalInstance() { \
+        static CLASSNAME##Singleton instance; \
+        return instance; \
+    } \
+    CLASSNAME& CLASSNAME##Singleton::Instance() { \
+        CLASSNAME##Singleton& instance = CLASSNAME##Singleton::InternalInstance(); \
+        return instance; \
+    }
+
+#endif // _TIZEN_COMMONS_SINGLETON_H_
diff --git a/src/Common/StandaloneConsole/CMakeLists.txt b/src/Common/StandaloneConsole/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a539bb5
--- /dev/null
@@ -0,0 +1,24 @@
+SET(TARGET "standaloneconsole")\r
+\r
+SET(SRCS\r
+  JSConsole.cpp\r
+  StandaloneConsole.cpp\r
+)\r
+\r
+INCLUDE_DIRECTORIES(
+       ${TOP}/Common\r
+)
+\r
+
+ADD_LIBRARY(${TARGET} SHARED ${SRCS})\r
+
+TARGET_LINK_LIBRARIES(${TARGET}\r
+  ${LIBS_COMMON}\r
+)
+
+INSTALL(TARGETS ${TARGET} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${COMMON_DESTINATION_NAME})\r
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/common
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
+\r
diff --git a/src/Common/StandaloneConsole/JSConsole.cpp b/src/Common/StandaloneConsole/JSConsole.cpp
new file mode 100755 (executable)
index 0000000..42fe5ad
--- /dev/null
@@ -0,0 +1,134 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSConsole.h"
+#include <CommonsJavaScript/Converter.h>
+#include <stdio.h>
+#include <dlog.h>
+#include <sys/time.h>
+#include <ctime>
+#include <sys/time.h>
+
+
+#undef LOG_TAG
+#define LOG_TAG "TIZEN_DEVICEAPI"
+
+using namespace std;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace WrtDeviceApis::Commons;
+
+
+namespace DeviceAPI {
+namespace Test {
+
+JSClassRef JSConsole::m_jsClassRef = NULL;
+
+JSClassDefinition JSConsole::m_jsClassInfo = {
+    0,                                       // current (and only) version is 0
+    kJSClassAttributeNone,        //attributes
+    "console",                        //class name
+    NULL,                                 // parent class
+    NULL,                                 //static values
+    JSConsole::m_function,     // static functions
+    JSConsole::initialize,         // initialize
+    JSConsole::finalize,          //finalize
+    NULL,                                //hasProperty
+    NULL,   //getProperty
+    NULL,                                //setProperty
+    NULL,                                //deleteProperty
+    NULL,                                //getPropertyNames
+    NULL,                               // callAsConstructor
+    NULL,                               // constructor
+    JSConsole::hasInstance,
+    NULL // convertToType
+};
+
+
+JSStaticFunction JSConsole::m_function[] = {
+    { "log", JSConsole::log, kJSPropertyAttributeNone },
+    { "debug", JSConsole::log, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSConsole::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSConsole::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+
+JSObjectRef JSConsole::createJSObject( JSContextRef ctx ){
+    return JSObjectMake(ctx, getClassRef(), NULL);
+}
+
+
+void JSConsole::initialize(JSContextRef ctx, JSObjectRef object)
+{
+}
+
+void JSConsole::finalize(JSObjectRef object)
+{
+}
+
+bool JSConsole::hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception) {
+    return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
+}
+
+#define timersub(a, b, result) \
+do { \
+    (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
+    (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
+    if ((result)->tv_usec < 0) { \
+        --(result)->tv_sec; \
+        (result)->tv_usec += 1000000; \
+    } \
+} while (0)
+
+JSValueRef JSConsole::log(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    static struct timeval prev = {0};
+    struct timeval current = {0};
+    struct timeval diff = {0};
+    gettimeofday(&current, NULL);
+    if( prev.tv_sec == 0 && prev.tv_usec == 0)
+        prev = current;
+
+    timersub(&current, &prev, &diff);
+    prev = current;
+
+    Converter convert(ctx);
+    if( argumentCount == 0 )
+        return JSValueMakeUndefined(ctx);
+
+    try{
+        string result = convert.toString(arguments[0]);
+        printf("<log[%d.%06d]>%s\n",(int)diff.tv_sec,(int)diff.tv_usec,result.c_str());
+        LOGD("%s", result.c_str());
+    }catch(const ConversionException& err){
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+} // Filesystem
+} // TizenApis
+
diff --git a/src/Common/StandaloneConsole/JSConsole.h b/src/Common/StandaloneConsole/JSConsole.h
new file mode 100644 (file)
index 0000000..5c6d08b
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_COMMON_JS_CONSOLE_
+#define _TIZEN_COMMON_JS_CONSOLE_
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Test{
+
+class JSConsole{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef createJSObject(JSContextRef context);
+
+protected:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static bool hasInstance(JSContextRef context, JSObjectRef constructor, JSValueRef possibleInstance, JSValueRef* exception);
+
+    static JSValueRef log(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef assert(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+private:
+       static JSClassDefinition m_jsClassInfo;
+       static JSClassRef m_jsClassRef;
+       static JSStaticFunction m_function[];
+
+};
+
+} // Test
+} // TizenApis
+
+#endif //_TIZEN_COMMON_JS_CONSOLE_
+
+
diff --git a/src/Common/StandaloneConsole/StandaloneConsole.cpp b/src/Common/StandaloneConsole/StandaloneConsole.cpp
new file mode 100755 (executable)
index 0000000..712960d
--- /dev/null
@@ -0,0 +1,581 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <stdio.h>
+#include <dlog.h>
+#include <JavaScriptCore/JavaScript.h>
+#include "StandaloneConsole.h"
+#include "JSConsole.h"
+#include <Ecore.h>
+#include <GlobalContextManager.h>
+#include <string>
+#include <vector>
+#include <iostream>
+#include <termios.h>
+#include <JSUtil.h>
+
+#undef LOG_TAG
+#define LOG_TAG "TIZEN_DEVICEAPI"
+
+using namespace std;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Test {
+
+struct _Command{
+    char * mLine;
+    StandaloneConsole *mConsole;
+    pthread_mutex_t *mLock;
+    _Command(const char * cmd, StandaloneConsole *console, pthread_mutex_t* lock){
+        mLine = strdup(cmd);
+        mConsole = console;
+        mLock = lock;
+    }
+    ~_Command(){
+        free(mLine);
+    }
+    void run(){
+        mConsole->RunLine(mLine);
+        pthread_mutex_unlock(mLock);
+    }
+};
+
+struct CallbackData{
+    JSObjectRef callback;
+    int id;
+    StandaloneConsole *console;
+};
+
+static Eina_Bool tick(void *data){
+    return true;
+}
+
+static Eina_Bool commandDispath(void *data){
+    _Command *cmd = (_Command*)data;
+    cmd->run();
+    delete cmd;
+    return false;
+}
+
+Eina_Bool StandaloneConsole::timerCb(void *data){
+    CallbackData *callback = (CallbackData*)data;
+    StandaloneConsole *console = callback->console;
+    map<int,int>::iterator itr;
+    itr = console->mTimerMap.find(callback->id);
+    if( itr == console->mTimerMap.end() ){
+        JSValueUnprotect(console->getGlobalContext(), callback->callback);
+        delete callback;
+        return false;
+    }
+    if( itr->second == 0){
+        console->mTimerMap.erase(itr);
+        JSValueUnprotect(console->getGlobalContext(), callback->callback);
+        delete callback;
+        return false;
+    }
+    if( callback->callback != NULL){
+        JSObjectCallAsFunction(console->getGlobalContext(), callback->callback, NULL, 0, 0, NULL);
+    }
+
+    if( itr->second == 2 ){
+        console->mTimerMap.erase(itr);
+        JSValueUnprotect(console->getGlobalContext(), callback->callback);
+        delete callback;
+        return false;
+    }
+
+    return true;
+}
+
+
+JSValueRef StandaloneConsole::alert(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    if( argumentCount < 1 )
+        return JSValueMakeUndefined(ctx);
+
+
+    //JSContextRef globalCtx = GlobalContextManager::getInstance()->getGlobalContext(ctx);
+    //printf(" local : %p, global : %p \n", ctx, globalCtx);
+
+    JSStringRef str = JSValueToStringCopy(ctx, arguments[0], NULL);
+    if(str == NULL){
+        return JSValueMakeUndefined(ctx);
+    }
+    int n = JSStringGetLength(str);
+    {
+        char cstr[n+1];
+        JSStringGetUTF8CString(str, cstr,n+1);
+        printf("<alert>%s\n", cstr);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef StandaloneConsole::setInterval(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    static int id = 0;
+    StandaloneConsole *console = static_cast<StandaloneConsole*>(JSObjectGetPrivate(thisObject));
+    if( argumentCount < 2 ){
+        if( exception != NULL){
+
+        }
+        return JSValueMakeUndefined(ctx);
+    }
+    int handleid = id++;
+    double interval = JSValueToNumber(ctx, arguments[1], NULL);
+    interval = interval/1000;
+
+    console->mTimerMap.insert(pair<int,int>(handleid, 1));
+    CallbackData *data = new CallbackData();
+    JSValueProtect(console->getGlobalContext(), arguments[0]);
+    data->callback = JSValueToObject(ctx, arguments[0], NULL);
+    data->id = handleid;
+    data->console = console;
+
+    ecore_timer_add( interval, StandaloneConsole::timerCb , data);
+    return JSValueMakeNumber(ctx, handleid);
+
+}
+
+JSValueRef StandaloneConsole::setTimeout(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    static int id = 0;
+    StandaloneConsole *console = static_cast<StandaloneConsole*>(JSObjectGetPrivate(thisObject));
+
+    if( argumentCount < 2 ){
+        if( exception != NULL){
+
+        }
+        return JSValueMakeUndefined(ctx);
+    }
+    int handleid = id++;
+    double interval = JSValueToNumber(ctx, arguments[1], NULL);
+    interval = interval/1000;
+
+    console->mTimerMap.insert(pair<int,int>(handleid, 2));
+    CallbackData *data = new CallbackData();
+    JSValueProtect(console->getGlobalContext(), arguments[0]);
+    data->callback = JSValueToObject(ctx, arguments[0], NULL);
+    data->id = handleid;
+    data->console = console;
+
+    ecore_timer_add( interval, StandaloneConsole::timerCb , data);
+    return JSValueMakeNumber(ctx, handleid);
+
+}
+
+
+JSValueRef StandaloneConsole::clearInterval(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    StandaloneConsole *console = static_cast<StandaloneConsole*>(JSObjectGetPrivate(thisObject));
+    if(console == NULL) return JSValueMakeUndefined(ctx);
+    if( argumentCount < 1 ){
+        printf("error clearInterval\n");
+        if( exception != NULL){
+
+        }
+        return JSValueMakeUndefined(ctx);
+    }
+
+    int handleid = JSValueToNumber(ctx, arguments[0], NULL);
+    map<int,int>::iterator it;
+    it = console->mTimerMap.find(handleid);
+    if( it != console->mTimerMap.end())
+        console->mTimerMap[handleid] = 0;
+    return JSValueMakeUndefined(ctx);
+}
+
+
+static JSValueRef test(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    return JSValueMakeUndefined(ctx);
+}
+
+
+static void setProperty(JSContextRef ctx , JSObjectRef object, const char *name, JSValueRef value, JSPropertyAttributes attributes)
+{
+       JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
+       JSObjectSetProperty(ctx, object, propertyName, value,attributes, NULL );
+       JSStringRelease(propertyName);
+}
+
+static JSValueRef getProperty(JSContextRef ctx , JSObjectRef object, const char *name){
+       JSValueRef value;
+       JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
+       value = JSObjectGetProperty(ctx, object, propertyName, NULL);
+       JSStringRelease(propertyName);
+       return value;
+}
+
+static char * toString(JSContextRef ctx , JSValueRef jsV){
+    JSValueRef exception = NULL;
+    JSStringRef jsStr = JSValueToStringCopy(ctx, jsV, &exception);
+    if( exception != NULL )
+        return NULL;
+    int n = JSStringGetMaximumUTF8CStringSize(jsStr);
+    char *buf = new char[n+1];
+    JSStringGetUTF8CString(jsStr, buf, n+1);
+    JSStringRelease(jsStr);
+    return buf;
+}
+
+StandaloneConsole::StandaloneConsole():mGlobalContext(NULL),mGlobalObject(NULL){
+}
+
+StandaloneConsole::~StandaloneConsole(){
+}
+
+void StandaloneConsole::initialize(){
+    // Function table
+    JSStaticFunction functions[] = {
+        { "alert", StandaloneConsole::alert , kJSPropertyAttributeNone },
+        { "setInterval", StandaloneConsole::setInterval , kJSPropertyAttributeNone },
+        { "setTimeout", StandaloneConsole::setTimeout , kJSPropertyAttributeNone },
+        { "clearInterval", StandaloneConsole::clearInterval , kJSPropertyAttributeNone },
+        { "clearTimeout", StandaloneConsole::clearInterval , kJSPropertyAttributeNone },
+        { "test", test, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+    };
+
+    // Global class
+    JSClassDefinition def = {
+        0,                                 // current (and only) version is 0
+        kJSClassAttributeNone,   //attributes
+        "global",                        //class name
+        NULL,                            // parent class
+        NULL,                            //static values
+        functions,                      // static functions
+        NULL,                            // initialize
+        NULL,                            //finalize
+        NULL,                            //hasProperty
+        NULL,                            //getProperty
+        NULL,                            //setProperty
+        NULL,                            //deleteProperty
+        NULL,                            //getPropertyNames
+        NULL,                            // callAsConstructor
+        NULL,                            // constructor
+        NULL,
+        NULL                             // convertToType
+    };
+
+    JSClassRef globalClass = JSClassCreate(&def);
+
+    mGlobalContext = JSGlobalContextCreate(globalClass);
+    mGlobalObject = JSContextGetGlobalObject(mGlobalContext);
+    JSObjectSetPrivate(mGlobalObject, this);
+    JSObjectRef console = JSConsole::createJSObject(mGlobalContext);
+    setProperty(mGlobalContext, mGlobalObject, "console", console, kJSPropertyAttributeReadOnly);
+
+
+    //is it ecore bug? event was not invoke, it was added in another thread
+    ecore_timer_add(0.001, tick, NULL);
+}
+
+
+JSObjectRef StandaloneConsole::getGlobalObject(){
+    return mGlobalObject;
+}
+
+JSContextRef StandaloneConsole::getGlobalContext(){
+    return mGlobalContext;
+}
+
+
+JSValueRef StandaloneConsole::RunLineEx(const char* line, JSValueRef *exception){
+    JSStringRef jsScript = JSStringCreateWithUTF8CString(line);
+    int size = strlen(line);
+    if( size != static_cast <int>(JSStringGetLength(jsScript))){
+        cout <<"error - fail to converting JSStringRef"<<endl;
+    }
+    JSValueRef ret = JSEvaluateScript(mGlobalContext, jsScript, NULL, NULL, 0, exception);
+    JSStringRelease(jsScript);
+    return ret;
+}
+
+JSValueRef StandaloneConsole::RunScriptEx(const char* path, JSValueRef *exception){
+
+    FILE* f = fopen(path, "r");
+    if( f == NULL ){
+        return NULL;
+    }
+
+    fseek(f, 0, SEEK_END);
+    int length = ftell(f);
+    fseek(f, 0, SEEK_SET);
+
+    if( length > 0 )
+    {
+        char buff[length+1];
+        memset(buff, '\0', length+1);
+        int r = fread(buff, 1, length, f);
+        fclose(f);
+
+        if( r != length ){
+            printf("error read\n");
+            return JSValueMakeUndefined(mGlobalContext);
+        }
+        return RunLineEx(buff, exception);
+    }
+    fclose(f);
+    return JSValueMakeUndefined(mGlobalContext);
+}
+
+void StandaloneConsole::RunLine(const char * line){
+    JSValueRef exception = NULL;
+    JSValueRef v = RunLineEx(line, &exception);
+    reportingResult(v,exception);
+}
+
+void StandaloneConsole::RunScript(const char * path){
+    JSValueRef exception = NULL;
+    JSValueRef v = RunScriptEx(path, &exception);
+    reportingResult(v,exception);
+}
+
+void StandaloneConsole::GarbageCollect(){
+    printf("GarbageCollect\n");
+    JSGarbageCollect(mGlobalContext);
+}
+void StandaloneConsole::reportingResult(JSValueRef v, JSValueRef exception){
+    if( exception != NULL ){
+        char *errStr = toString(mGlobalContext, exception);
+        if( errStr != NULL ){
+            printf("< error - %s\n", errStr);
+            delete[] errStr;
+        }
+        JSObjectRef errObj = JSValueToObject(mGlobalContext, exception, NULL);
+        if( errObj != NULL ){
+            JSValueRef stack = getProperty(mGlobalContext, errObj, "stack");
+            char *stackStr = NULL;
+            if( !JSValueIsUndefined(mGlobalContext, stack) && (stackStr = toString(mGlobalContext, stack )) != NULL){
+                printf("stack:%s\n", stackStr);
+                delete[] stackStr;
+            }
+        }
+    }else{
+        char *resultStr = toString(mGlobalContext, v);
+        if( resultStr != NULL ){
+            printf("< %s\n", resultStr);
+            delete[] resultStr;
+        }
+    }
+}
+
+JSObjectRef StandaloneConsole::registModule(const char * name, JSClassRef module, void * priv){
+    JSObjectRef obj = JSObjectMake(mGlobalContext, module, priv);
+    setProperty(mGlobalContext, mGlobalObject, name, obj, kJSPropertyAttributeReadOnly);
+    return obj;
+}
+
+void StandaloneConsole::appendModule(const char * name, JSObjectRef module){
+    setProperty(mGlobalContext, mGlobalObject, name, module, kJSPropertyAttributeReadOnly);
+}
+
+
+int getch(void)
+{
+    int ch;
+    struct termios buf;
+    struct termios save;
+
+    tcgetattr(0, &save);
+    buf = save;
+    buf.c_lflag &= ~(ICANON|ECHO);
+    buf.c_cc[VMIN] = 1;
+    buf.c_cc[VTIME] = 0;
+    tcsetattr(0, TCSAFLUSH, &buf);
+    ch = getchar();
+    tcsetattr(0, TCSAFLUSH, &save);
+    return ch;
+}
+
+struct termios gSave;
+
+void onExit(void)
+{
+    tcsetattr(0, TCSAFLUSH, &gSave);
+}
+
+class LineBuffer{
+    vector<string> mHistory;
+    string mLine;
+    int mHistoryIndex;
+    unsigned int mCurrentPos;
+    unsigned int mCurrentPosTmp;
+    int mLineLength;
+public:
+    LineBuffer():mHistoryIndex(0), mCurrentPos(0){
+        tcgetattr(0, &gSave);
+        atexit(onExit);
+    }
+    ~LineBuffer(){
+        tcsetattr(0, TCSAFLUSH, &gSave);
+    }
+
+    void backSpace( int length ){
+        for( int i =0 ; i < length ; i++){
+            putchar('\b');
+            putchar(' ');
+            putchar('\b');
+        }
+    }
+
+    void cleanLine(){
+        int diff = mLineLength - mCurrentPosTmp;
+        while( diff-- > 0 ){
+            moveCursor(false);
+        }
+        backSpace(mLineLength);
+    }
+
+    void applyHistory( unsigned int index ){
+        if( mHistory.size() > index ){
+            mLine = mHistory[index];
+            mCurrentPos = mLine.size();
+        }
+    }
+
+    void moveCursor( bool Left ){
+        putchar(27);putchar(91);
+        if( Left )
+            putchar(68);
+        else
+            putchar(67);
+    }
+
+    void moveCurrentCursorPosition(){
+        int diff = mLine.size() - mCurrentPos;
+
+        while( diff-- > 0 ){
+            moveCursor(true);
+        }
+    }
+
+    bool checkSpecialKeys(int a){
+        if( a == 8 ){
+            if( mLine.size() != 0 && mCurrentPos != 0){
+                mCurrentPos--;
+                mLine.erase(mCurrentPos,1);
+            }
+            return true;
+        }
+        if( a == 27 ){
+            a = getch(); // 91
+            a = getch();
+            switch( a ){
+                case 65:
+                    //UP
+                    if( mHistoryIndex > 0 ){
+                        applyHistory(--mHistoryIndex);
+                    }
+                    break;
+                case 66:
+                    //DOWN
+                    if( (unsigned)mHistoryIndex < mHistory.size() ){
+                        applyHistory(++mHistoryIndex);
+                    }
+                    break;
+                case 67:
+                    //RIGHT
+                    if( mCurrentPos < mLine.size())
+                        mCurrentPos++;
+                    break;
+                case 68:
+                    //LEFT
+                    if( mCurrentPos > 0 )
+                        mCurrentPos--;
+                    break;
+                case 51:
+                    //delete
+                    getch();
+                    if( mCurrentPos < mLine.size())
+                        mLine.erase(mCurrentPos,1);
+                    break;
+                case 52:
+                    //end
+                    getch();
+                    mCurrentPos = mLine.size();
+                    break;
+                case 49:
+                    //home
+                    mCurrentPos = 0;
+                    a = getch();
+                    break;
+                default:
+                    a = getch();
+            }
+
+            return true;
+        }
+        return false;
+    }
+
+    string Prompt(const char * prompt){
+        printf("%s", prompt);
+        mCurrentPos = 0;
+        mLine.clear();
+        mLineLength = mLine.size();
+        mCurrentPosTmp = mCurrentPos;
+        while(1){
+            int a = getch();
+            cleanLine();
+            if( a == 10 )
+                break;
+
+            if(!checkSpecialKeys(a)){
+                mLine.insert(mCurrentPos,1, a);
+                mCurrentPos++;
+            }
+            cout << mLine;
+            moveCurrentCursorPosition();
+            mLineLength = mLine.size();
+            mCurrentPosTmp = mCurrentPos;
+        }
+        cout << mLine;
+        if( mLine.size() > 0 ){
+            mHistory.push_back(mLine);
+            mHistoryIndex = mHistory.size();
+        }
+        return mLine;
+    }
+
+};
+
+
+
+void StandaloneConsole::commandline(StandaloneConsole* console){
+    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+    printf("command line mode ( \"quit\" for exit  )\n");
+    LineBuffer linebuff;
+    while(1){
+        pthread_mutex_lock(&lock);
+        string line = linebuff.Prompt(">");
+        printf("\n");
+
+        if( line == "quit" )
+            break;
+        if( line == "gc" ){
+            console->GarbageCollect();
+            continue;
+        }
+        if( line.size() == 0 )
+            continue;
+        _Command *cmd = new _Command(line.c_str(), console, &lock);
+        // for thread safety
+        ecore_idler_add(commandDispath, cmd);
+    }
+}
+
+
+}
+}
+
diff --git a/src/Common/StandaloneConsole/StandaloneConsole.h b/src/Common/StandaloneConsole/StandaloneConsole.h
new file mode 100644 (file)
index 0000000..b125f8e
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_COMMON_STANDALONECONSOLE_
+#define _TIZEN_COMMON_STANDALONECONSOLE_
+
+#include <Ecore.h>
+#include <map>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Test{
+
+class StandaloneConsole{
+    public :
+        StandaloneConsole();
+        virtual ~StandaloneConsole();
+        void initialize();
+        JSObjectRef getGlobalObject();
+        JSContextRef getGlobalContext();
+
+        void RunLine(const char *line);
+        void RunScript(const char * path);
+
+        void GarbageCollect();
+
+
+        JSValueRef RunLineEx( const char *line , JSValueRef *exception);
+        JSValueRef RunScriptEx( const char *path , JSValueRef *exception);
+
+        JSObjectRef registModule( const char *name, JSClassRef module, void *priv);
+        void appendModule( const char* name, JSObjectRef module );
+
+        static JSValueRef alert(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+        static JSValueRef setInterval(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+        static JSValueRef clearInterval(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+        static JSValueRef setTimeout(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+        static void commandline(StandaloneConsole *console);
+
+    private:
+        static Eina_Bool timerCb(void *data);
+        void reportingResult(JSValueRef v, JSValueRef exception);
+
+        JSContextRef mGlobalContext;
+        JSObjectRef mGlobalObject;
+        std::map<int,int> mTimerMap;
+};
+
+}
+}
+
+#endif //_TIZEN_COMMON_STANDALONECONSOLE_
diff --git a/src/Common/TimeTracer/CMakeLists.txt b/src/Common/TimeTracer/CMakeLists.txt
new file mode 100644 (file)
index 0000000..3dddade
--- /dev/null
@@ -0,0 +1,24 @@
+SET(TARGET "timetracer")
+
+SET(SRCS
+  TimeTracer.c
+)
+
+INCLUDE_DIRECTORIES(
+       ${TOP}/Common
+)
+
+ADD_DEFINITIONS("-DTIME_TRACER_UNIT_MSEC")
+
+ADD_LIBRARY(${TARGET} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET}
+  ${LIBS_COMMON}
+)
+
+INSTALL(TARGETS ${TARGET} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${COMMON_DESTINATION_NAME})
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/common
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
+
diff --git a/src/Common/TimeTracer/TimeTracer.c b/src/Common/TimeTracer/TimeTracer.c
new file mode 100755 (executable)
index 0000000..c670ff9
--- /dev/null
@@ -0,0 +1,463 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#undef LOG_TAG
+#define LOG_TAG "TIME_TRACER"
+
+#include <stdio.h>
+#include <dlog.h>
+#include <stdio.h>
+#include <malloc.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/time.h>
+#include <sys/utsname.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include "TimeTracer.h"
+
+/*
+* Global Variables
+*/
+#define TIME_TRACER_ITEM_MAX    500
+
+#ifdef USE_REFACTORING_VERSION
+#define OUTPUT_DIR "/opt/usr/media/wrt-plugins-tizen-time-trace-result"
+const int REPORT_FORMAT_CSV = 1;
+#else
+#define OUTPUT_DIR "/tmp/wrt-plugins-tizen-time-trace-result"
+const int REPORT_FORMAT_CSV = 0;
+#endif
+
+time_tracer_item ** g_items = NULL; //Time tracer item list
+static int g_index = 0;
+static int g_max_item_name_length = 0;
+static long long g_first_time = 0;
+
+#ifdef TIME_TRACER_UNIT_MSEC
+static long long CURRENT_TIME()
+{
+    struct timeval startTime;
+    gettimeofday(&startTime, NULL);
+    long long usec = (long long)(((long long)(unsigned long)startTime.tv_sec) * 1000000LL + (long long)(startTime.tv_usec));
+    return usec/1000;
+}
+#else
+static long long CURRENT_TIME()
+{
+    struct timeval startTime;
+    gettimeofday(&startTime, NULL);
+    return (long long)(((long long)(unsigned long)startTime.tv_sec) * 1000000LL + (long long)(startTime.tv_usec));
+}
+#endif
+
+
+/*
+* Internal Implementation
+*/
+static void __time_tracer_item_free(void)
+{
+    int i = 0;
+    if (!g_items)
+        return;
+
+    for(i=0;i<g_index;i++)
+    {
+        if(g_items[i])
+        {
+            if (g_items[i]->name)
+                free(g_items[i]->name);
+            free(g_items[i]);
+            g_items[i] = NULL;
+        }
+    }
+
+    g_index = 0;
+    g_max_item_name_length = 0;
+    g_first_time = 0;
+    free(g_items);
+    g_items = NULL;
+}
+
+static int __get_time_tracer_item_index(char* name)
+{
+    int i;
+    assert(name);
+    if(!g_items)
+        return -1;
+
+    for ( i = 0; i < g_index; i++ )
+    {
+        if(!g_items[i])
+            return -1;
+        if (strcmp(name, g_items[i]->name)==0)
+            return i;
+    }
+    return -1;
+}
+
+
+/*
+* Implementation
+*/
+int time_tracer_init(void)
+{
+    if (g_items) {
+        LOGW("[%s] Ignored. Already Initialized.", __FUNCTION__);
+        return 0;
+    }
+    g_items = (time_tracer_item **) malloc(TIME_TRACER_ITEM_MAX * sizeof(time_tracer_item *));
+    if(!g_items)
+    {
+        LOGE("[%s] Failed to create global tracer item",__FUNCTION__);
+        return -1;
+    }
+    g_first_time = CURRENT_TIME();
+    LOGE("TIME TRACER INITIALIZED");
+    return 0;
+}
+
+int time_tracer_release(void)
+{
+    if (!g_items)
+        return 0;
+    LOGE("TIME TRACER DESTROYED");
+    __time_tracer_item_free();
+    return 0;
+}
+
+int time_tracer_item_begin(const char* name, int show, const char* filename, int line)
+{
+    time_tracer_item *item = NULL;
+    int index = 0;
+    int name_len = 0;
+
+    if (!g_items)
+        return 0;
+
+    if (g_index == TIME_TRACER_ITEM_MAX)
+    {
+        LOGE("[%s] Do not exceed tracer item max value (max : %d, index : %d)",__FUNCTION__,TIME_TRACER_ITEM_MAX, g_index);
+        return -1;
+    }
+
+    if (!name)
+    {
+        LOGE("[%s] Item name is NULL.",__FUNCTION__);
+        return -1;
+    }
+
+    name_len = strlen(name);
+    if(name_len==0)
+    {
+        LOGE("[%s] Item name is Empty.",__FUNCTION__);
+        return -1;
+    }
+
+    //1. Creates of gets the item
+    //1-1. Creates new item if 'name' is not exists.
+    if ((index = __get_time_tracer_item_index((char*)name)) == -1)
+    {
+        item = (time_tracer_item *)malloc(sizeof(time_tracer_item));
+        if ( !item )
+        {
+            LOGE("[%s] Failed to create tracer item", __FUNCTION__);
+            return -1;
+        }
+
+        //Clean-up
+        memset( item, 0, sizeof (time_tracer_item) );
+        item->min_elapsed_time = 0xFFFFFFFF;
+
+        item->name = strdup(name);
+        if (!item->name)
+        {
+            LOGE("[%s] Failed to strdup", __FUNCTION__);
+            free(item);
+            return -1;
+        }
+
+        //Add to the global item array
+        g_items[g_index] = item;
+        g_index++;
+
+        if ( g_max_item_name_length < name_len )
+            g_max_item_name_length = name_len;
+    }
+    else // 1-2. Returns existing item
+    {
+        item = g_items[index];
+    }
+
+
+    // 2. Gets the timestamp
+    item->timestamp = CURRENT_TIME();
+
+
+    if (item->first_timestamp == 0) // in case of first
+    {
+        //set first timestamp
+        item->first_timestamp = item->timestamp;
+        if (g_first_time > item->first_timestamp)
+            g_first_time = item->first_timestamp;
+    }
+
+    // 3. Verify pairs of begin, end
+    if (item->on_tracing)
+    {
+        LOGE("[%s] (Name : %s) is not 'end'ed!",__FUNCTION__, item->name);
+        item->mismatch_count ++;
+        return -1;
+    }
+
+    //set tracing on
+    item->on_tracing = 1;
+
+    if (show)
+    {
+        LOGE("[%s][BEGIN] %s (at %s:%d)", __FUNCTION__,name, filename, line );
+        printf("[%s][BEGIN] %s (at %s:%d)\n", LOG_TAG,name, filename, line );
+    }
+    //Add invoke count for given item
+    item->invoke_count++;
+    return 0;
+}
+
+int time_tracer_item_end(const char* name, int show, const char* filename, int line)
+{
+    time_tracer_item * item = NULL;
+    long long tval = 0;
+    int index = 0;
+
+    if (!g_items)
+        return 0;
+
+    // 1. Gets current timestamp first for more accuracy.
+    tval = CURRENT_TIME();
+
+    if (g_index == TIME_TRACER_ITEM_MAX)
+    {
+        LOGE("[%s] Do not exceed tracer item max value (max : %d, index : %d)",__FUNCTION__,TIME_TRACER_ITEM_MAX, g_index);
+        return -1;
+    }
+
+    if (!name)
+    {
+        LOGE("[%s] Item name is NULL.",__FUNCTION__);
+        return -1;
+    }
+
+    if(strlen(name)==0)
+    {
+        LOGE("[%s] Item name is Empty.",__FUNCTION__);
+        return -1;
+    }
+
+    //2. Gets the item
+    if ((index = __get_time_tracer_item_index((char*)name)) == -1)
+    {
+        LOGE("[%s] (Name : %s) is not exist.",__FUNCTION__, name);
+        return -1;
+    }
+    item = g_items[index];
+
+    // 3. Verify pairs of begin, end
+    if (!item->on_tracing)
+    {
+        LOGE("[%s] (Name : %s) is not 'begin' yet",__FUNCTION__, item->name);
+        item->mismatch_count ++;
+        return -1;
+    }
+
+    //set last timestamp as current time
+    item->last_timestamp = tval;
+
+    //calculates the time gap(elapsed time) between current timestamp and item's timestamp.
+    tval = tval - item->timestamp;
+
+    //set max_elapsed_time if current elapsed time is larger than item's max elasped time.
+    item->max_elapsed_time = tval > item->max_elapsed_time ? tval : item->max_elapsed_time;
+    //set min_elapsed_time if current elapsed time is less than item's min elasped time.
+    item->min_elapsed_time = tval < item->min_elapsed_time ? tval : item->min_elapsed_time;
+
+    //Accumulates the item's total elapse time
+    item->total_elapsed_time += tval;
+    //set tracing off
+    item->on_tracing = 0;
+
+    if (show)
+    {
+        LOGE("[%s][END] %s - total elapsed time(acc): %lld, current elased time : %lld (at %s:%d)",__FUNCTION__, name, item->total_elapsed_time, tval, filename, line );
+        printf("[%s][END] %s - total elapsed time(acc): %lld, current elased time : %lld (at %s:%d)\n",LOG_TAG,name, item->total_elapsed_time, tval, filename, line );
+    }
+    return 0;
+}
+
+void time_tracer_export_report(int direction, char* name)
+{
+    int i = 0;
+    char format[256] = "";
+    FILE* fp = stderr;
+
+    if (!g_items)
+        return;
+
+    switch (direction)
+    {
+        case TIME_TRACER_EXPORT_STDOUT:
+            fp = stdout;
+            break;
+        case TIME_TRACER_EXPORT_STDERR:
+            fp = stderr;
+            break;
+        case TIME_TRACER_EXPORT_FILE:
+            if(mkdir(OUTPUT_DIR,0755)!=0)
+            {
+                LOGE("[%s] Failed to mkdir()",__FUNCTION__);
+            }
+            char f_name[256];
+            if(name==NULL || strlen(name)==0) {
+#ifdef USE_REFACTORING_VERSION
+                sprintf(f_name,"%s/default.%d.log",OUTPUT_DIR,getpid());
+#else
+                sprintf(f_name,"%s/%s",OUTPUT_DIR,"default.log");
+#endif
+            }
+            else {
+#ifdef USE_REFACTORING_VERSION
+                sprintf(f_name,"%s/%s.%d.%s",OUTPUT_DIR,name,getpid(),"log");
+#else
+                sprintf(f_name,"%s/%s.%s",OUTPUT_DIR,name,"log");
+#endif
+            }
+
+            fp = fopen(f_name, "wt");
+            if (!fp)
+            {
+                LOGE("[%s] Failed to fopen().",__FUNCTION__);
+                return;
+            }
+            break;
+        default:
+            LOGE("[%s] Invalid output direction.",__FUNCTION__);
+            return;
+    }
+
+    if(REPORT_FORMAT_CSV) {
+        for ( i = 0; i < g_index; i++ ) {
+            if (g_items[i]->invoke_count == 0) {
+                g_items[i]->invoke_count = 1;
+            }
+
+            long long average = 0;
+            if (g_items[i]->total_elapsed_time == 0 || g_items[i]->invoke_count <3) {
+                average = 0;
+            }
+            else {
+                average = ((g_items[i]->total_elapsed_time) - (g_items[i]->min_elapsed_time) - (g_items[i]->max_elapsed_time)) / (g_items[i]->invoke_count-2);
+            }
+
+            fprintf(fp, "%s,%lld\n", g_items[i]->name, average);
+            print_log(DLOG_ERROR, LOG_TAG, "%s,%lld\n", g_items[i]->name, average);
+        }
+    }
+    else {
+
+#ifdef USE_REFACTORING_VERSION
+    snprintf(format, sizeof(format)-1,"[%%3d] %%-%ds |\tTotal:%%lld,\tCnt:%%lld,\tAvg:%%lld/%%lld,\tMin:%%lld,\tMax:%%lld,\tStart:%%lld,\tEnd:%%lld,\tMismatch:%%lld\n", g_max_item_name_length);
+    fprintf(fp, "TIME TRACER REPORT [BEGIN]=========================== [# of Item:%d, unit(usec)]\n", g_index);
+    LOGE("TIME TRACER REPORT [BEGIN]=========================== [# of Item:%d, unit(usec)]", g_index);
+#else
+#ifdef TIME_TRACER_UNIT_MSEC
+    snprintf(format, sizeof(format)-1, "[%%3d] %%-%ds|\tTotal:%%4ld,\tCnt:%%3ld,\tAvg:%%4ld,\tMin:%%4ld,\tMax:%%4ld,\tStart:%%4lu,\tEnd:%%4lu,\tMismatch:%%3ld\n", g_max_item_name_length);
+    fprintf(fp, "TIME TRACER REPORT [BEGIN]=========================== [# of Item:%d, unit(msec)]\n", g_index);
+    LOGE("TIME TRACER REPORT [BEGIN]=========================== [# of Item:%d, unit(msec)]", g_index);
+#else
+    snprintf(format, sizeof(format)-1, "[%%3d] %%-%ds |\tTotal:%%ld,\tCnt:%%ld,\tAvg:%%ld,\tMin:%%ld,\tMax:%%ld,\tStart:%%lu,\tEnd:%%lu,\tMismatch:%%ld\n", g_max_item_name_length);
+    fprintf(fp, "TIME TRACER REPORT [BEGIN]=========================== [# of Item:%d, unit(usec)]\n", g_index);
+    LOGE("TIME TRACER REPORT [BEGIN]=========================== [# of Item:%d, unit(usec)]", g_index);
+#endif
+#endif
+
+        for ( i = 0; i < g_index; i++ ) {
+            if (g_items[i]->invoke_count == 0) {
+                g_items[i]->invoke_count = 1;
+            }
+
+#ifdef USE_REFACTORING_VERSION
+            fprintf(fp, format, i,
+                g_items[i]->name, // item name
+                g_items[i]->total_elapsed_time, // total elasped time
+                g_items[i]->invoke_count, // # of call
+                (g_items[i]->total_elapsed_time == 0) ? 0 : (g_items[i]->total_elapsed_time / g_items[i]->invoke_count), // calculates the average elapsed time
+                (g_items[i]->total_elapsed_time == 0 || g_items[i]->invoke_count <3) ? 0 : ((g_items[i]->total_elapsed_time-g_items[i]->min_elapsed_time-g_items[i]->max_elapsed_time) / (g_items[i]->invoke_count-2)), // calculates the average elapsed time (exclude min/max)
+                g_items[i]->min_elapsed_time, // mininum elpased time
+                g_items[i]->max_elapsed_time,// maximum elpased time
+                g_items[i]->first_timestamp - g_first_time, //begin timestamp
+                g_items[i]->last_timestamp - g_first_time, //end timestamp
+                g_items[i]->mismatch_count ); // # of mismatch (begin - end mismatch)
+
+            print_log(DLOG_ERROR, LOG_TAG, format,i,
+                g_items[i]->name,
+                g_items[i]->total_elapsed_time,
+                g_items[i]->invoke_count,
+                (g_items[i]->total_elapsed_time == 0) ? 0 : (g_items[i]->total_elapsed_time / (long long)g_items[i]->invoke_count),
+                (g_items[i]->total_elapsed_time == 0 || g_items[i]->invoke_count <3) ? 0 : ((g_items[i]->total_elapsed_time-g_items[i]->min_elapsed_time-g_items[i]->max_elapsed_time) / (g_items[i]->invoke_count-2)),
+                g_items[i]->min_elapsed_time,
+                g_items[i]->max_elapsed_time,
+                g_items[i]->first_timestamp - g_first_time,
+                g_items[i]->last_timestamp - g_first_time,
+                g_items[i]->mismatch_count );
+#else
+        fprintf(fp, format, i,
+                g_items[i]->name, // item name
+                g_items[i]->total_elapsed_time, // total elasped time
+                g_items[i]->invoke_count, // # of call
+                (g_items[i]->total_elapsed_time == 0)?0:(int)(g_items[i]->total_elapsed_time / g_items[i]->invoke_count), // calculates the average elapsed time
+                g_items[i]->min_elapsed_time, // mininum elpased time
+                g_items[i]->max_elapsed_time,// maximum elpased time
+                g_items[i]->first_timestamp - g_first_time, //begin timestamp
+                g_items[i]->last_timestamp - g_first_time, //end timestamp
+                g_items[i]->mismatch_count ); // # of mismatch (begin - end mismatch)
+
+        print_log(DLOG_ERROR, LOG_TAG, format, i,
+                g_items[i]->name,
+                g_items[i]->total_elapsed_time,
+                g_items[i]->invoke_count,
+                (g_items[i]->total_elapsed_time == 0) ? 0 : (int)(g_items[i]->total_elapsed_time / g_items[i]->invoke_count),
+                g_items[i]->min_elapsed_time,
+                g_items[i]->max_elapsed_time,
+                g_items[i]->first_timestamp - g_first_time,
+                g_items[i]->last_timestamp - g_first_time,
+                g_items[i]->mismatch_count);
+
+#endif
+        }
+
+        fprintf(fp, "TIME TRACER REPORT [END]  ============================\n");
+        LOGE("TIME TRACER REPORT [END]  ============================");
+    }
+
+    if (direction == TIME_TRACER_EXPORT_FILE) {
+        fclose(fp);
+    }
+}
diff --git a/src/Common/TimeTracer/TimeTracer.h b/src/Common/TimeTracer/TimeTracer.h
new file mode 100755 (executable)
index 0000000..6bbc90e
--- /dev/null
@@ -0,0 +1,120 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_COMMON_TIME_TRACER__
+#define __TIZEN_COMMON_TIME_TRACER__
+
+#ifdef __cplusplus
+
+#if defined(ENABLE_TIME_TRACER) && defined(__cplusplus)
+#include <string>
+#endif
+
+extern "C" {
+#endif
+
+typedef struct _time_tracer_item
+{
+       char* name;
+       long long total_elapsed_time;
+       long long min_elapsed_time;
+       long long max_elapsed_time;
+       long long first_timestamp;
+       long long last_timestamp;
+       long long timestamp;
+       int on_tracing;
+       long long invoke_count;
+       long long mismatch_count;
+} time_tracer_item;
+
+/* COMMON */
+int time_tracer_init(void);
+int time_tracer_release(void);
+void time_tracer_export_report(int direction, char* name);
+int time_tracer_item_begin(const char* name, int show,const  char* filename, int line);
+int time_tracer_item_end(const char* name, int show, const char* filename, int line);
+
+#define TIME_TRACER_EXPORT_STDOUT      0
+#define TIME_TRACER_EXPORT_STDERR      1
+#define TIME_TRACER_EXPORT_FILE        2
+
+#ifdef ENABLE_TIME_TRACER
+//Initialize the time tracer
+#define TIME_TRACER_INIT()     (time_tracer_init())
+//Release the time tracer
+#define TIME_TRACER_RELEASE()  (time_tracer_release())
+//Export tracing report to stdout
+#define TIME_TRACER_EXPORT_REPORT()            (time_tracer_export_report(TIME_TRACER_EXPORT_STDOUT,NULL))
+//Export tracing report to user specific direction (stdout, stderr, file)
+#define TIME_TRACER_EXPORT_REPORT_TO(x,y)      (time_tracer_export_report(x,y))
+//Set tracing point to begin
+#define TIME_TRACER_ITEM_BEGIN(name,show)      (time_tracer_item_begin(name,show,__FILE__,__LINE__))
+//Set tracing point to end
+#define TIME_TRACER_ITEM_END(name,show)        (time_tracer_item_end(name,show,__FILE__,__LINE__)      )
+#else
+#define TIME_TRACER_INIT()
+#define TIME_TRACER_RELEASE()
+#define TIME_TRACER_EXPORT_REPORT()
+#define TIME_TRACER_EXPORT_REPORT_TO(x,y)
+#define TIME_TRACER_ITEM_BEGIN(name,show)
+#define TIME_TRACER_ITEM_END(name,show)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#if defined(ENABLE_TIME_TRACER) && defined(__cplusplus)
+class TimeTracerItem {
+public:
+    TimeTracerItem(const char* file, const char* function, int line, int show)
+        : m_file(file), m_function(function), m_show(show)
+    {
+        m_name = formatName(file, function);
+        time_tracer_item_begin(m_name.c_str(), show, file, line);
+    }
+
+    virtual ~TimeTracerItem()
+    {
+        time_tracer_item_end(m_name.c_str(), m_show, m_file, 0);
+    }
+
+private:
+    static std::string formatName(const char* file, const char* function)
+    {
+        static const std::string s_src_path_pattern("/src/");
+        std::string filestr(file);
+        size_t found_at = filestr.find(s_src_path_pattern);
+
+        if(found_at != std::string::npos) {
+            filestr = filestr.substr(found_at + s_src_path_pattern.length());
+        }
+        return filestr + ":" + std::string(function);
+    }
+
+    const char* m_file;
+    const char* m_function;
+    std::string m_name;
+    int m_show;
+};
+
+#define SET_TIME_TRACER_ITEM(_show_) TimeTracerItem _time_tracer_item_(__FILE__, __FUNCTION__, __LINE__ , _show_)
+#else
+#define SET_TIME_TRACER_ITEM(_show_)
+#endif // ENABLE_TIME_TRACER
+
+#endif //__TIZEN_COMMON_TIME_TRACER__
diff --git a/src/Common/WebAPIError.cpp b/src/Common/WebAPIError.cpp
new file mode 100644 (file)
index 0000000..5b799e4
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "WebAPIError.h"
+
+namespace DeviceAPI {
+namespace Common {
+
+WebAPIError::WebAPIError(const int code,
+        const std::string& name,
+        const std::string& message) :
+        m_code(code), m_name(name), m_message(message)
+{
+}
+
+WebAPIError::~WebAPIError()
+{
+}
+
+int WebAPIError::getCode() const
+{
+    return m_code;
+}
+
+std::string WebAPIError::getName() const
+{
+    return m_name;
+}
+
+std::string WebAPIError::getMessage() const
+{
+    return m_message;
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/WebAPIError.h b/src/Common/WebAPIError.h
new file mode 100644 (file)
index 0000000..fada9fb
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _WEBAPI_ERROR_H_
+#define _WEBAPI_ERROR_H_
+
+#include <string>
+
+namespace DeviceAPI {
+namespace Common {
+
+class WebAPIError {
+public:
+    WebAPIError(const int code,
+            const std::string& name,
+            const std::string& message = std::string());
+    virtual ~WebAPIError();
+
+    int getCode() const;
+    std::string getName() const;
+    std::string getMessage() const;
+
+private:
+    int m_code;
+    std::string m_name;
+    std::string m_message;
+};
+
+} // Common
+} // DeviceAPI
+
+#endif // _WEBAPI_ERROR_H_
diff --git a/src/Common/WebKitProxy.cpp b/src/Common/WebKitProxy.cpp
new file mode 100644 (file)
index 0000000..1664d69
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "WebKitProxy.h"
+#include <WKBundle.h>
+#include "Logger.h"
+
+using namespace std;
+
+namespace DeviceAPI {
+namespace Common {
+
+void WebKitProxy::reportException(JSContextRef context, JSValueRef exception)
+{
+    LOGW("Throwing exception to WebKit.");
+
+    if (exception)
+    {
+        WKBundleReportException(context, exception);
+    }
+}
+
+} // Common
+} // DeviceAPI
diff --git a/src/Common/WebKitProxy.h b/src/Common/WebKitProxy.h
new file mode 100644 (file)
index 0000000..e96cded
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _WEBKIT_PROXY_H_
+#define _WEBKIT_PROXY_H_
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Common {
+
+class WebKitProxy
+{
+public:
+    static void reportException(JSContextRef ctx, JSValueRef exception);
+};
+
+} // Common
+} // DeviceAPI
+
+#endif //_WEBKIT_PROXY_H_
diff --git a/src/Contact/AddressBook.cpp b/src/Contact/AddressBook.cpp
new file mode 100755 (executable)
index 0000000..b9d5c6e
--- /dev/null
@@ -0,0 +1,1396 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AddressBook.h"
+#include <Logger.h>
+#include <contacts.h>
+#include "ContactUtil.h"
+#include <PlatformException.h>
+#include "ContactSearchEngine.h"
+#include "JSContact.h"
+
+#include <algorithm>
+#include <JSWebAPIErrorFactory.h>
+#include <GlobalContextManager.h>
+#include <account.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace Common;
+
+const long AddressBook::DEFAULT_ADDRESS_BOOK_ID = 0;
+const long AddressBook::UNIFIED_ADDRESS_BOOK_ID = -1;
+const char* AddressBook::UNIFIED_ADDRESS_BOOK_NAME = "Unified address book";
+
+long AddressBook::s_listener_counter = 1;
+int AddressBook::s_latest_version = 0;
+
+AddressBook::AddressBook():
+        SecurityAccessor(),
+        m_address_book_id(0),
+        m_is_address_book_id_set(false),
+        m_name(""),
+        m_read_only(false),
+        m_is_unified(false),
+        m_account_id(0)
+{
+}
+
+AddressBook::~AddressBook()
+{
+    unregisterChangeListeners();
+}
+
+long AddressBook::getAddressBookId()
+{
+    return m_address_book_id;
+}
+
+void AddressBook::setAddressBookId(long address_book_id)
+{
+    m_is_address_book_id_set = true;
+    m_address_book_id = address_book_id;
+}
+
+bool AddressBook::isAddressBookIdSet()
+{
+    return m_is_address_book_id_set;
+}
+
+std::string AddressBook::getName()
+{
+    return m_name;
+}
+
+void AddressBook::setName(const std::string &name)
+{
+    m_name = name;
+}
+
+bool AddressBook::getReadOnly()
+{
+    return m_read_only;
+}
+
+void AddressBook::setReadOnly(bool read_only)
+{
+    m_read_only = read_only;
+}
+
+
+bool AddressBook::getIsUnified() const
+{
+    return m_is_unified;
+}
+
+void AddressBook::setIsUnified(bool is_unified)
+{
+    if (is_unified) {
+        m_is_address_book_id_set = false;
+    }
+    m_is_unified = is_unified;
+}
+
+unsigned long AddressBook::getAccountId()
+{
+    return m_account_id;
+}
+
+void AddressBook::setAccountId(unsigned long account_id)
+{
+
+    m_account_id = account_id;
+}
+
+void AddressBook::updateAdditionalInformation(ContactPtr contact,
+        contacts_record_h_ptr& contacts_record_ptr)
+{
+    int int_value = -1;
+    ContactUtil::getIntFromRecord(*contacts_record_ptr,
+            _contacts_contact.person_id, &int_value);
+    contact->setPersonId(static_cast<long>(int_value));
+    ContactUtil::getIntFromRecord(*contacts_record_ptr,
+            _contacts_contact.address_book_id, &int_value);
+    contact->setAddressBookId(static_cast<long>(int_value));
+    ContactUtil::getIntFromRecord(*contacts_record_ptr,
+            _contacts_contact.changed_time, &int_value);
+    contact->setLastUpdated(static_cast<std::time_t>(int_value));
+    bool bool_value = false;
+    ContactUtil::getBoolFromRecord(*contacts_record_ptr,
+            _contacts_contact.is_favorite, &bool_value);
+    contact->setIsFavorite(bool_value);
+}
+
+ContactPtr AddressBook::get(long contact_id)
+{
+    int err = CONTACTS_ERROR_NONE;
+    ContactPtr contact = ContactPtr(new(std::nothrow) Contact());
+    if (!contact) {
+        LOGW("Contact is null");
+        throw Common::UnknownException("Contact is null");
+    }
+    contacts_record_h contacts_record = NULL;
+    err = contacts_db_get_record(_contacts_contact._uri, contact_id, &contacts_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException<NotFoundException>(err, "contacts_db_get_record()");
+    }
+    contacts_record_h_ptr contacts_record_ptr(&contacts_record, contactsDeleter);
+    contact->setId(contact_id);
+
+    contact->importFromContactsRecord(*contacts_record_ptr);
+    updateAdditionalInformation(contact, contacts_record_ptr);
+
+    return contact;
+}
+
+void AddressBook::add(ContactPtr contact)
+{
+    LOGE("Entered");
+    int err = CONTACTS_ERROR_NONE;
+    if (contact->isSet(ContactAttribute::CONTACT_ATTRIBUTE_ID)) {
+        LOGE("Contact already exists");
+        throw Common::UnknownException("Contact already exists");
+    }
+
+    contacts_record_h contacts_record = NULL;
+    err = contacts_record_create(_contacts_contact._uri, &contacts_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+
+    //contacts_record starts to be protected by unique_ptr
+    contacts_record_h_ptr contacts_record_ptr(&contacts_record, contactsDeleter);
+    contact->exportToContactsRecord(*contacts_record_ptr);
+
+    int id = -1;
+    err = contacts_db_insert_record(*contacts_record_ptr, &id);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_db_insert_record()");
+    }
+    contact->setId(static_cast<long>(id));
+
+    contacts_record_h reset_record;
+    err = contacts_db_get_record(_contacts_contact._uri, id, &reset_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_db_get_record()");
+    }
+    if ( NULL != reset_record ) {
+        LOGE("reset");
+        contacts_record_ptr.reset(&reset_record);
+    }
+
+    updateAdditionalInformation(contact, contacts_record_ptr);
+}
+
+gboolean AddressBook::addBatchCallback(void *data)
+{
+    auto callback = static_cast<ContactArrayCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    auto contacts = callback->getContacts();
+    if (!contacts) {
+        LOGE("contacts is null");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            JSObjectRef arr = ptrVectorToJSObjectArray<JSContact, ContactPtr>(
+                    *contacts, context);
+            callback->callSuccessCallback(arr);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* AddressBook::addBatchThread(void *data)
+{
+    auto callback = static_cast<ContactArrayCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    auto contacts = callback->getContacts();
+    if (!contacts) {
+        LOGE("contacts is null");
+        return NULL;
+    }
+
+    int size = contacts->size();
+
+    long address_book_id = callback->getAddressBookId();
+
+    try {
+        int error_code = 0;
+        contacts_list_h contacts_list = NULL;
+
+        error_code = contacts_list_create(&contacts_list);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_list_create()");
+        }
+
+        contacts_list_h_ptr contacts_list_ptr(&contacts_list,
+                contactsListDeleter);
+
+        auto it = contacts->begin();
+        auto ite = contacts->end();
+
+        for (;it != ite; ++it) {
+            ContactPtr contact = *it;
+            contacts_record_h contacts_record = NULL;
+
+            error_code = contacts_record_create(_contacts_contact._uri,
+                    &contacts_record);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_record_create()");
+            }
+
+            contact->exportToContactsRecord(contacts_record);
+
+            if(UNIFIED_ADDRESS_BOOK_ID == address_book_id) {
+                error_code = contacts_record_set_int(contacts_record,
+                        _contacts_contact.address_book_id, 0);
+            }
+            else {
+                error_code = contacts_record_set_int(contacts_record,
+                        _contacts_contact.address_book_id, address_book_id);
+            }
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_record_set_int()");
+            }
+
+            error_code = contacts_list_add(*contacts_list_ptr, contacts_record);
+            if(CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_list_add()");
+            }
+        }
+
+        int *ids;
+        int count;
+        error_code = contacts_db_insert_records(*contacts_list_ptr, &ids, &count);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_insert_records()");
+        }
+
+        if (size != count) {
+            LOGW("Added different number of contacts");
+        }
+
+        int err = CONTACTS_ERROR_NONE;
+        for(int i = 0; i < count; i++) {
+            contacts->at(i)->setId(ids[i]);
+            contacts->at(i)->setAddressBookId(callback->getAddressBookId());
+
+            contacts_record_h contact_record;
+            err = contacts_db_get_record(_contacts_contact._uri, ids[i], &contact_record);
+            if (CONTACTS_ERROR_NONE != err) {
+                LOGE("ret: %d", err);
+                ContactUtil::throwContactException(err, "contacts_db_get_record()");
+            }
+            contacts_record_h_ptr contacts_record_ptr(&contact_record, contactsDeleter);
+
+            int int_value = -1;
+            ContactUtil::getIntFromRecord(*contacts_record_ptr,
+                    _contacts_contact.person_id, &int_value);
+            contacts->at(i)->setPersonId(static_cast<long>(int_value));
+            ContactUtil::getIntFromRecord(*contacts_record_ptr,
+                    _contacts_contact.changed_time, &int_value);
+            contacts->at(i)->setLastUpdated(static_cast<std::time_t>(int_value));
+            bool bool_value = false;
+            ContactUtil::getBoolFromRecord(*contacts_record_ptr,
+                    _contacts_contact.is_favorite, &bool_value);
+            contacts->at(i)->setIsFavorite(bool_value);
+        }
+        delete[] ids;
+        ids = NULL;
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+    }
+    catch (...) {
+        LOGE("addBatchThread fails");
+        callback->setError("UnknownError", "addBatchThread fails");
+    }
+
+    guint id = g_idle_add(addBatchCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    return NULL;
+}
+
+void AddressBook::addBatch(ContactArrayCallbackData *callback)
+{
+    callback->setAddressBookId(m_address_book_id);
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, addBatchThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void AddressBook::update(ContactPtr contact)
+{
+    int err = CONTACTS_ERROR_NONE;
+
+    if(!contact){
+        LOGE("Contact pointer is NULL");
+        throw Common::TypeMismatchException("Contact pointer is NULL");
+    }
+
+    if (!contact->isSet(ContactAttribute::CONTACT_ATTRIBUTE_ID)) {
+        LOGE("Contact doesn't exists");
+        throw Common::UnknownException("Contact doesn't exists");
+    }
+
+    if(contact->getId() != 0 && contact->getAddressBookId()){
+        LOGE("Contact is not saved in databased");
+        throw Common::InvalidValuesException("Contact is not saved in databased");
+    }
+
+    contacts_record_h to_update = NULL;
+    err = contacts_db_get_record(_contacts_contact._uri, contact->getId(), &to_update);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException<NotFoundException>(err, "contacts_db_get_record()");
+    }
+    contacts_record_h_ptr contacts_record_ptr(&to_update, contactsDeleter);
+    contact->exportToContactsRecord(*contacts_record_ptr);
+    err = contacts_db_update_record(*contacts_record_ptr);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        if (CONTACTS_ERROR_INVALID_PARAMETER == err) {
+            ContactUtil::throwContactException<Common::NotFoundException>(err, "contacts_db_update_record()");
+        }
+        ContactUtil::throwContactException(err, "contacts_db_update_record()");
+    }
+    updateAdditionalInformation(contact, contacts_record_ptr);
+}
+
+void AddressBook::remove(long contact_id)
+{
+    int err = CONTACTS_ERROR_NONE;
+    err = contacts_db_delete_record(_contacts_contact._uri, contact_id);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        if (CONTACTS_ERROR_NO_DATA == err) {
+            ContactUtil::throwContactException<Common::NotFoundException>(err, "contacts_db_delete_record()");
+        }
+        ContactUtil::throwContactException(err, "contacts_db_delete_record()");
+    }
+}
+
+gboolean AddressBook::batchOperationCallback(void *data)
+{
+    auto callback = static_cast<OperationCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            callback->callSuccessCallback();
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* AddressBook::removeBatchThread(void *data)
+{
+    auto callback = static_cast<IdArrayCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    auto contact_ids = callback->getIds();
+    if (!contact_ids) {
+        LOGE("contact ids is null");
+        return NULL;
+    }
+
+    long address_book_id = callback->getAddressBookId();
+
+    try {
+        int error_code = 0;
+
+        const int count = contact_ids->size();
+        int ids[count];
+        memset(ids, 0, sizeof(int) * count);
+
+        for (int i = 0; i < count; i++) {
+            contacts_record_h contacts_record = NULL;
+
+            ids[i] = contact_ids->at(i);
+            error_code = contacts_db_get_record(_contacts_simple_contact._uri,
+                    ids[i], &contacts_record);
+
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException<Common::NotFoundException>(error_code, "contacts_db_get_record()");
+            }
+
+            contacts_record_h_ptr contacts_record_ptr(&contacts_record,
+                    contactsDeleter);
+
+            int current_address_book_id = 0;
+            ContactUtil::getIntFromRecord(*contacts_record_ptr,
+                    _contacts_simple_contact.address_book_id, &current_address_book_id);
+
+            if (address_book_id != current_address_book_id) {
+                LOGE("Wrong address book");
+                throw UnknownException(
+                        "Contact is not a member of this address book");
+            }
+        }
+
+        error_code = contacts_db_delete_records(_contacts_contact._uri,
+                ids, count);
+
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_delete_records()");
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+    }
+    catch (...) {
+        LOGE("removeBatchThread fails");
+        callback->setError("UnknownError", "removeBatchThread fails");
+    }
+
+    guint id = g_idle_add(batchOperationCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    return NULL;
+}
+
+void AddressBook::removeBatch(IdArrayCallbackData *callback)
+{
+    callback->setAddressBookId(m_address_book_id);
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, removeBatchThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* AddressBook::updateBatchThread(void *data)
+{
+    auto callback = static_cast<ContactArrayCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    auto contacts = callback->getContacts();
+    if (!contacts) {
+        LOGE("contacts is null");
+        return NULL;
+    }
+
+    long address_book_id = callback->getAddressBookId();
+
+    try {
+        int error_code = 0;
+        contacts_list_h contacts_list = NULL;
+
+        error_code = contacts_list_create(&contacts_list);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            if (NULL != contacts_list) {
+                int ret = contacts_list_destroy(contacts_list, false);
+                if (CONTACTS_ERROR_NONE != ret) {
+                    LOGW("%s", ContactUtil::getContactErrorString(ret, "contacts_list_destroy()").c_str());
+                }
+            }
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_list_create()");
+        }
+
+        contacts_list_h_ptr contacts_list_ptr(&contacts_list,
+                contactsListDeleter);
+
+        auto it = contacts->begin();
+        auto ite = contacts->end();
+
+        for(; it != ite; ++it) {
+            ContactPtr contact = *it;
+            contacts_record_h contacts_record = NULL;
+            if (!contact->isSet(CONTACT_ATTRIBUTE_ID)) {
+                LOGE("Contact have no id");
+                throw InvalidValuesException("Invalid contact");
+            }
+
+            error_code = contacts_db_get_record(_contacts_contact._uri, contact->getId(), &contacts_record);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_db_get_record()").c_str());
+            }
+
+            if (address_book_id != -1
+                    && (!contact->isSet(CONTACT_ATTRIBUTE_ADDRESS_BOOK_ID)
+                            || contact->getAddressBookId() != address_book_id )) {
+                LOGE("Wrong addressbook");
+                throw InvalidValuesException("Wrong address book");
+            }
+
+            contact->exportToContactsRecord(contacts_record);
+
+            error_code = contacts_list_add(*contacts_list_ptr, contacts_record);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_list_add()");
+            }
+        }
+
+        error_code = contacts_db_update_records(*contacts_list_ptr);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_update_records()");
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+    }
+    catch (...) {
+        LOGE("updateBatchThread fails");
+        callback->setError("UnknownError", "updateBatchThread fails");
+    }
+
+    guint id = g_idle_add(batchOperationCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    return NULL;
+}
+
+
+void AddressBook::updateBatch(ContactArrayCallbackData *callback)
+{
+    callback->setAddressBookId(m_address_book_id);
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, updateBatchThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+ListenersMap AddressBook::s_listeners;
+std::mutex AddressBook::s_mutex;
+
+gboolean AddressBook::changeCallbackFunc(void* data)
+{
+    LOGD("Entered");
+    auto hold = static_cast<AddressBookChangeListenerHolder*>(data);
+    if (!hold) {
+        LOGE("Listener holder is null");
+        return false;
+    }
+
+    std::unique_ptr<AddressBookChangeListenerHolder> holder(hold);
+
+    auto callback = holder->callback;
+    if (!callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+
+    try {
+        if (holder->added_contacts) {
+            callback->oncontactsadded(*holder->added_contacts);
+        } else if (holder->updated_contacts) {
+            callback->oncontactsupdated(*holder->updated_contacts);
+        } else if (holder->removed_ids) {
+            callback->oncontactsremoved(*holder->removed_ids);
+        } else {
+            LOGW("Callback called with no data");
+        }
+    }
+    catch (const Common::BasePlatformException &err) {
+        LOGE("AddressBook change listener failed: %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+
+    return false;
+}
+
+void AddressBook::contactsDBChangeCallback(const char* view_uri,
+        void* user_data)
+{
+    LOGD("Entered");
+    int error_code = 0;
+
+    ListenersMap listeners;
+
+    {
+        std::lock_guard<std::mutex> lock(s_mutex);
+        listeners = s_listeners;
+    }
+
+    auto it = listeners.begin();
+    auto ite = listeners.end();
+
+    for(; it != ite; ++it) {
+        std::pair<long, AddressBookChangeCallbackPtr> cb = *it;
+
+        int address_book_id = cb.second->getAddressBookId();
+        int latest_version = 0;
+
+        contacts_list_h contacts_list = NULL;
+
+        error_code = contacts_db_get_changes_by_version(
+                _contacts_contact_updated_info._uri, address_book_id,
+                s_latest_version, &contacts_list, &latest_version);
+
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("%s", ContactUtil::getContactErrorString(error_code, "contacts_db_get_changes_by_version()").c_str());
+        }
+        else {
+            contacts_list_h_ptr contacts_list_ptr(&contacts_list, contactsListDeleter);
+            int count = 0;
+
+            error_code = contacts_list_get_count(*contacts_list_ptr, &count);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_list_get_count()").c_str());
+                return;
+            }
+
+            if (!count) {
+                LOGW("No updated contacts");
+                return;
+            }
+
+            contacts_list_first(*contacts_list_ptr);
+
+            std::shared_ptr<ContactPtrVector> added(new ContactPtrVector());
+            std::shared_ptr<ContactPtrVector> updated(new ContactPtrVector());
+            std::shared_ptr<StringVector> removed(new StringVector());
+
+            for(int i = 0; i < count; i++) {
+                contacts_record_h contact_updated_record = NULL;
+
+                error_code = contacts_list_get_current_record_p(*contacts_list_ptr,
+                        &contact_updated_record);
+                if (CONTACTS_ERROR_NONE != error_code) {
+                    LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_list_get_current_record_p()").c_str());
+                    return;
+                }
+
+                int changed_id = 0;
+                int changed_ab_id = 0;
+                int changed_type = 0;
+
+                try {
+                    ContactUtil::getIntFromRecord(contact_updated_record,
+                            _contacts_contact_updated_info.contact_id,
+                            &changed_id);
+
+                    ContactUtil::getIntFromRecord(contact_updated_record,
+                            _contacts_contact_updated_info.address_book_id,
+                            &changed_ab_id);
+
+                    ContactUtil::getIntFromRecord(contact_updated_record,
+                            _contacts_contact_updated_info.type,
+                            &changed_type);
+                }
+                catch (const BasePlatformException &err) {
+                    LOGE("failt to get int from record");
+                    return;
+                }
+
+                if (CONTACTS_CHANGE_INSERTED == changed_type
+                        || CONTACTS_CHANGE_UPDATED == changed_type) {
+                    contacts_record_h contacts_record = NULL;
+
+                    error_code = contacts_db_get_record(_contacts_contact._uri,
+                            changed_id, &contacts_record);
+
+                    if (CONTACTS_ERROR_NONE != error_code) {
+                        LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_db_get_record()").c_str());
+                        return;
+                    }
+
+                    contacts_record_h_ptr contact_record_ptr(&contacts_record,
+                            contactsDeleter);
+
+                    ContactPtr contact(new Contact());
+                    contact->importFromContactsRecord(*contact_record_ptr);
+
+                    if (CONTACTS_CHANGE_INSERTED == changed_type) {
+                        added->push_back(contact);
+                    }
+                    else {
+                        updated->push_back(contact);
+                    }
+                }
+                else if (CONTACTS_CHANGE_DELETED == changed_type) {
+                    removed->push_back(std::to_string(changed_id));
+                }
+            }
+
+            if (!added->empty()) {
+                AddressBookChangeListenerHolder* holder =
+                        new(std::nothrow) AddressBookChangeListenerHolder();
+
+                holder->added_contacts = added;
+                holder->callback = cb.second;
+
+                if (!g_idle_add(changeCallbackFunc, holder)) {
+                    LOGE("g_idle_add_fails");
+                    delete holder;
+                    holder = NULL;
+                }
+            }
+            if (!updated->empty()) {
+                AddressBookChangeListenerHolder* holder =
+                        new(std::nothrow) AddressBookChangeListenerHolder();
+
+                holder->updated_contacts = updated;
+                holder->callback = cb.second;
+
+                if (!g_idle_add(changeCallbackFunc, holder)) {
+                    LOGE("g_idle_add_fails");
+                    delete holder;
+                    holder = NULL;
+                }
+            }
+            if (!removed->empty()) {
+                AddressBookChangeListenerHolder* holder =
+                        new(std::nothrow) AddressBookChangeListenerHolder();
+
+                holder->removed_ids = removed;
+                holder->callback = cb.second;
+
+                if (!g_idle_add(changeCallbackFunc, holder)) {
+                    LOGE("g_idle_add_fails");
+                    delete holder;
+                    holder = NULL;
+                }
+            }
+
+        }
+    }
+
+    error_code = contacts_db_get_current_version(&s_latest_version);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_db_get_current_version()").c_str());
+    }
+}
+
+long AddressBook::addChangeListener(AddressBookChangeCallbackPtr callback)
+{
+    LOGD("Entered");
+    std::lock_guard<std::mutex> lock(s_mutex);
+
+    callback->setAddressBookId(m_address_book_id);
+
+    long listener_id = s_listener_counter++;
+
+    int error_code = 0;
+
+    if (s_listeners.empty()) {
+        error_code = contacts_db_add_changed_cb(_contacts_contact._uri,
+                contactsDBChangeCallback, NULL);
+
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_add_changed_cb()");
+        }
+    }
+
+    error_code = contacts_db_get_current_version(&s_latest_version);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_db_get_current_version()");
+    }
+
+    s_listeners.insert(ListenerPair(listener_id, callback));
+
+    return listener_id;
+}
+
+void AddressBook::removeChangeListener(JSContextRef context, long watch_id)
+{
+    std::lock_guard<std::mutex> lock(s_mutex);
+    ListenersMap::iterator it = s_listeners.find(watch_id);
+
+    if (it != s_listeners.end()) {
+        JSContextRef global_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        if(it->second->getContext() != global_ctx) {
+            LOGE("No listener with such id in current context");
+            throw NotFoundException("No listener with such id in current context");
+        }
+
+        it->second->setActive(false);
+        s_listeners.erase(it);
+
+        if (s_listeners.empty()) {
+            int error_code = contacts_db_remove_changed_cb(
+                    _contacts_contact._uri, contactsDBChangeCallback, NULL);
+
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_db_remove_changed_cb()");
+            }
+        }
+    } else {
+        LOGE("No listener with such id: %d", watch_id);
+        throw NotFoundException("No listener with such id");
+    }
+}
+
+void AddressBook::unregisterChangeListeners()
+{
+    std::lock_guard<std::mutex> lock(s_mutex);
+
+    LongVector watch_ids;
+    auto it = s_listeners.begin();
+    auto ite = s_listeners.end();
+
+    for(; it != ite; ++it) {
+        if (it->second->getAddressBookId() == m_address_book_id) {
+            watch_ids.push_back(it->first);
+        }
+    }
+
+    auto it_l = watch_ids.begin();
+    auto ite_l = watch_ids.end();
+
+    for(; it_l != ite_l; ++it_l) {
+        s_listeners.erase(*it_l);
+    }
+
+    if (s_listeners.empty()) {
+        s_latest_version = 0;
+
+        int error_code = contacts_db_remove_changed_cb(
+                _contacts_contact._uri, contactsDBChangeCallback, NULL);
+
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("%s", ContactUtil::getContactErrorString(error_code, "contacts_db_remove_changed_cb()").c_str());
+        }
+    }
+}
+
+void AddressBook::addGroup(ContactGroupPtr group_ptr)
+{
+    contacts_record_h contacts_record = NULL;
+    if(!group_ptr){
+        LOGE("No contact group object");
+        throw Common::InvalidValuesException("No contact group object");
+    }
+    if(group_ptr->getIdIsSet() || group_ptr->getAddressBookIdIsSet()){
+        LOGE("Group object is previously added");
+        throw Common::InvalidValuesException("Group object is previously added");
+    }
+    int err = CONTACTS_ERROR_NONE;
+    err = contacts_record_create(_contacts_group._uri, &contacts_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&contacts_record, contactsDeleter);
+
+    int address_book_id = (m_is_unified) ? 0 : m_address_book_id;
+    ContactUtil::setIntInRecord(contacts_record,
+            _contacts_group.address_book_id, address_book_id);
+
+    group_ptr->exportToContactsRecord(contacts_record);
+    int group_id = 0;
+    err = contacts_db_insert_record(contacts_record, &group_id);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_db_insert_record()");
+    }
+    group_ptr->setId(std::to_string(group_id));
+    group_ptr->setAddressBookId(std::to_string(m_address_book_id));
+}
+
+ContactGroupPtr AddressBook::getGroup(long id)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h contacts_record = NULL;
+    if (id < 0) {
+        LOGE("Negative group id value: $d", id);
+        throw Common::InvalidValuesException("Incorrect group id");
+    }
+
+    err = contacts_db_get_record(_contacts_group._uri, id, &contacts_record);
+    if( CONTACTS_ERROR_NONE != err || NULL == contacts_record ){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException<NotFoundException>(err, "contacts_db_get_record()");
+    }
+    contacts_record_h_ptr record(&contacts_record, contactsDeleter);
+
+    if(!m_is_unified)
+    {
+        int address_book_id = 0;
+        ContactUtil::getIntFromRecord(contacts_record,
+                _contacts_group.address_book_id, &address_book_id);
+        if(address_book_id != m_address_book_id){
+            throw Common::NotFoundException("No group in this address book.");
+        }
+    }
+
+    ContactGroupPtr group = ContactGroupPtr(new ContactGroup());
+    group->importFromContactsRecord(contacts_record);
+
+    return group;
+}
+
+void AddressBook::updateGroup(ContactGroupPtr group_ptr)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h contacts_record = NULL;
+
+    if(!group_ptr){
+        LOGE("No contact group object");
+        throw Common::InvalidValuesException("No contact group object");
+    }
+
+    if(!group_ptr->getIdIsSet() || !group_ptr->getAddressBookIdIsSet()){
+        LOGE("Group object is previously added");
+        throw Common::InvalidValuesException("Group object is previously added");
+    }
+
+    if(m_is_unified && (group_ptr->getAddressBookId() != std::to_string(getAddressBookId()))){
+        LOGE("Wrong address book");
+        throw Common::InvalidValuesException("Wrong address book");
+    }
+
+    if (group_ptr->getReadOnly()) {
+        LOGW("Group is readonly - cancel update");
+        return;
+    }
+
+    int group_id = std::stoi(group_ptr->getId());
+    if(group_id < 0) {
+        LOGE("Incorrect group id: %d", group_id);
+        throw Common::InvalidValuesException("Incorrect group id");
+    }
+
+    err = contacts_db_get_record(_contacts_group._uri, group_id, &contacts_record);
+    if (CONTACTS_ERROR_NONE != err || contacts_record == NULL) {
+        LOGE("ret: %d", err);
+        if(CONTACTS_ERROR_NO_DATA == err){
+            ContactUtil::throwContactException<NotFoundException>(err, "contacts_db_get_record()");
+        }
+        ContactUtil::throwContactException(err, "contacts_db_get_record()");
+    }
+
+    contacts_record_h_ptr record(&contacts_record, contactsDeleter);
+    group_ptr->exportToContactsRecord(contacts_record);
+
+    err = contacts_db_update_record(contacts_record);
+    if(CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        if (CONTACTS_ERROR_INVALID_PARAMETER == err) {
+            ContactUtil::throwContactException<Common::NotFoundException>(err, "contacts_db_update_record()");
+        }
+        ContactUtil::throwContactException(err, "contacts_db_update_record()");
+    }
+}
+
+void AddressBook::removeGroup(long id)
+{
+    int err = CONTACTS_ERROR_NONE;
+    if(id < 0){
+        LOGE("Incorrect group id: %d", id);
+        throw Common::InvalidValuesException("Incorrect group id");
+    }
+
+    if (!m_is_unified) {
+        contacts_record_h contacts_record = NULL;
+        err = contacts_db_get_record(_contacts_group._uri, id, &contacts_record);
+        if (CONTACTS_ERROR_NONE != err || contacts_record == NULL) {
+            LOGE("ret: %d", err);
+            if(CONTACTS_ERROR_NO_DATA == err){
+                ContactUtil::throwContactException<Common::NotFoundException>(err, "contacts_db_get_record()");
+            }
+            ContactUtil::throwContactException(err, "contacts_db_get_record()");
+        }
+
+        int address_book_id = 0;
+        ContactUtil::getIntFromRecord(contacts_record,
+                _contacts_group.address_book_id, &address_book_id);
+
+        if (address_book_id != m_address_book_id) {
+            throw Common::UnknownException("Contact is not a member of this address book");
+        }
+    }
+
+    err = contacts_db_delete_record(_contacts_group._uri, id);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        if (CONTACTS_ERROR_INVALID_PARAMETER == err) {
+            ContactUtil::throwContactException<NotFoundException>(err, "contacts_db_delete_record()");
+        }
+        ContactUtil::throwContactException(err, "contacts_db_delete_record()");
+    }
+}
+
+ContactGroupPtrVector AddressBook::getGroups()
+{
+    int err = CONTACTS_ERROR_NONE;
+    ContactGroupPtrVector group_vector;
+    contacts_list_h groups_list = NULL;
+
+    if (m_is_unified) {
+        err = contacts_db_get_all_records(_contacts_group._uri, 0, 0, &groups_list);
+        if(CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_db_get_all_records()");
+        }
+    }
+    else {
+        contacts_query_h query = NULL;
+        contacts_filter_h filter = NULL;
+
+        err = contacts_query_create(_contacts_group._uri, &query);
+        if(CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_query_create()");
+        }
+        contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+        err = contacts_filter_create(_contacts_group._uri, &filter);
+        if(CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_filter_create()");
+        }
+        contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+        err = contacts_filter_add_int(*filter_ptr,
+                _contacts_group.address_book_id, CONTACTS_MATCH_EQUAL, m_address_book_id);
+        if (CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_filter_add_int()");
+        }
+
+        err = contacts_query_set_filter(*query_ptr, *filter_ptr);
+        if (CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_query_set_filter()");
+        }
+
+        err = contacts_db_get_records_with_query(*query_ptr, 0, 0, &groups_list);
+        if (CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_db_get_records_with_query()");
+        }
+    }
+    contacts_list_h_ptr groups_list_ptr(&groups_list, contactsListDeleter);
+
+    int record_count = 0;
+    err = contacts_list_get_count(*groups_list_ptr, &record_count);
+    if (CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_list_get_count()");
+    }
+
+    contacts_list_first(*groups_list_ptr);
+    for(int i=0; i < record_count; i++)
+    {
+        try{
+            contacts_record_h contacts_record;
+            err = contacts_list_get_current_record_p(*groups_list_ptr, &contacts_record);
+            if( CONTACTS_ERROR_NONE != err || NULL == contacts_record )
+            {
+                LOGW("%s", ContactUtil::getContactErrorString(err, "contacts_list_get_current_record_p()").c_str());
+                continue;
+            }
+
+            int id = 0;
+            int address_book_id = 0;
+            char *name = NULL;
+            char *ringtone_uri = NULL;
+            char *photo_uri = NULL;
+            bool is_read_only = false;
+
+            ContactUtil::getIntFromRecord(contacts_record,
+                    _contacts_group.id, &id);
+            ContactUtil::getIntFromRecord(contacts_record,
+                    _contacts_group.address_book_id, &address_book_id);
+            ContactUtil::getStrFromRecord(contacts_record,
+                    _contacts_group.name, &name);
+            ContactUtil::getStrFromRecord(contacts_record,
+                    _contacts_group.image_path, &photo_uri);
+            ContactUtil::getStrFromRecord(contacts_record,
+                    _contacts_group.ringtone_path, &ringtone_uri);
+            ContactUtil::getBoolFromRecord(contacts_record,
+                    _contacts_group.is_read_only, &is_read_only);
+
+
+            ContactGroupPtr group = ContactGroupPtr(new ContactGroup());
+            group->setId(std::to_string(id));
+            group->setAddressBookId(std::to_string(address_book_id));
+
+            if (name) {
+                group->setName(std::string(name));
+            }
+            else {
+                group->setName("");
+            }
+
+            if(photo_uri){
+                group->setPhotoURI(ContactUtil::convertPathToUri(std::string(photo_uri)));
+            }
+            if(ringtone_uri){
+                group->setRingtoneURI(ContactUtil::convertPathToUri(std::string(ringtone_uri)));
+            }
+            group->setReadOnly(is_read_only);
+
+            group_vector.push_back(group);
+
+            err = contacts_list_next(*groups_list_ptr);
+            if(CONTACTS_ERROR_NONE != err)
+            {
+                LOGW("%s", ContactUtil::getContactErrorString(err, "contacts_list_next()").c_str());
+                break;
+            }
+        }
+        catch(const Common::BasePlatformException& e){
+            LOGW("%s",e.getMessage().c_str());
+        }
+    }
+
+    return group_vector;
+}
+
+gboolean AddressBook::findCallback(void *data)
+{
+    auto callback = static_cast<AddressBookFindCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            auto contacts = callback->getContacts();
+            if (!contacts) {
+                LOGE("contacts is null");
+                return false;
+            }
+            JSObjectRef arr = ptrVectorToJSObjectArray<JSContact, ContactPtr>(
+                    *contacts, context);
+            callback->callSuccessCallback(arr);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Find callback fails");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* AddressBook::findThread(void *data)
+{
+    auto callback = static_cast<AddressBookFindCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        ContactSearchEngine search_engine;
+        if(callback->isAddressBookIdSet()) {
+            search_engine.setAddressBookId(callback->getAddressBookId());
+        }
+        Tizen::SortModePtr sort_mode = callback->getSortMode();
+        Tizen::AbstractFilterPtr filter = callback->getFilter();
+
+        search_engine.applyFilter(filter);
+        search_engine.setSortMode(sort_mode);
+
+        callback->setContacts(search_engine.find());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+    }
+    catch (...) {
+        LOGE("UnknownError");
+        callback->setError("UnknownError", "Find method fails");
+    }
+
+    guint id = g_idle_add(findCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    return NULL;
+}
+
+void AddressBook::find(AddressBookFindCallbackData *callback)
+{
+    if(!this->getIsUnified()) {
+        callback->setAddressBookId(m_address_book_id);
+    }
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, findThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+bool AddressBook::isValidAccount(unsigned long account_id)
+{
+    bool result = false;
+    account_h handle;
+    int ret = account_create(&handle);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("Failed to create account handle : %x", ret);
+        throw UnknownException("Failed to create account handle.");
+    }
+    ret = account_query_account_by_account_id(static_cast<int>(account_id), &handle);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGW("Failed account_query_account_by_account_id(): %d", ret);
+        result = false;
+    } else {
+        result = true;
+    }
+
+    ret = account_destroy(handle);
+    if (ACCOUNT_ERROR_NONE != ret) {
+        LOGE("Failed to destroy account handle : %x", ret);
+        throw UnknownException("Failed to destroy account handle.");
+    }
+
+    return result;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/AddressBook.h b/src/Contact/AddressBook.h
new file mode 100644 (file)
index 0000000..ad30a94
--- /dev/null
@@ -0,0 +1,123 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_ADDRESS_BOOK_H__
+#define __TIZEN_CONTACT_ADDRESS_BOOK_H__
+
+#include "Contact.h"
+#include "ContactUtil.h"
+#include "ContactGroup.h"
+#include <memory>
+#include <vector>
+#include <mutex>
+#include <map>
+#include <glib.h>
+#include "AddressBookCallbackData.h"
+#include "AddressBookChangeCallback.h"
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class AddressBook;
+typedef std::shared_ptr<AddressBook> AddressBookPtr;
+typedef std::vector<AddressBookPtr> AddressBookPtrVector;
+typedef std::vector<std::string> StringVector;
+typedef std::map<long, AddressBookChangeCallbackPtr> ListenersMap;
+typedef std::pair<long, AddressBookChangeCallbackPtr> ListenerPair;
+
+class AddressBook : public Common::SecurityAccessor {
+public:
+    static const long DEFAULT_ADDRESS_BOOK_ID;
+    static const long UNIFIED_ADDRESS_BOOK_ID;
+    static const char* UNIFIED_ADDRESS_BOOK_NAME;
+
+    AddressBook();
+    virtual ~AddressBook();
+
+    long getAddressBookId();
+    void setAddressBookId(long address_book_id);
+    bool isAddressBookIdSet();
+    std::string getName();
+    void setName(const std::string &name);
+    bool getReadOnly();
+    void setReadOnly(bool read_only);
+    bool getIsUnified() const;
+    void setIsUnified(bool is_unified);
+    unsigned long getAccountId();
+    void setAccountId(unsigned long account_id);
+
+    ContactPtr get(long contact_id);
+    void add(ContactPtr contact);
+    void addBatch(ContactArrayCallbackData *callback);
+    void update(ContactPtr contact);
+    void remove(long contact_id);
+    void removeBatch(IdArrayCallbackData *callback);
+    void updateBatch(ContactArrayCallbackData *callback);
+
+    long addChangeListener(AddressBookChangeCallbackPtr callback);
+    void removeChangeListener(JSContextRef context, long watch_id);
+    void unregisterChangeListeners();
+
+    void addGroup(ContactGroupPtr group_ptr);
+    ContactGroupPtr getGroup(long id);
+    void updateGroup(ContactGroupPtr group_ptr);
+    void removeGroup(long id);
+    ContactGroupPtrVector getGroups();
+
+    void find(AddressBookFindCallbackData *callback);
+    static bool isValidAccount(unsigned long account_id);
+
+private:
+    long m_address_book_id;
+    bool m_is_address_book_id_set;
+    std::string m_name;
+    bool m_read_only;
+    bool m_is_unified;
+    unsigned long m_account_id;
+
+    static long s_listener_counter;
+    static ListenersMap s_listeners;
+    static std::mutex s_mutex;
+    static int s_latest_version;
+
+    static void contactsDBChangeCallback(const char* view_uri, void* user_data);
+    static gboolean addBatchCallback(void *data);
+    static void* addBatchThread(void *data);
+    static gboolean batchOperationCallback(void *data);
+    static void* removeBatchThread(void *data);
+    static void* updateBatchThread(void *data);
+    static gboolean findCallback(void *data);
+    static void* findThread(void *data);
+    static gboolean changeCallbackFunc(void *data);
+
+    void updateAdditionalInformation(ContactPtr contact,
+            contacts_record_h_ptr& contacts_record_ptr);
+
+    struct AddressBookChangeListenerHolder {
+        AddressBookChangeCallbackPtr callback;
+        std::shared_ptr<ContactPtrVector> added_contacts;
+        std::shared_ptr<ContactPtrVector> updated_contacts;
+        std::shared_ptr<StringVector> removed_ids;
+    };
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif
diff --git a/src/Contact/AddressBookCallbackData.cpp b/src/Contact/AddressBookCallbackData.cpp
new file mode 100644 (file)
index 0000000..25794b3
--- /dev/null
@@ -0,0 +1,146 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        AddressBookCallbackData.cpp
+ */
+
+#include "AddressBookCallbackData.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+OperationCallbackData::OperationCallbackData(JSContextRef globalCtx):
+        Common::CallbackUserData(globalCtx),
+        m_is_error(false),
+        m_address_book_id(0)
+{
+}
+
+OperationCallbackData::~OperationCallbackData()
+{
+}
+
+void OperationCallbackData::setError(const std::string &err_name,
+        const std::string &err_message)
+{
+    m_err_name = err_name;
+    m_err_message = err_message;
+    m_is_error = true;
+}
+
+bool OperationCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+std::string OperationCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string OperationCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void OperationCallbackData::setAddressBookId(long id)
+{
+    m_is_address_book_id_set = true;
+    m_address_book_id = id;
+}
+
+long OperationCallbackData::getAddressBookId() const
+{
+    return m_address_book_id;
+}
+
+bool OperationCallbackData::isAddressBookIdSet() const
+{
+    return m_is_address_book_id_set;
+}
+
+ContactArrayCallbackData::ContactArrayCallbackData(JSContextRef globalCtx):
+        OperationCallbackData(globalCtx)
+{
+}
+
+ContactArrayCallbackData::~ContactArrayCallbackData()
+{
+}
+
+void ContactArrayCallbackData::setContacts(
+        std::shared_ptr<ContactPtrVector> contacts)
+{
+    m_contacts = contacts;
+}
+
+std::shared_ptr<ContactPtrVector> ContactArrayCallbackData::getContacts() const
+{
+    return m_contacts;
+}
+
+IdArrayCallbackData::IdArrayCallbackData(JSContextRef globalCtx):
+        OperationCallbackData(globalCtx)
+{
+}
+
+IdArrayCallbackData::~IdArrayCallbackData()
+{
+}
+
+void IdArrayCallbackData::setIds(std::shared_ptr<LongVector> ids)
+{
+    m_ids = ids;
+}
+
+std::shared_ptr<LongVector> IdArrayCallbackData::getIds() const
+{
+    return m_ids;
+}
+
+AddressBookFindCallbackData::AddressBookFindCallbackData(JSContextRef globalCtx):
+        ContactArrayCallbackData(globalCtx)
+{
+}
+
+AddressBookFindCallbackData::~AddressBookFindCallbackData()
+{
+}
+
+void AddressBookFindCallbackData::setFilter(Tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+Tizen::AbstractFilterPtr AddressBookFindCallbackData::getFilter() const
+{
+    return m_filter;
+}
+
+void AddressBookFindCallbackData::setSortMode(Tizen::SortModePtr sort_mode)
+{
+    m_sort_mode = sort_mode;
+}
+
+Tizen::SortModePtr AddressBookFindCallbackData::getSortMode() const
+{
+    return m_sort_mode;
+}
+
+}
+}
diff --git a/src/Contact/AddressBookCallbackData.h b/src/Contact/AddressBookCallbackData.h
new file mode 100644 (file)
index 0000000..fffce52
--- /dev/null
@@ -0,0 +1,108 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        AddressBookCallbackData.h
+ */
+
+#ifndef __ADDRESS_BOOK_CALLBACK_DATA_H__
+#define __ADDRESS_BOOK_CALLBACK_DATA_H__
+
+#include <CallbackUserData.h>
+#include <string>
+#include <memory>
+#include "Contact.h"
+#include <AbstractFilter.h>
+#include <SortMode.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class OperationCallbackData : public Common::CallbackUserData
+{
+public:
+    OperationCallbackData(JSContextRef globalCtx);
+    virtual ~OperationCallbackData();
+
+    void setError(const std::string &err_name,
+            const std::string &err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    void setAddressBookId(long id);
+    long getAddressBookId() const;
+    bool isAddressBookIdSet() const;
+
+private:
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+    long m_address_book_id;
+    bool m_is_address_book_id_set;
+};
+
+class ContactArrayCallbackData : public OperationCallbackData
+{
+public:
+    ContactArrayCallbackData(JSContextRef globalCtx);
+    virtual ~ContactArrayCallbackData();
+
+    void setContacts(std::shared_ptr<ContactPtrVector> contacts);
+    std::shared_ptr<ContactPtrVector> getContacts() const;
+
+private:
+    std::shared_ptr<ContactPtrVector> m_contacts;
+
+};
+
+class IdArrayCallbackData : public OperationCallbackData
+{
+public:
+    IdArrayCallbackData(JSContextRef globalCtx);
+    virtual ~IdArrayCallbackData();
+
+    void setIds(std::shared_ptr<LongVector> ids);
+    std::shared_ptr<LongVector> getIds() const;
+
+private:
+    std::shared_ptr<LongVector> m_ids;
+
+};
+
+class AddressBookFindCallbackData : public ContactArrayCallbackData
+{
+public:
+    AddressBookFindCallbackData(JSContextRef globalCtx);
+    virtual ~AddressBookFindCallbackData();
+
+    void setFilter(Tizen::AbstractFilterPtr filter);
+    Tizen::AbstractFilterPtr getFilter() const;
+
+    void setSortMode(Tizen::SortModePtr sort_mode);
+    Tizen::SortModePtr getSortMode() const;
+
+private:
+    Tizen::AbstractFilterPtr m_filter;
+    Tizen::SortModePtr m_sort_mode;
+
+};
+
+}
+}
+
+#endif //__ADDRESS_BOOK_CALLBACK_DATA_H__
diff --git a/src/Contact/AddressBookChangeCallback.cpp b/src/Contact/AddressBookChangeCallback.cpp
new file mode 100644 (file)
index 0000000..1f37857
--- /dev/null
@@ -0,0 +1,115 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        AddressBookChangeCallback.cpp
+ */
+
+#include "AddressBookChangeCallback.h"
+#include "JSContact.h"
+#include "ContactUtil.h"
+#include <JSUtil.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace Common;
+
+const char* AddressBookChangeCallback::CALLBACK_CONTACTS_ADDED = "oncontactsadded";
+const char* AddressBookChangeCallback::CALLBACK_CONTACTS_UPDATED = "oncontactsupdated";
+const char* AddressBookChangeCallback::CALLBACK_CONTACTS_REMOVED = "oncontactsremoved";
+
+AddressBookChangeCallback::AddressBookChangeCallback(JSContextRef globalCtx,
+        JSObjectRef object): m_is_active(true)
+{
+    m_callback = MultiCallbackPtr(new (std::nothrow) MultiCallbackUserData(globalCtx, object));
+
+    if (!m_callback) {
+        LOGW("Callback is null");
+        throw UnknownException("Cannot allocate memory");
+    }
+}
+
+AddressBookChangeCallback::~AddressBookChangeCallback()
+{
+}
+
+void AddressBookChangeCallback::oncontactsadded(const ContactPtrVector &contacts)
+{
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+    JSObjectRef jsContacts = ptrVectorToJSObjectArray<JSContact, ContactPtr>(
+                contacts, context);
+
+    m_callback->invokeCallback(CALLBACK_CONTACTS_ADDED, jsContacts);
+}
+
+void AddressBookChangeCallback::oncontactsupdated(const ContactPtrVector &contacts)
+{
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+    JSObjectRef jsContacts = ptrVectorToJSObjectArray<JSContact, ContactPtr>(
+            contacts, context);
+
+    m_callback->invokeCallback(CALLBACK_CONTACTS_UPDATED, jsContacts);
+}
+
+void AddressBookChangeCallback::oncontactsremoved(const StringVector &contact_ids)
+{
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+    m_callback->invokeCallback(CALLBACK_CONTACTS_REMOVED, JSUtil::toJSValueRef(context, contact_ids));
+}
+
+void AddressBookChangeCallback::setAddressBookId(long address_book_id)
+{
+    m_address_book_id = address_book_id;
+}
+
+long AddressBookChangeCallback::getAddressBookId() const
+{
+    return m_address_book_id;
+}
+
+void AddressBookChangeCallback::setActive(bool act)
+{
+    m_is_active = act;
+}
+
+bool AddressBookChangeCallback::isActive() const
+{
+    return m_is_active;
+}
+
+JSContextRef AddressBookChangeCallback::getContext() const
+{
+    return m_callback->getContext();
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/AddressBookChangeCallback.h b/src/Contact/AddressBookChangeCallback.h
new file mode 100644 (file)
index 0000000..cd8fc6f
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        AddressBookChangeCallback.h
+ */
+
+#ifndef __TIZEN_ADDRESS_BOOK_CHANGE_CALLBACK_H__
+#define __TIZEN_ADDRESS_BOOK_CHANGE_CALLBACK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <vector>
+#include <memory>
+#include <string>
+#include "Contact.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class AddressBookChangeCallback;
+typedef std::shared_ptr<AddressBookChangeCallback> AddressBookChangeCallbackPtr;
+typedef std::shared_ptr<Common::MultiCallbackUserData> MultiCallbackPtr;
+
+typedef std::vector<std::string> StringVector;
+
+class AddressBookChangeCallback {
+public:
+    AddressBookChangeCallback(JSContextRef globalCtx, JSObjectRef object);
+    virtual ~AddressBookChangeCallback();
+
+    void oncontactsadded(const ContactPtrVector &contacts);
+    void oncontactsupdated(const ContactPtrVector &contacts);
+    void oncontactsremoved(const StringVector &contact_ids);
+
+    void setAddressBookId(long address_book_id);
+    long getAddressBookId() const;
+
+    static const char* CALLBACK_CONTACTS_ADDED;
+    static const char* CALLBACK_CONTACTS_UPDATED;
+    static const char* CALLBACK_CONTACTS_REMOVED;
+
+    bool isActive() const;
+    void setActive(bool act);
+
+    JSContextRef getContext() const;
+
+private:
+    MultiCallbackPtr m_callback;
+    long m_address_book_id;
+    bool m_is_active;
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif //__TIZEN_ADDRESS_BOOK_CHANGE_CALLBACK_H__
diff --git a/src/Contact/CMakeLists.txt b/src/Contact/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..2bc3e9c
--- /dev/null
@@ -0,0 +1,100 @@
+SET(TARGET_NAME ${contact_target})
+SET(DESTINATION_NAME ${contact_dest})
+SET(TARGET_IMPL_NAME ${contact_impl})
+SET(TARGET_CONFIG_NAME ${contact_config})
+
+PKG_CHECK_MODULES(platform_pkgs_contact REQUIRED accounts-svc contacts-service2 libpcrecpp)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+SET(INCLUDE_DIRS
+    ${tizen_include}
+    ${platform_pkgs_contact_INCLUDE_DIRS}
+)
+
+INCLUDE_DIRECTORIES(${INCLUDE_COMMON} ${INCLUDE_DIRS})
+MESSAGE(STATUS "${TARGET_NAME} module includes: INCLUDE_COMMON ${INCLUDE_DIRS}")
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSAddressBook.cpp
+    JSContact.cpp
+    JSContactAddress.cpp
+    JSContactAnniversary.cpp
+    JSContactEmailAddress.cpp
+    JSContactGroup.cpp
+    JSContactInstantMessenger.cpp
+    JSContactManager.cpp
+    JSContactName.cpp
+    JSContactOrganization.cpp
+    JSContactPhoneNumber.cpp
+    JSContactRef.cpp
+    JSContactRelationship.cpp
+    JSContactWebSite.cpp
+    JSPerson.cpp
+    AddressBook.cpp
+    AddressBookCallbackData.cpp
+    AddressBookChangeCallback.cpp
+    Contact.cpp
+    ContactAddress.cpp
+    ContactAnniversary.cpp
+    ContactEmailAddress.cpp
+    ContactGroup.cpp
+    ContactInstantMessenger.cpp
+    ContactManager.cpp
+    ContactManagerCallbackData.cpp
+    ContactName.cpp
+    ContactOrganization.cpp
+    ContactPhoneNumber.cpp
+    ContactRef.cpp
+    ContactRelationship.cpp
+    ContactSearchEngine.cpp
+    ContactUtil.cpp
+    ContactWebSite.cpp
+    Person.cpp
+    PersonChangeCallback.cpp
+    PersonSearchEngine.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+SET(LINK_LIBS
+    ${tizen_impl}
+    ${platform_pkgs_contact_LIBRARIES}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME} ${LIBS_COMMON} ${LINK_LIBS})
+MESSAGE(STATUS "${TARGET_NAME} module links: LIBS_COMMON ${LINK_LIBS}")
+
+SET(SRCS_CONFIG
+    plugin_config.cpp
+)
+
+ADD_LIBRARY(${TARGET_CONFIG_NAME} SHARED ${SRCS_CONFIG})
+
+TARGET_LINK_LIBRARIES(${TARGET_CONFIG_NAME}
+    ${LIBS_COMMON}
+)
+
+SET(SRCS
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+    ${TARGET_CONFIG_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_CONFIG_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/contact
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Contact/Contact.cpp b/src/Contact/Contact.cpp
new file mode 100644 (file)
index 0000000..e5e03b9
--- /dev/null
@@ -0,0 +1,1006 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "Contact.h"
+#include "ContactUtil.h"
+#include <algorithm>
+#include <ctime>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+Contact::Contact()
+{
+    m_id = 0;
+    m_person_id = 0;
+    m_address_book_id = 0;
+    m_last_updated = 0;
+    m_is_favorite = false;
+    m_photo_uri = "";
+    m_birthday = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    m_ringtone_uri = "";
+    for (int i = 0; i < CONTACT_NUMBER_OF_ATTRIBUTES; i++) {
+        m_is_set[i] = false;
+    }
+    m_context = NULL;
+}
+
+Contact::~Contact()
+{
+
+}
+
+long Contact::getId()
+{
+    return m_id;
+}
+
+void Contact::setId(long id)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_ID] = true;
+    m_id = id;
+}
+
+long Contact::getPersonId()
+{
+    return m_person_id;
+}
+
+void Contact::setPersonId(long person_id)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_PERSON_ID] = true;
+    m_person_id = person_id;
+}
+
+long Contact::getAddressBookId()
+{
+    return m_address_book_id;
+}
+
+void Contact::setAddressBookId(long address_book_id)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_ADDRESS_BOOK_ID] = true;
+    m_address_book_id = address_book_id;
+}
+
+std::time_t Contact::getLastUpdated()
+{
+    return m_last_updated;
+}
+
+void Contact::setLastUpdated(std::time_t last_updated)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_LAST_UPDATED] = true;
+    m_last_updated = last_updated;
+}
+
+bool Contact::getIsFavorite()
+{
+    return m_is_favorite;
+}
+
+void Contact::setIsFavorite(bool is_favorite)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_IS_FAVORITE] = true;
+    m_is_favorite = is_favorite;
+}
+
+ContactNamePtr Contact::getName()
+{
+    return m_name;
+}
+
+void Contact::setName(ContactNamePtr name)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_NAME] = true;
+    m_name = name;
+}
+
+ContactAddressPtrVector Contact::getAddresses()
+{
+    return m_addresses;
+}
+
+void Contact::setAddresses(const ContactAddressPtrVector &addresses)
+{
+    m_addresses = addresses;
+}
+
+std::string Contact::getPhotoUri()
+{
+    return ContactUtil::convertPathToUri(m_photo_uri);
+}
+
+void Contact::setPhotoUri(const std::string &photo_uri)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_PHOTO_URI] = true;
+    m_photo_uri = ContactUtil::convertUriToPath(photo_uri);
+}
+
+ContactPhoneNumberPtrVector Contact::getPhoneNumbers()
+{
+    return m_phone_numbers;
+}
+
+void Contact::setPhoneNumbers(const ContactPhoneNumberPtrVector &phone_numbers)
+{
+    m_phone_numbers = phone_numbers;
+}
+
+ContactEmailAddressPtrVector Contact::getEmails()
+{
+    return m_emails;
+}
+
+void Contact::setEmails(const ContactEmailAddressPtrVector &emails)
+{
+    m_emails = emails;
+}
+
+ContactInstantMessengerPtrVector Contact::getMessengers() const
+{
+    return m_messengers;
+}
+
+void Contact::setMessengers(const ContactInstantMessengerPtrVector &messengers)
+{
+    m_messengers = messengers;
+}
+
+ContactRelationshipPtrVector Contact::getRelationships() const
+{
+    return m_relationships;
+}
+
+void Contact::setRelationships(const ContactRelationshipPtrVector &relationships)
+{
+    m_relationships = relationships;
+}
+
+tm Contact::getBirthday()
+{
+    return m_birthday;
+}
+
+void Contact::setBirthday(std::tm birthday)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_BIRTHDAY] = true;
+    m_birthday = birthday;
+}
+
+ContactAnniversaryPtrVector Contact::getAnniversaries()
+{
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(
+            m_context)) {
+        return m_anniversaries;
+    }
+    else {
+        return static_cast<ContactAnniversaryPtrVector>(*m_js_anniversaries);
+    }
+}
+
+void Contact::setAnniversaries(const ContactAnniversaryPtrVector &anniversaries)
+{
+    if (Common::GlobalContextManager::getInstance()->isAliveGlobalContext(
+            m_context)) {
+        *m_js_anniversaries = anniversaries;
+    }
+    else {
+        m_anniversaries = anniversaries;
+    }
+}
+
+ContactOrganizationPtrVector Contact::getOrganizations()
+{
+    return m_organizations;
+}
+
+void Contact::setOrganizations(const ContactOrganizationPtrVector &organizations)
+{
+    m_organizations = organizations;
+}
+
+StringVector Contact::getNotes()
+{
+    return m_notes;
+}
+
+void Contact::setNotes(const StringVector &notes)
+{
+    m_notes = notes;
+}
+
+ContactWebSitePtrVector Contact::getUrls()
+{
+    return m_urls;
+}
+
+void Contact::setUrls(const ContactWebSitePtrVector &urls)
+{
+    m_urls = urls;
+}
+
+std::string Contact::getRingtoneUri() const
+{
+    return m_ringtone_uri;
+}
+
+void Contact::setRingtoneUri(const std::string &ringtone_uri)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_RINGTONE_URI] = true;
+    m_ringtone_uri = ringtone_uri;
+}
+
+std::string Contact::getMessageAlertUri() const
+{
+    return m_message_alert_uri;
+}
+
+void Contact::setMessageAlertUri(const std::string &message_alert_uri)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_MESSAGE_ALERT_URI] = true;
+    m_message_alert_uri = message_alert_uri;
+}
+
+std::string Contact::getVibrationUri() const
+{
+    return m_vibration_uri;
+}
+
+void Contact::setVibrationUri(const std::string &vibration_uri)
+{
+    m_is_set[ContactAttribute::CONTACT_ATTRIBUTE_VIBRATION_URI] = true;
+    m_vibration_uri = vibration_uri;
+}
+
+LongVector Contact::getGroupIds()
+{
+    return m_group_ids;
+}
+
+void Contact::setGroupIds(const LongVector &group_ids)
+{
+    m_group_ids = group_ids;
+}
+
+bool Contact::isSet(ContactAttribute attribute) const
+{
+    return m_is_set[attribute];
+}
+
+void Contact::setIsSet(ContactAttribute attribute, bool is_set)
+{
+    m_is_set[attribute] = is_set;
+}
+
+std::string Contact::convertToString(ContactTextFormat ctf)
+{
+    int err = CONTACTS_ERROR_NONE;
+    std::string result;
+    char* vcard = NULL;
+
+    if (CONTACT_TEXT_FORMAT_VCARD_30 != ctf) {
+        LOGE("Unsupported format");
+        throw Common::NotSupportedException("Unsupported format");
+    }
+
+    contacts_record_h contacts_record = NULL;
+    try{
+        err = contacts_db_get_record(_contacts_contact._uri, m_id, &contacts_record);
+        if (CONTACTS_ERROR_NONE != err) {
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_db_get_record()");
+        }
+
+        importFromContactsRecord(contacts_record);
+    }catch(...){
+        LOGE("Fail to get contact");
+        throw Common::UnknownException("Fail to get contact");
+    }
+
+    err = contacts_vcard_make_from_contact(contacts_record, &vcard);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_vcard_make_from_contact()");
+    }
+    if (vcard) {
+        result = std::string(vcard);
+        free(vcard);
+    }
+    return result;
+}
+
+void Contact::importFromVCard(const std::string& str_vcard)
+{
+    int err = CONTACTS_ERROR_NONE;
+    const char* vcard_char_ptr = str_vcard.c_str();
+    contacts_list_h contacts_list = NULL;
+
+    err = contacts_vcard_parse_to_contacts(vcard_char_ptr, &contacts_list);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        if (CONTACTS_ERROR_INVALID_PARAMETER == err) {
+            ContactUtil::throwContactException<Common::InvalidValuesException>(err, "contacts_vcard_parse_to_contacts()");
+        }
+        ContactUtil::throwContactException(err, "contacts_vcard_parse_to_contacts()");
+    }
+
+    int record_count = 0;
+    err = contacts_list_get_count(contacts_list, &record_count);
+    if (CONTACTS_ERROR_NONE != err || 0 == record_count) {
+        int ret = contacts_list_destroy(contacts_list, true);
+        if (CONTACTS_ERROR_NONE != ret) {
+            LOGW("Failed contacts_list_destroy(): %s, %d",
+                    ContactUtil::getContactErrorMessage(ret).c_str(), ret);
+        }
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_list_get_count()");
+    }
+
+    contacts_record_h contacts_record;
+    err = contacts_list_first(contacts_list);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGW("Failed contacts_list_first(): %s, %d",
+                ContactUtil::getContactErrorMessage(err).c_str(), err);
+    }
+    err = contacts_list_get_current_record_p(contacts_list, &contacts_record);
+    if( CONTACTS_ERROR_NONE != err || NULL == contacts_record )
+    {
+        int ret = contacts_list_destroy(contacts_list, true);
+        if (CONTACTS_ERROR_NONE != ret) {
+            LOGW("Failed contacts_list_destroy(): %s, %d",
+                    ContactUtil::getContactErrorMessage(ret).c_str(), ret);
+        }
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_list_get_current_record_p()");
+    }
+
+    importFromContactsRecord(contacts_record);
+    //method importFromContactsRecord sets ID's m_is_set values to "true", but before
+    //adding contact to addressBook IDs are not set. This values have to be set to "false"
+    setIsSet(CONTACT_ATTRIBUTE_ID, false);
+    setIsSet(CONTACT_ATTRIBUTE_PERSON_ID, false);
+    setIsSet(CONTACT_ATTRIBUTE_ADDRESS_BOOK_ID, false);
+}
+
+ContactPtr Contact::clone()
+{
+    ContactPtr result = ContactPtr(new(std::nothrow) Contact());
+
+    for (int i = 0; i < CONTACT_NUMBER_OF_ATTRIBUTES; i++) {
+        result->m_is_set[i] = m_is_set[i];
+    }
+
+    if (m_is_set[CONTACT_ATTRIBUTE_IS_FAVORITE]) {
+        result->m_is_favorite = m_is_favorite;
+    }
+
+    if (m_is_set[CONTACT_ATTRIBUTE_NAME]) {
+        result->m_name = ContactNamePtr(new(std::nothrow) ContactName());
+        *(result->m_name) = *(m_name);
+    }
+
+    if (this->m_addresses.size() > 0) {
+        result->m_addresses = cloneVector<ContactAddressPtr, ContactAddress>(m_addresses);
+    }
+
+    if (m_is_set[CONTACT_ATTRIBUTE_PHOTO_URI]) {
+        result->m_photo_uri = m_photo_uri;
+    }
+
+    if (this->m_phone_numbers.size() > 0) {
+        result->m_phone_numbers =
+                cloneVector<ContactPhoneNumberPtr, ContactPhoneNumber>(m_phone_numbers);
+    }
+
+    if (this->m_emails.size() > 0) {
+        result->m_emails =
+                cloneVector<ContactEmailAddressPtr, ContactEmailAddress>(m_emails);
+    }
+
+    if (m_is_set[CONTACT_ATTRIBUTE_BIRTHDAY]) {
+        result->m_birthday = m_birthday;
+    }
+
+    auto anniversaries = getAnniversaries();
+    if (anniversaries.size() > 0) {
+        result->m_anniversaries =
+                cloneVector<ContactAnniversaryPtr, ContactAnniversary>(anniversaries);
+    }
+
+    if (this->m_organizations.size() > 0) {
+        result->m_organizations =
+                cloneVector<ContactOrganizationPtr, ContactOrganization>(m_organizations);
+    }
+
+    if (this->m_notes.size() > 0) {
+        result->m_notes = m_notes;
+    }
+
+    if (this->m_urls.size() > 0) {
+        result->m_urls =
+                cloneVector<ContactWebSitePtr, ContactWebSite>(m_urls);
+    }
+
+    if (m_is_set[CONTACT_ATTRIBUTE_RINGTONE_URI]) {
+        result->m_ringtone_uri = m_ringtone_uri;
+    }
+
+    if (this->m_group_ids.size() > 0) {
+        result->m_group_ids = m_group_ids;
+    }
+
+    return result;
+}
+
+void Contact::importFromContactsRecord(contacts_record_h contacts_record)
+{
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGW("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    m_context = NULL;
+    int id = 0;
+    ContactUtil::getIntFromRecord(contacts_record, _contacts_contact.id, &id);
+    setId(id);
+    ContactUtil::getIntFromRecord(contacts_record,
+            _contacts_contact.address_book_id, &id);
+    setAddressBookId(id);
+    ContactUtil::getIntFromRecord(contacts_record, _contacts_contact.person_id,
+            &id);
+    setPersonId(id);
+
+    bool is_favorite = false;
+    ContactUtil::getBoolFromRecord(contacts_record,
+            _contacts_contact.is_favorite, &is_favorite);
+    setIsFavorite(is_favorite);
+
+    int last_update = 0;
+    ContactUtil::getIntFromRecord(contacts_record,
+            _contacts_contact.changed_time,
+            &last_update);
+    setLastUpdated(static_cast<std::time_t>(last_update));
+
+    //### ContactName: ###
+    m_name = ContactNamePtr(new(std::nothrow) ContactName);
+    if (!m_name) {
+        LOGW("Name is null");
+        throw Common::UnknownException("Name is null");
+    }
+
+    try {
+        m_name->importFromContactsRecord(contacts_record);
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_NAME, true);
+    }
+    catch (...) {
+        LOGW("No contact name");
+    }
+
+    //### ContactEmailAddress: ###
+    try {
+        unsigned int number_of_email =
+                ContactUtil::getNumberOfChildRecord(contacts_record, _contacts_contact.email);
+        for (unsigned int index = 0; index < number_of_email; index++) {
+            ContactEmailAddressPtr element = ContactEmailAddressPtr(new ContactEmailAddress());
+            element->importFromContactsRecord(contacts_record, index);
+            m_emails.push_back(element);
+        }
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_EMAILS, true);
+    }
+    catch (...) {
+        LOGW("No contact emails");
+    }
+
+    //### ContactPhoneNumber: ###
+    try {
+        unsigned int number_of_email =
+                ContactUtil::getNumberOfChildRecord(contacts_record, _contacts_contact.number);
+        for (unsigned int index = 0; index < number_of_email; index++) {
+            ContactPhoneNumberPtr element = ContactPhoneNumberPtr(new ContactPhoneNumber());
+            element->importFromContactsRecord(contacts_record, index);
+            m_phone_numbers.push_back(element);
+        }
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_PHONE_NUMBERS, true);
+    }
+    catch (...) {
+        LOGW("No contact phone number");
+    }
+
+    //### ContactOrganizations: ###
+    try {
+        unsigned int number_of_organizations =
+                ContactUtil::getNumberOfChildRecord(contacts_record, _contacts_contact.company);
+        for (unsigned int index = 0; index < number_of_organizations; index++) {
+            ContactOrganizationPtr element = ContactOrganizationPtr(new ContactOrganization());
+            element->importFromContactsRecord(contacts_record, index);
+            m_organizations.push_back(element);
+        }
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_ORGANIZATIONS, true);
+    }
+    catch (...) {
+        LOGW("No contact organizations");
+    }
+
+    //### ContactWebSite: ###
+    try {
+        unsigned int number_of_organizations =
+                ContactUtil::getNumberOfChildRecord(contacts_record, _contacts_contact.url);
+        for (unsigned int index = 0; index < number_of_organizations; index++) {
+            ContactWebSitePtr element = ContactWebSitePtr(new ContactWebSite());
+            element->importFromContactsRecord(contacts_record, index);
+            m_urls.push_back(element);
+        }
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_URLS, true);
+    }
+    catch (...) {
+        LOGW("No contact website");
+    }
+
+    //### ContactAnniversary: ###
+    try {
+        unsigned int number_of_organizations =
+                ContactUtil::getNumberOfChildRecord(contacts_record, _contacts_contact.event);
+        for (unsigned int index = 0; index < number_of_organizations; index++) {
+            ContactAnniversaryPtr element = ContactAnniversaryPtr(new ContactAnniversary());
+            if (element->importFromContactsRecord(contacts_record, index)) {
+                m_anniversaries.push_back(element);
+            }
+            else {
+                importBirthdayFromContactsRecord(contacts_record, index);
+                setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_BIRTHDAY, true);
+            }
+        }
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_ANNIVERSARIES, true);
+    }
+    catch (...) {
+        LOGW("No contact anniversaries");
+    }
+
+    //### ContactAddress: ###
+    try {
+        unsigned int number_of_organizations =
+                ContactUtil::getNumberOfChildRecord(contacts_record, _contacts_contact.address);
+        for (unsigned int index = 0; index < number_of_organizations; index++) {
+            ContactAddressPtr element = ContactAddressPtr(new ContactAddress());
+            element->importFromContactsRecord(contacts_record, index);
+            m_addresses.push_back(element);
+        }
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_ADDRESSES, true);
+    }
+    catch (...) {
+        LOGW("No contact addresses");
+    }
+
+    //### ContactInstantMessenger: ###
+    try {
+        unsigned int num_of_messengers =
+                ContactUtil::getNumberOfChildRecord(contacts_record, _contacts_contact.messenger);
+        for (unsigned int index = 0; index < num_of_messengers; index++) {
+            ContactInstantMessengerPtr element = ContactInstantMessengerPtr(new ContactInstantMessenger());
+            element->importFromContactsRecord(contacts_record, index);
+            m_messengers.push_back(element);
+        }
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_MESSENGERS, true);
+    }
+    catch (...) {
+        LOGW("No contact messengers");
+    }
+
+    //### ContactRelationship: ###
+    try {
+        unsigned int num_of_relationships =
+                ContactUtil::getNumberOfChildRecord(contacts_record, _contacts_contact.relationship);
+        for (unsigned int index = 0; index < num_of_relationships; index++) {
+            ContactRelationshipPtr element = ContactRelationshipPtr(new ContactRelationship());
+            element->importFromContactsRecord(contacts_record, index);
+            m_relationships.push_back(element);
+        }
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_RELATIONSHIPS, true);
+    }
+    catch (...) {
+        LOGW("No contact relationships");
+    }
+
+    //### m_notes: ###
+    try {
+        unsigned int number_of_notes =
+                ContactUtil::getNumberOfChildRecord(contacts_record, _contacts_contact.note);
+        for (unsigned int index = 0; index < number_of_notes; index++) {
+            importNotesFromContactsRecord(contacts_record, index);
+        }
+        setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_NOTES, true);
+    }
+    catch (...) {
+        LOGW("No contact notes");
+    }
+
+    //### m_photo_uri ###
+    //### m_ringtone_uri ###
+    try{
+        importUriPathFromContactRecord(contacts_record);
+    }
+    catch(...) {
+        LOGW("Problem during setting rightone or photo");
+    }
+}
+
+void Contact::exportToContactsRecord(contacts_record_h contacts_record)
+{
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGW("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    //### ContactName: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.name);
+    if(isSet(ContactAttribute::CONTACT_ATTRIBUTE_NAME)){
+        m_name->exportToContactsRecord(contacts_record);
+    }
+
+    //### ContactEmailAddress: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.email);
+    for (ContactEmailAddressPtrVector::iterator it = m_emails.begin();
+            it != m_emails.end(); ++it) {
+        (*it)->exportToContactsRecord(contacts_record);
+    }
+
+    //### ContactPhoneNumber: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.number);
+    for (ContactPhoneNumberPtrVector::iterator it = m_phone_numbers.begin();
+            it != m_phone_numbers.end(); ++it) {
+        (*it)->exportToContactsRecord(contacts_record);
+    }
+
+    //### ContactOrganizations: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.company);
+    for (ContactOrganizationPtrVector::iterator it = m_organizations.begin();
+            it != m_organizations.end(); ++it) {
+        (*it)->exportToContactsRecord(contacts_record);
+    }
+
+    //### ContactWebSite: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.url);
+    for (ContactWebSitePtrVector::iterator it = m_urls.begin();
+            it != m_urls.end(); ++it) {
+        (*it)->exportToContactsRecord(contacts_record);
+    }
+
+    //### ContactAnniversary: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.event);
+    exportBirthdayToContactsRecord(contacts_record);
+    ContactAnniversaryPtrVector anniversaries = getAnniversaries();
+    for (ContactAnniversaryPtrVector::iterator it = anniversaries.begin();
+            it != anniversaries.end(); ++it) {
+        (*it)->exportToContactsRecord(contacts_record);
+    }
+
+    //### ContactAddress: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.address);
+    for (ContactAddressPtrVector::iterator it = m_addresses.begin();
+            it != m_addresses.end(); ++it) {
+        (*it)->exportToContactsRecord(contacts_record);
+    }
+
+    //### ContactInstantMessenger: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.messenger);
+    for (ContactInstantMessengerPtrVector::iterator it = m_messengers.begin();
+            it != m_messengers.end(); ++it) {
+        (*it)->exportToContactsRecord(contacts_record);
+    }
+
+    //### ContactRelationship: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.relationship);
+    for (ContactRelationshipPtrVector::iterator it = m_relationships.begin();
+            it != m_relationships.end(); ++it) {
+        (*it)->exportToContactsRecord(contacts_record);
+    }
+
+    //### m_notes: ###
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.note);
+    for (StringVector::iterator it = m_notes.begin();
+            it != m_notes.end(); ++it) {
+        if((*it).empty()){
+            continue;
+        }
+        exportNotesToContactsRecord(contacts_record,*it);
+    }
+
+    //### m_photo_uri ###
+    //### m_ringtone_uri ###
+    exportUriPathsToContactsRecord(contacts_record);
+
+}
+
+void Contact::importBirthdayFromContactsRecord(contacts_record_h contacts_record,
+        unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_get_child_record_at_p(contacts_record,
+            _contacts_contact.event, index, &child_record);
+    if ( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err ) {
+        LOGW("Failed contacts_record_get_child_record_at_p(): %s, %d",
+                ContactUtil::getContactErrorMessage(err).c_str(), err);
+        return;
+    }
+
+    int value = 0;
+    ContactUtil::getIntFromRecord(child_record,
+            _contacts_event.type, &value);
+
+    if (CONTACTS_EVENT_TYPE_BIRTH == value) {
+        int date = 0;
+        ContactUtil::getIntFromRecord(child_record,
+                _contacts_event.date, &date);
+        try {
+            setBirthday(ContactUtil::toTimeT(date));
+        }
+        catch (const Common::BasePlatformException& e) {
+            LOGE("%d", e.getMessage().c_str());
+        }
+    }
+}
+
+void Contact::exportBirthdayToContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h birthday_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    if (m_birthday.tm_year == 0 && m_birthday.tm_mon == 0
+            && m_birthday.tm_mday == 0) {
+            return;
+    }
+
+    int date = ContactUtil::toDateDbInt(m_birthday);
+
+    err = contacts_record_create(_contacts_event._uri, &birthday_record);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&birthday_record, contactsDeleter);
+
+    ContactUtil::setIntInRecord(birthday_record,
+            _contacts_event.type, CONTACTS_EVENT_TYPE_BIRTH);
+
+    ContactUtil::setIntInRecord(birthday_record,
+            _contacts_event.date, date);
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.event, birthday_record);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    record.release();
+}
+
+void Contact::importNotesFromContactsRecord(contacts_record_h contacts_record, unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h notes_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+    err = contacts_record_get_child_record_at_p(contacts_record,
+            _contacts_contact.note, index, &notes_record);
+    if ( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err ) {
+        LOGW("Failed contacts_record_get_child_record_at_p(): %s, %d",
+                ContactUtil::getContactErrorMessage(err).c_str(), err);
+        return;
+    }
+
+    char* note = NULL;
+    ContactUtil::getStrFromRecord(notes_record,
+            _contacts_note.note, &note);
+
+    if (note) {
+        m_notes.push_back(std::string(note));
+    }
+}
+
+void Contact::exportNotesToContactsRecord(contacts_record_h contacts_record, const std::string& value)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h notes_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_create(_contacts_note._uri, &notes_record);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&notes_record, contactsDeleter);
+
+    ContactUtil::setStrInRecord(notes_record,
+            _contacts_note.note, value.c_str());
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.note, notes_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+
+    record.release();
+}
+
+void Contact::importUriPathFromContactRecord(contacts_record_h contacts_record)
+{
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    char* value = NULL;
+    ContactUtil::getStrFromRecord(contacts_record,
+            _contacts_contact.image_thumbnail_path, &value);
+    if(value){
+        setPhotoUri(std::string(value));
+    }
+
+    value = NULL;
+    ContactUtil::getStrFromRecord(contacts_record,
+            _contacts_contact.ringtone_path, &value);
+    if (value) {
+        setRingtoneUri(ContactUtil::convertPathToUri(std::string(value)));
+    }
+    value = NULL;
+    ContactUtil::getStrFromRecord(contacts_record,
+            _contacts_contact.message_alert, &value);
+    if (value) {
+        setMessageAlertUri(ContactUtil::convertPathToUri(std::string(value)));
+    }
+    value = NULL;
+    ContactUtil::getStrFromRecord(contacts_record,
+            _contacts_contact.vibration, &value);
+    if (value) {
+        setVibrationUri(ContactUtil::convertPathToUri(std::string(value)));
+    }
+}
+
+void Contact::exportUriPathsToContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+
+    char *old_value_str = NULL;
+    std::string abstract_value_str;
+    std::string real_path;
+
+    // Contact.photoURI
+    if(!isSet(CONTACT_ATTRIBUTE_PHOTO_URI) || getPhotoUri().empty())
+    {
+        err = contacts_record_create(_contacts_image._uri, &child_record);
+        if (CONTACTS_ERROR_NONE != err) {
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_record_create()");
+        }
+        contacts_record_h_ptr record = contacts_record_h_ptr(&child_record, contactsDeleter);
+        err = contacts_record_add_child_record(contacts_record,
+                _contacts_contact.image, child_record);
+        if (CONTACTS_ERROR_NONE != err) {
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+        }
+        record.release();
+    }
+    else
+    {
+        bool is_first = false;
+        err = contacts_record_get_child_record_at_p(contacts_record, _contacts_contact.image, 0, &child_record);
+        if(CONTACTS_ERROR_NONE != err || NULL == child_record )
+        {
+            LOGW("Failed contacts_record_get_child_record_at_p(): %s, %d",
+                    ContactUtil::getContactErrorMessage(err).c_str(), err);
+            int ret = contacts_record_create(_contacts_image._uri, &child_record);
+            if (CONTACTS_ERROR_NONE != ret) {
+                LOGE("ret: %d", ret);
+                ContactUtil::throwContactException(ret, "contacts_record_create()");
+            }
+            is_first = true;
+        }
+        contacts_record_h_ptr record = contacts_record_h_ptr(&child_record, contactsDeleter);
+        ContactUtil::getStrFromRecord(child_record,
+                _contacts_image.path, &old_value_str);
+
+        real_path = ContactUtil::convertUriToPath(getPhotoUri());
+
+        ContactUtil::setStrInRecord(child_record,
+                _contacts_image.path, real_path.c_str());
+
+        if(is_first){
+            err = contacts_record_add_child_record(contacts_record, _contacts_contact.image, child_record);
+            if (CONTACTS_ERROR_NONE != err) {
+                LOGE("ret: %d", err);
+                ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+            }
+        }
+        record.release();
+    }
+    // Contact.ringtoneURI
+    real_path = ContactUtil::convertUriToPath(getRingtoneUri());
+    ContactUtil::setStrInRecord(contacts_record,
+            _contacts_contact.ringtone_path, real_path.c_str());
+    // Contact.messageAlertURI
+    real_path = ContactUtil::convertUriToPath(getMessageAlertUri());
+    ContactUtil::setStrInRecord(contacts_record,
+            _contacts_contact.message_alert, real_path.c_str());
+    // Contact.vibrationURI
+    real_path = ContactUtil::convertUriToPath(getVibrationUri());
+    ContactUtil::setStrInRecord(contacts_record,
+            _contacts_contact.vibration, real_path.c_str());
+}
+
+JSContextRef Contact::getContext() const
+{
+    return m_context;
+}
+
+JSContactAnniversaryArray Contact::getJSAnniversaries(JSContextRef global_ctx)
+{
+    if (!m_context && !global_ctx) {
+        LOGE("no context set");
+        throw Common::UnknownException("no context set");
+    }
+    else if (!m_context && global_ctx) {
+        m_context = global_ctx;
+    }
+
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(
+            m_context)) {
+        LOGE("Context is not alive");
+        throw Common::UnknownException("context is not alive");
+    }
+    else if (!m_js_anniversaries) {
+        m_js_anniversaries = std::shared_ptr<JSContactAnniversaryArray>(
+                new JSContactAnniversaryArray(m_context));
+        for_each(m_anniversaries.begin(), m_anniversaries.end(),
+                [this] (
+                        ContactAnniversaryPtr anniversary) {
+            m_js_anniversaries->append(anniversary);
+        });
+        m_anniversaries.clear();
+    }
+
+    return *m_js_anniversaries;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/Contact.h b/src/Contact/Contact.h
new file mode 100644 (file)
index 0000000..7f6a330
--- /dev/null
@@ -0,0 +1,196 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_CONTACT_H__
+#define __TIZEN_CONTACT_CONTACT_H__
+
+#include <ctime>
+#include <string>
+#include <vector>
+#include <memory>
+#include <PlatformException.h>
+#include <Logger.h>
+#include <contacts.h>
+#include <contacts_internal.h>
+#include "ContactName.h"
+#include "ContactAddress.h"
+#include "ContactPhoneNumber.h"
+#include "ContactEmailAddress.h"
+#include "ContactAnniversary.h"
+#include "ContactOrganization.h"
+#include "ContactWebSite.h"
+#include "JSContactAnniversary.h"
+#include "ContactInstantMessenger.h"
+#include "ContactRelationship.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class Contact;
+typedef std::shared_ptr<Contact> ContactPtr;
+typedef std::vector<ContactPtr> ContactPtrVector;
+typedef std::vector<long> LongVector;
+typedef std::vector<std::string> StringVector;
+
+enum ContactTextFormat{
+    CONTACT_TEXT_FORMAT_VCARD_30
+};
+
+enum ContactAttribute{
+    CONTACT_ATTRIBUTE_ID,
+    CONTACT_ATTRIBUTE_PERSON_ID,
+    CONTACT_ATTRIBUTE_ADDRESS_BOOK_ID,
+    CONTACT_ATTRIBUTE_LAST_UPDATED,
+    CONTACT_ATTRIBUTE_IS_FAVORITE,
+    CONTACT_ATTRIBUTE_NAME,
+    CONTACT_ATTRIBUTE_ADDRESSES,
+    CONTACT_ATTRIBUTE_PHOTO_URI,
+    CONTACT_ATTRIBUTE_PHONE_NUMBERS,
+    CONTACT_ATTRIBUTE_EMAILS,
+    CONTACT_ATTRIBUTE_MESSENGERS,
+    CONTACT_ATTRIBUTE_RELATIONSHIPS,
+    CONTACT_ATTRIBUTE_BIRTHDAY,
+    CONTACT_ATTRIBUTE_ANNIVERSARIES,
+    CONTACT_ATTRIBUTE_ORGANIZATIONS,
+    CONTACT_ATTRIBUTE_NOTES,
+    CONTACT_ATTRIBUTE_URLS,
+    CONTACT_ATTRIBUTE_RINGTONE_URI,
+    CONTACT_ATTRIBUTE_MESSAGE_ALERT_URI,
+    CONTACT_ATTRIBUTE_VIBRATION_URI,
+    CONTACT_ATTRIBUTE_GROUP_IDS,
+    CONTACT_NUMBER_OF_ATTRIBUTES
+};
+
+class Contact {
+public:
+    Contact();
+    virtual ~Contact();
+
+    long getId();
+    void setId(long id);
+    long getPersonId();
+    void setPersonId(long person_id);
+    long getAddressBookId();
+    void setAddressBookId(long address_book_id);
+    std::time_t getLastUpdated();
+    void setLastUpdated(std::time_t last_updated);
+    bool getIsFavorite();
+    void setIsFavorite(bool is_favorite);
+    ContactNamePtr getName();
+    void setName(ContactNamePtr name);
+    ContactAddressPtrVector getAddresses();
+    void setAddresses(const ContactAddressPtrVector &addresses);
+    std::string getPhotoUri();
+    void setPhotoUri(const std::string &photo_uri);
+    ContactPhoneNumberPtrVector getPhoneNumbers();
+    void setPhoneNumbers(const ContactPhoneNumberPtrVector &phone_numbers);
+    ContactEmailAddressPtrVector getEmails();
+    void setEmails(const ContactEmailAddressPtrVector &emails);
+    ContactInstantMessengerPtrVector getMessengers() const;
+    void setMessengers(const ContactInstantMessengerPtrVector &messengers);
+    ContactRelationshipPtrVector getRelationships() const;
+    void setRelationships(const ContactRelationshipPtrVector &relationships);
+    std::tm getBirthday();
+    void setBirthday(std::tm birthday);
+    ContactAnniversaryPtrVector getAnniversaries();
+    void setAnniversaries(const ContactAnniversaryPtrVector &anniversaries);
+    ContactOrganizationPtrVector getOrganizations();
+    void setOrganizations(const ContactOrganizationPtrVector &organizations);
+    StringVector getNotes();
+    void setNotes(const StringVector &notes);
+    ContactWebSitePtrVector getUrls();
+    void setUrls(const ContactWebSitePtrVector &urls);
+    std::string getRingtoneUri() const;
+    void setRingtoneUri(const std::string &ringtone_uri);
+    std::string getMessageAlertUri() const;
+    void setMessageAlertUri(const std::string &ringtone_uri);
+    std::string getVibrationUri() const;
+    void setVibrationUri(const std::string &ringtone_uri);
+    LongVector getGroupIds();
+    void setGroupIds(const LongVector &group_ids);
+
+    bool isSet(ContactAttribute attribute) const;
+    void setIsSet(ContactAttribute attribute, bool is_set);
+
+    std::string convertToString(ContactTextFormat ctf = CONTACT_TEXT_FORMAT_VCARD_30);
+    void importFromVCard(const std::string& str_vcard);
+    ContactPtr clone();
+
+    void importFromContactsRecord(contacts_record_h contacts_record);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+    void importBirthdayFromContactsRecord(contacts_record_h contacts_record,
+            unsigned int index);
+    void exportBirthdayToContactsRecord(contacts_record_h contacts_record);
+    void importNotesFromContactsRecord(contacts_record_h contacts_record,
+            unsigned int index);
+    void exportNotesToContactsRecord(contacts_record_h contacts_record,
+            const std::string& value);
+    void exportUriPathsToContactsRecord(contacts_record_h contacts_record);
+    void importUriPathFromContactRecord(contacts_record_h contacts_record);
+
+    JSContextRef getContext() const;
+    JSContactAnniversaryArray getJSAnniversaries(JSContextRef global_ctx);
+
+private:
+    long m_id;
+    long m_person_id;
+    long m_address_book_id;
+    std::time_t m_last_updated;
+    bool m_is_favorite;
+    ContactNamePtr m_name;
+    ContactAddressPtrVector m_addresses;
+    std::string m_photo_uri;
+    ContactPhoneNumberPtrVector m_phone_numbers;
+    ContactEmailAddressPtrVector m_emails;
+    ContactInstantMessengerPtrVector m_messengers;
+    ContactRelationshipPtrVector m_relationships;
+    std::tm m_birthday;
+    ContactAnniversaryPtrVector m_anniversaries;
+    ContactOrganizationPtrVector m_organizations;
+    StringVector m_notes;
+    ContactWebSitePtrVector m_urls;
+    std::string m_ringtone_uri;
+    std::string m_message_alert_uri;
+    std::string m_vibration_uri;
+    LongVector m_group_ids;
+    bool m_is_set[ContactAttribute::CONTACT_NUMBER_OF_ATTRIBUTES];
+
+    template<class T, class U>
+    std::vector<T> cloneVector(const std::vector<T> &vec)
+    {
+        std::vector<T> cloned_vec;
+        size_t vec_size = vec.size();
+        for (size_t i = 0; i < vec_size; i++) {
+            T cloned = T(new(std::nothrow) U());
+            if (!cloned) {
+                LOGW("Clone is null");
+                throw Common::UnknownException("Clone is null");
+            }
+            *(cloned) = *(vec[i]);
+            cloned_vec.push_back(cloned);
+        }
+        return cloned_vec;
+    }
+
+    JSContextRef m_context;
+    std::shared_ptr<JSContactAnniversaryArray> m_js_anniversaries;
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif
diff --git a/src/Contact/ContactAddress.cpp b/src/Contact/ContactAddress.cpp
new file mode 100644 (file)
index 0000000..b311369
--- /dev/null
@@ -0,0 +1,286 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "ContactAddress.h"
+#include "ContactUtil.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+namespace{
+struct getter{
+    ContactAddressAttribute atr;
+    unsigned int prop_id;
+};
+
+getter get[CONTACT_ADDRESS_NUMBER_OF_ATTRIBUTES] = {
+     { CONTACT_ADDRESS_ATTRIBUTE_COUNTRY, _contacts_address.country, },
+     { CONTACT_ADDRESS_ATTRIBUTE_REGION, _contacts_address.region},
+     { CONTACT_ADDRESS_ATTRIBUTE_CITY, _contacts_address.locality},
+     { CONTACT_ADDRESS_ATTRIBUTE_STREETADDR, _contacts_address.street},
+     { CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO, _contacts_address.extended},
+     { CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE, _contacts_address.postal_code},
+     { CONTACT_ADDRESS_ATTRIBUTE_LABEL, _contacts_address.label}
+};
+}
+
+ContactAddress::ContactAddress()
+{
+    m_country = "";
+    m_region = "";
+    m_city = "";
+    m_street_address = "";
+    m_additional_information = "";
+    m_postal_code = "";
+    m_is_default = false;
+    m_types.push_back(ContactUtil::CONTACT_TYPE_HOME);
+    for(int i = 0; i < CONTACT_ADDRESS_NUMBER_OF_ATTRIBUTES; i++){
+        m_is_set[i] = false;
+    }
+    m_label = "";
+}
+
+ContactAddress::~ContactAddress()
+{
+
+}
+
+std::string ContactAddress::getAttribute(ContactAddressAttribute attribute) const
+{
+    switch (attribute) {
+        case CONTACT_ADDRESS_ATTRIBUTE_COUNTRY:
+            return m_country;
+        case CONTACT_ADDRESS_ATTRIBUTE_REGION:
+            return m_region;
+        case CONTACT_ADDRESS_ATTRIBUTE_CITY:
+            return m_city;
+        case CONTACT_ADDRESS_ATTRIBUTE_STREETADDR:
+            return m_street_address;
+        case CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO:
+            return m_additional_information;
+        case CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE:
+            return m_postal_code;
+        case CONTACT_ADDRESS_ATTRIBUTE_LABEL:
+            return m_label;
+        default:
+            throw DeviceAPI::Common::NotSupportedException("Not an attribute");
+    }
+}
+
+void ContactAddress::setAttribute(ContactAddressAttribute attribute,
+        const std::string &value)
+{
+    switch (attribute) {
+        case CONTACT_ADDRESS_ATTRIBUTE_COUNTRY:
+            m_is_set[CONTACT_ADDRESS_ATTRIBUTE_COUNTRY] = true;
+            m_country = value;
+            break;
+        case CONTACT_ADDRESS_ATTRIBUTE_REGION:
+            m_is_set[CONTACT_ADDRESS_ATTRIBUTE_REGION] = true;
+            m_region = value;
+            break;
+        case CONTACT_ADDRESS_ATTRIBUTE_CITY:
+            m_is_set[CONTACT_ADDRESS_ATTRIBUTE_CITY] = true;
+            m_city = value;
+            break;
+        case CONTACT_ADDRESS_ATTRIBUTE_STREETADDR:
+            m_is_set[CONTACT_ADDRESS_ATTRIBUTE_STREETADDR] = true;
+            m_street_address = value;
+            break;
+        case CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO:
+            m_is_set[CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO] = true;
+            m_additional_information = value;
+            break;
+        case CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE:
+            m_is_set[CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE] = true;
+            m_postal_code = value;
+            break;
+        case CONTACT_ADDRESS_ATTRIBUTE_LABEL:
+            m_is_set[CONTACT_ADDRESS_ATTRIBUTE_LABEL] = true;
+            m_label = value;
+            break;
+        default:
+            throw DeviceAPI::Common::NotSupportedException("Not an attribute");
+    }
+}
+
+bool ContactAddress::isSet(ContactAddressAttribute attribute) const
+{
+    return m_is_set[attribute];
+}
+
+void ContactAddress::setIsSet(ContactAddressAttribute attribute, bool is_set)
+{
+    m_is_set[attribute] = is_set;
+}
+
+bool ContactAddress::getIsDefault() const
+{
+    return m_is_default;
+}
+
+void ContactAddress::setIsDefault(bool is_default)
+{
+    m_is_default = is_default;
+}
+
+std::vector<std::string> ContactAddress::getTypes()
+{
+    return m_types;
+}
+
+JSValueRef ContactAddress::getJSTypes(JSContextRef global_ctx)
+{
+    return m_types.getJSArray(global_ctx);
+}
+
+void ContactAddress::setTypes(const std::vector<std::string> &types)
+{
+    m_types = types;
+}
+
+void ContactAddress::importFromContactsRecord(contacts_record_h contacts_record,
+        unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_get_child_record_at_p(contacts_record,
+            _contacts_contact.address, index, &child_record);
+    if ( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err ) {
+        LOGW("Failed contacts_record_get_child_record_at_p(): %s, %d",
+                ContactUtil::getContactErrorMessage(err).c_str(), err);
+        return;
+    }
+
+    char* value = NULL;
+    int enum_val = 0;
+    for (; enum_val<(static_cast<int>(CONTACT_ADDRESS_NUMBER_OF_ATTRIBUTES));
+         enum_val++) {
+        try{
+        ContactUtil::getStrFromRecord(child_record,get[enum_val].prop_id,
+                        &value);
+        if(value){
+            setAttribute(get[enum_val].atr, std::string(value));
+            setIsSet(get[enum_val].atr, true);
+        }
+        } catch(const Common::BasePlatformException& e){
+            LOGE("ContactAddress attribute %d is not set", enum_val);
+        }
+    }
+
+    bool bool_value = false;
+    ContactUtil::getBoolFromRecord(child_record,
+            _contacts_address.is_default, &bool_value);
+    setIsDefault(bool_value);
+
+    int int_value = 0;
+    ContactUtil::getIntFromRecord(child_record,
+            _contacts_address.type, &int_value);
+
+    m_types.clear();
+    if (int_value & CONTACTS_ADDRESS_TYPE_HOME) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_HOME);
+    }
+    if (int_value & CONTACTS_ADDRESS_TYPE_WORK) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_WORK);
+    }
+    if (int_value & CONTACTS_ADDRESS_TYPE_CUSTOM) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_CUSTOM);
+    }
+    if (0 == int_value) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_OTHER);
+    }
+
+    if (0 == m_types.size()) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_HOME);
+    }
+}
+
+void ContactAddress::exportToContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h address_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_create(_contacts_address._uri, &address_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&address_record, contactsDeleter);
+
+    for(int enum_val = 0 ;
+            enum_val < (static_cast<int>(CONTACT_ADDRESS_NUMBER_OF_ATTRIBUTES)) ;
+            enum_val++) {
+        if (isSet(get[enum_val].atr)) {
+            ContactUtil::setStrInRecord(address_record,get[enum_val].prop_id,
+                    getAttribute(get[enum_val].atr).c_str());
+        }
+    }
+
+    ContactUtil::setBoolInRecord(address_record,
+            _contacts_address.is_default,
+                getIsDefault());
+
+    int type_to_set = 0;
+    auto types = getTypes();
+    for (size_t i = 0; i < types.size(); i++) {
+        switch (ContactUtil::stringToContactAddressType(types[i])) {
+            case CONTACT_ADDRESS_TYPE_WORK:
+                type_to_set = type_to_set | CONTACTS_ADDRESS_TYPE_WORK;
+                break;
+            case CONTACT_ADDRESS_TYPE_OTHER:
+                type_to_set = 0;
+                break;
+            case CONTACT_ADDRESS_TYPE_CUSTOM:
+                type_to_set = type_to_set | CONTACTS_ADDRESS_TYPE_CUSTOM;
+                break;
+            default:
+                type_to_set = type_to_set | CONTACTS_ADDRESS_TYPE_HOME;
+                break;
+        }
+        if (!type_to_set) {
+            break;
+        }
+    }
+
+    ContactUtil::setIntInRecord(address_record,_contacts_address.type,
+            type_to_set);
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.address, address_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    record.release();
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactAddress.h b/src/Contact/ContactAddress.h
new file mode 100644 (file)
index 0000000..b11f804
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_CONTACT_ADDRESS_H__
+#define __TIZEN_CONTACT_CONTACT_ADDRESS_H__
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <JSVector.h>
+#include <contacts.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactAddress;
+typedef std::shared_ptr<ContactAddress> ContactAddressPtr;
+typedef std::vector<ContactAddressPtr> ContactAddressPtrVector;
+
+enum ContactAddressType {
+    CONTACT_ADDRESS_TYPE_NONE,
+    CONTACT_ADDRESS_TYPE_WORK,
+    CONTACT_ADDRESS_TYPE_HOME,
+    CONTACT_ADDRESS_TYPE_PREF,
+    CONTACT_ADDRESS_TYPE_OTHER,
+    CONTACT_ADDRESS_TYPE_CUSTOM
+};
+typedef std::vector<ContactAddressType> ContactAddressTypeVector;
+
+enum ContactAddressAttribute{
+    CONTACT_ADDRESS_ATTRIBUTE_COUNTRY,
+    CONTACT_ADDRESS_ATTRIBUTE_REGION,
+    CONTACT_ADDRESS_ATTRIBUTE_CITY,
+    CONTACT_ADDRESS_ATTRIBUTE_STREETADDR,
+    CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO,
+    CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE,
+    CONTACT_ADDRESS_ATTRIBUTE_LABEL,
+    CONTACT_ADDRESS_NUMBER_OF_ATTRIBUTES
+};
+
+class ContactAddress {
+public:
+    ContactAddress();
+    virtual ~ContactAddress();
+
+    std::string getAttribute(ContactAddressAttribute attribute) const;
+    void setAttribute(ContactAddressAttribute attribute,
+            const std::string &value);
+    bool isSet(ContactAddressAttribute attribute) const;
+    void setIsSet(ContactAddressAttribute attribute, bool is_set);
+    bool getIsDefault() const;
+    void setIsDefault(bool is_default);
+    std::vector<std::string> getTypes();
+    void setTypes(const std::vector<std::string> &types);
+    JSValueRef getJSTypes(JSContextRef global_ctx);
+    void importFromContactsRecord(contacts_record_h contacts_record,
+            unsigned int index);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+
+private:
+    std::string m_country;
+    std::string m_region;
+    std::string m_city;
+    std::string m_street_address;
+    std::string m_additional_information;
+    std::string m_postal_code;
+    bool m_is_default;
+    Common::JSStringVector m_types;
+    std::string m_label;
+    bool m_is_set[ContactAddressAttribute::CONTACT_ADDRESS_NUMBER_OF_ATTRIBUTES];
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif
diff --git a/src/Contact/ContactAnniversary.cpp b/src/Contact/ContactAnniversary.cpp
new file mode 100644 (file)
index 0000000..b8e2645
--- /dev/null
@@ -0,0 +1,164 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactAnniversary.cpp
+ */
+#include <PlatformException.h>
+#include <Logger.h>
+#include "ContactAnniversary.h"
+#include "ContactUtil.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+ContactAnniversary::ContactAnniversary()
+{
+    m_tm = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+    m_is_label_set = false;
+}
+
+ContactAnniversary::~ContactAnniversary()
+{
+
+}
+
+std::tm ContactAnniversary::getDate()
+{
+    return m_tm;
+}
+
+void ContactAnniversary::setDate(const std::tm& value)
+{
+    m_tm = value;
+}
+
+std::string ContactAnniversary::getLabel()
+{
+    return m_label;
+}
+
+void ContactAnniversary::setLabel(const std::string &value)
+{
+    m_label = value;
+    m_is_label_set = true;
+}
+
+bool ContactAnniversary::isLabelSet()
+{
+    return m_is_label_set;
+}
+
+void ContactAnniversary::unsetLabel()
+{
+    m_is_label_set = false;
+}
+
+bool ContactAnniversary::importFromContactsRecord(contacts_record_h contacts_record,
+        unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_get_child_record_at_p(contacts_record,
+            _contacts_contact.event, index, &child_record);
+    if ( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err ) {
+        LOGW("Failed contacts_record_get_child_record_at_p(): %s, %d",
+                ContactUtil::getContactErrorMessage(err).c_str(), err);
+        return false;
+    }
+
+    int value = 0;
+    ContactUtil::getIntFromRecord(child_record,
+            _contacts_event.type, &value);
+
+    if(CONTACTS_EVENT_TYPE_BIRTH == value){
+        return false;
+    }
+
+    if (CONTACTS_EVENT_TYPE_ANNIVERSARY == value) {
+        ContactUtil::getIntFromRecord(child_record,
+                _contacts_event.date, &value);
+        try {
+            setDate(ContactUtil::toTimeT(value));
+        }
+        catch (const Common::BasePlatformException& e) {
+            LOGE("%d", e.getMessage().c_str());
+        }
+        char* label = NULL;
+        ContactUtil::getStrFromRecord(child_record,
+                _contacts_event.label, &label);
+        if(!label){
+            unsetLabel();
+        }
+        setLabel(std::string(label));
+    }
+    return true;
+}
+
+void ContactAnniversary::exportToContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h anniversary_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    if (m_tm.tm_year == 0 && m_tm.tm_mon == 0
+            && m_tm.tm_mday == 0) {
+            return;
+    }
+
+    int date = ContactUtil::toDateDbInt(m_tm);
+
+    err = contacts_record_create(_contacts_event._uri, &anniversary_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&anniversary_record, contactsDeleter);
+
+    ContactUtil::setIntInRecord(anniversary_record,
+            _contacts_event.type, CONTACTS_EVENT_TYPE_ANNIVERSARY);
+
+    ContactUtil::setIntInRecord(anniversary_record,
+            _contacts_event.date, date);
+
+
+    if(isLabelSet()){
+        ContactUtil::setStrInRecord(anniversary_record,
+                _contacts_event.label, getLabel().c_str());
+    }
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.event, anniversary_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    record.release();
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactAnniversary.h b/src/Contact/ContactAnniversary.h
new file mode 100644 (file)
index 0000000..a0529ba
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactAnniversary.h
+ */
+
+#ifndef _TIZEN_CONTACT_CONTACT_ANNIVERSARY_H_
+#define _TIZEN_CONTACT_CONTACT_ANNIVERSARY_H_
+
+#include <memory>
+#include <ctime>
+#include <string>
+#include <vector>
+#include <contacts.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactAnniversary;
+typedef std::shared_ptr<ContactAnniversary> ContactAnniversaryPtr;
+typedef std::vector<ContactAnniversaryPtr> ContactAnniversaryPtrVector;
+
+/* This object represents an anniversary data of a contact */
+class ContactAnniversary {
+public:
+    ContactAnniversary();
+    virtual ~ContactAnniversary();
+
+    std::tm getDate();
+    void setDate(const std::tm& value);
+    std::string getLabel();
+    void setLabel(const std::string &value);
+    bool isLabelSet();
+    void unsetLabel();
+    bool importFromContactsRecord(contacts_record_h contacts_record,
+            unsigned int index);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+
+private:
+    tm m_tm;
+    std::string m_label;
+    bool m_is_label_set;
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // _TIZEN_CONTACT_CONTACT_ANNIVERSARY_H_
diff --git a/src/Contact/ContactEmailAddress.cpp b/src/Contact/ContactEmailAddress.cpp
new file mode 100644 (file)
index 0000000..3c9bced
--- /dev/null
@@ -0,0 +1,219 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "ContactEmailAddress.h"
+#include "ContactUtil.h"
+#include <algorithm>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+ContactEmailAddress::ContactEmailAddress()
+{
+    m_email = "";
+    m_is_default = false;
+    m_types.push_back(ContactUtil::CONTACT_TYPE_WORK);
+    m_is_label_set = false;
+    m_label = "";
+}
+
+ContactEmailAddress::~ContactEmailAddress()
+{
+}
+
+std::string ContactEmailAddress::getEmail() const
+{
+    return m_email;
+}
+
+void ContactEmailAddress::setEmail(const std::string &email)
+{
+    m_email = email;
+}
+
+bool ContactEmailAddress::getIsDefault() const
+{
+    return m_is_default;
+}
+
+void ContactEmailAddress::setIsDefault(bool is_default)
+{
+    m_is_default = is_default;
+}
+
+void ContactEmailAddress::setTypes(const std::vector<std::string> &types)
+{
+    m_types = types;
+}
+
+void ContactEmailAddress::importFromContactsRecord(contacts_record_h contacts_record,
+        unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_get_child_record_at_p(contacts_record, _contacts_contact.email, index, &child_record);
+    if (CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err) {
+        LOGW("Failed contacts_record_get_child_record_at_p(): %s, %d",
+                ContactUtil::getContactErrorMessage(err).c_str(), err);
+        return;
+    }
+
+    char* email = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_email.email, &email);
+    if(!email){
+        return;
+    }
+    m_email = std::string(email);
+
+    bool is_default = false;
+    ContactUtil::getBoolFromRecord(child_record,
+            _contacts_email.is_default, &is_default);
+    m_is_default = is_default;
+
+    int type = 0;
+    ContactUtil::getIntFromRecord(child_record,
+            _contacts_email.type, &type);
+
+    char* label = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_email.label, &label);
+    if (label) {
+        setLabel(std::string(label));
+    }
+
+    m_types.clear();
+    if(type & CONTACTS_EMAIL_TYPE_HOME){
+        m_types.push_back(ContactUtil::CONTACT_TYPE_HOME);
+    }
+    if(type & CONTACTS_EMAIL_TYPE_WORK){
+        m_types.push_back(ContactUtil::CONTACT_TYPE_WORK);
+    }
+    if(type & CONTACTS_EMAIL_TYPE_CUSTOM){
+        m_types.push_back(ContactUtil::CONTACT_TYPE_CUSTOM);
+    }
+    if (!type) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_OTHER);
+    }
+
+    if (0 == m_types.size()) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_HOME);
+    }
+}
+
+void ContactEmailAddress::exportToContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h c_email_record_h = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_create(_contacts_email._uri, &c_email_record_h);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&c_email_record_h, contactsDeleter);
+
+    ContactUtil::setStrInRecord(c_email_record_h,
+            _contacts_email.email, getEmail().c_str());
+    ContactUtil::setBoolInRecord(c_email_record_h,
+            _contacts_email.is_default, getIsDefault());
+
+    int type_to_set = 0;
+
+    auto types = getTypes();
+    for (size_t i = 0; i < types.size(); i++) {
+        switch (ContactUtil::stringToContactEmailAddressType(types[i])) {
+            case CONTACT_EMAIL_ADDRESS_TYPE_WORK:
+                type_to_set = type_to_set | CONTACTS_EMAIL_TYPE_WORK;
+                break;
+            case CONTACT_EMAIL_ADDRESS_TYPE_OTHER:
+                type_to_set = 0;
+                break;
+            case CONTACT_EMAIL_ADDRESS_TYPE_CUSTOM:
+                type_to_set = type_to_set | CONTACTS_EMAIL_TYPE_CUSTOM;
+                break;
+            default:
+                type_to_set = type_to_set | CONTACTS_EMAIL_TYPE_HOME;
+                break;
+        }
+        if (!type_to_set) {
+            break;
+        }
+    }
+    ContactUtil::setIntInRecord(c_email_record_h,
+            _contacts_email.type, type_to_set);
+    if (isLabelSet()) {
+        ContactUtil::setStrInRecord(c_email_record_h,
+                _contacts_email.label, getLabel().c_str());
+    }
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.email, c_email_record_h);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    record.release();
+}
+
+std::vector<std::string> ContactEmailAddress::getTypes()
+{
+    return m_types;
+}
+
+JSValueRef ContactEmailAddress::getJSTypes(JSContextRef global_ctx)
+{
+    return m_types.getJSArray(global_ctx);
+}
+
+bool ContactEmailAddress::isLabelSet() const
+{
+    return m_is_label_set;
+}
+
+std::string ContactEmailAddress::getLabel() const
+{
+    return m_label;
+}
+
+void ContactEmailAddress::setLabel(std::string label)
+{
+    m_label = label;
+    m_is_label_set = true;
+}
+
+void ContactEmailAddress::unsetLabel()
+{
+    m_is_label_set = false;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactEmailAddress.h b/src/Contact/ContactEmailAddress.h
new file mode 100644 (file)
index 0000000..d8a9b45
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_CONTACT_EMAIL_ADDRESS_H__
+#define __TIZEN_CONTACT_CONTACT_EMAIL_ADDRESS_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <contacts.h>
+#include <JSVector.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactEmailAddress;
+typedef std::shared_ptr<ContactEmailAddress> ContactEmailAddressPtr;
+typedef std::vector<ContactEmailAddressPtr> ContactEmailAddressPtrVector;
+
+enum ContactEmailAddressType {
+    CONTACT_EMAIL_ADDRESS_TYPE_NONE,
+    CONTACT_EMAIL_ADDRESS_TYPE_WORK,
+    CONTACT_EMAIL_ADDRESS_TYPE_HOME,
+    CONTACT_EMAIL_ADDRESS_TYPE_PREF,
+    CONTACT_EMAIL_ADDRESS_TYPE_OTHER,
+    CONTACT_EMAIL_ADDRESS_TYPE_CUSTOM
+};
+
+class ContactEmailAddress {
+public:
+    ContactEmailAddress();
+    virtual ~ContactEmailAddress();
+
+    std::string getEmail() const;
+    void setEmail(const std::string &email);
+    bool getIsDefault() const;
+    void setIsDefault(bool is_default);
+    std::vector<std::string> getTypes();
+    void setTypes(const std::vector<std::string> &types);
+    void importFromContactsRecord(contacts_record_h contacts_record, unsigned int index);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+    JSValueRef getJSTypes(JSContextRef global_ctx);
+    bool isLabelSet() const;
+    std::string getLabel() const;
+    void setLabel(std::string label);
+    void unsetLabel();
+
+private:
+    std::string m_email;
+    bool m_is_default;
+    Common::JSStringVector m_types;
+    bool m_is_label_set;
+    std::string m_label;
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif
diff --git a/src/Contact/ContactGroup.cpp b/src/Contact/ContactGroup.cpp
new file mode 100644 (file)
index 0000000..588501a
--- /dev/null
@@ -0,0 +1,231 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactGroup.cpp
+ */
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "ContactGroup.h"
+#include "ContactUtil.h"
+
+namespace DeviceAPI {
+namespace Contact {
+ContactGroup::ContactGroup() :
+        m_id_is_set(false),
+        m_address_book_id_is_set(false),
+        m_ringtone_uri_is_set(false),
+        m_photo_uri_is_set(false),
+        m_read_only(false)
+{
+}
+
+ContactGroup::~ContactGroup()
+{
+}
+
+std::string ContactGroup::getId() const
+{
+    return m_id;
+}
+
+void ContactGroup::setId(const std::string &value)
+{
+    m_id = value;
+    m_id_is_set = true;
+}
+
+void ContactGroup::unsetId()
+{
+    m_id = "";
+    m_id_is_set = false;
+}
+
+bool ContactGroup::getIdIsSet() const
+{
+    return m_id_is_set;
+}
+
+std::string ContactGroup::getAddressBookId() const
+{
+    return m_address_book_id;
+}
+
+void ContactGroup::setAddressBookId(const std::string &value)
+{
+    m_address_book_id = value;
+    m_address_book_id_is_set = true;
+}
+
+void ContactGroup::unsetAddressBookId()
+{
+    m_address_book_id = "";
+    m_address_book_id_is_set = false;
+}
+
+bool ContactGroup::getAddressBookIdIsSet() const
+{
+    return m_address_book_id_is_set;
+}
+
+std::string ContactGroup::getName() const
+{
+    return m_name;
+}
+
+void ContactGroup::setName(const std::string &value)
+{
+    m_name = value;
+}
+
+std::string ContactGroup::getRingtoneURI() const
+{
+    return m_ringtone_uri;
+}
+
+void ContactGroup::setRingtoneURI(const std::string &value)
+{
+    m_ringtone_uri = value;
+    m_ringtone_uri_is_set = true;
+}
+
+void ContactGroup::unsetRingtoneURI()
+{
+    m_ringtone_uri = "";
+    m_ringtone_uri_is_set = false;
+}
+
+bool ContactGroup::getRingtoneURIIsSet() const
+{
+    return m_ringtone_uri_is_set;
+}
+
+std::string ContactGroup::getPhotoURI() const
+{
+    return m_photo_uri;
+}
+
+void ContactGroup::setPhotoURI(const std::string &value)
+{
+    m_photo_uri = value;
+    m_photo_uri_is_set = true;
+}
+
+void ContactGroup::unsetPhotoURI()
+{
+    m_photo_uri = "";
+    m_photo_uri_is_set = false;
+}
+
+bool ContactGroup::getPhotoURIIsSet() const
+{
+    return m_photo_uri_is_set;
+}
+
+bool ContactGroup::getReadOnly() const
+{
+    return m_read_only;
+}
+
+void ContactGroup::setReadOnly(const bool &value)
+{
+    m_read_only = value;
+}
+
+void ContactGroup::importFromContactsRecord(contacts_record_h contacts_record)
+{
+
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    // id
+    int int_val = 0;
+    ContactUtil::getIntFromRecord(contacts_record,
+            _contacts_group.id, &int_val);
+    setId(std::to_string(int_val));
+
+    // addressBookId
+    ContactUtil::getIntFromRecord(contacts_record,
+            _contacts_group.address_book_id, &int_val);
+    setAddressBookId(std::to_string(int_val));
+
+    // name
+    char* char_value = NULL;
+    ContactUtil::getStrFromRecord(contacts_record,
+            _contacts_group.name, &char_value);
+    if (char_value){
+        setName(std::string(char_value));
+    }
+
+    // photoURI
+    char_value = NULL;
+    ContactUtil::getStrFromRecord(contacts_record,
+            _contacts_group.image_path, &char_value);
+    if (char_value) {
+        setPhotoURI(ContactUtil::convertPathToUri(std::string(char_value)));
+    }
+    else {
+        unsetPhotoURI();
+    }
+
+    // ringtoneURI
+    char_value = NULL;
+    ContactUtil::getStrFromRecord(contacts_record,
+            _contacts_group.ringtone_path, &char_value);
+    if (char_value) {
+        setRingtoneURI(ContactUtil::convertPathToUri(char_value));
+    }
+    else {
+        unsetRingtoneURI();
+    }
+
+    // is_read_only
+    bool bool_value = false;
+    ContactUtil::getBoolFromRecord(contacts_record,
+            _contacts_group.is_read_only, &bool_value);
+    setReadOnly(bool_value);
+}
+
+void ContactGroup::exportToContactsRecord(contacts_record_h contacts_record)
+{
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    // name
+    ContactUtil::setStrInRecord(contacts_record,
+            _contacts_group.name, getName().c_str());
+
+    // photoURI
+    std::string real_path = ContactUtil::convertUriToPath(getPhotoURI());
+    ContactUtil::setStrInRecord(contacts_record,
+            _contacts_group.image_path, real_path.c_str());
+
+    // rightone URI
+    real_path = ContactUtil::convertUriToPath(getPhotoURI());
+    ContactUtil::setStrInRecord(contacts_record,
+            _contacts_group.ringtone_path, getRingtoneURI().c_str());
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactGroup.h b/src/Contact/ContactGroup.h
new file mode 100644 (file)
index 0000000..3900e04
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactGroup.h
+ */
+
+#ifndef __TIZEN_CONTACT_CONTACT_GROUP_H__
+#define __TIZEN_CONTACT_CONTACT_GROUP_H__
+
+#include <string>
+#include <memory>
+#include <vector>
+#include "contacts.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactGroup;
+typedef std::shared_ptr<ContactGroup> ContactGroupPtr;
+typedef std::vector<ContactGroupPtr> ContactGroupPtrVector;
+
+class ContactGroup {
+public:
+    ContactGroup();
+    virtual ~ContactGroup();
+
+    std::string getId() const;
+    void setId(const std::string &value);
+    void unsetId();
+    bool getIdIsSet() const;
+
+    std::string getAddressBookId() const;
+    void setAddressBookId(const std::string &value);
+    void unsetAddressBookId();
+    bool getAddressBookIdIsSet() const;
+
+    std::string getName() const;
+    void setName(const std::string &value);
+
+    std::string getRingtoneURI() const;
+    void setRingtoneURI(const std::string &value);
+    void unsetRingtoneURI();
+    bool getRingtoneURIIsSet() const;
+
+    std::string getPhotoURI() const;
+    void setPhotoURI(const std::string &value);
+    void unsetPhotoURI();
+    bool getPhotoURIIsSet() const;
+
+    bool getReadOnly() const;
+    void setReadOnly(const bool &value);
+
+    void importFromContactsRecord(contacts_record_h contacts_record);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+
+private:
+    std::string m_id;
+    bool m_id_is_set;
+
+    std::string m_address_book_id;
+    bool m_address_book_id_is_set;
+
+    std::string m_name;
+
+    std::string m_ringtone_uri;
+    bool m_ringtone_uri_is_set;
+
+    std::string m_photo_uri;
+    bool m_photo_uri_is_set;
+
+    bool m_read_only;
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif
diff --git a/src/Contact/ContactInstantMessenger.cpp b/src/Contact/ContactInstantMessenger.cpp
new file mode 100644 (file)
index 0000000..5d65bac
--- /dev/null
@@ -0,0 +1,242 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactInstantMessenger.cpp
+ */
+
+#include "ContactInstantMessenger.h"
+#include <Logger.h>
+#include <PlatformException.h>
+#include "ContactUtil.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+ContactInstantMessenger::ContactInstantMessenger():
+        m_is_label_set(false)
+{
+}
+
+ContactInstantMessenger::~ContactInstantMessenger()
+{
+}
+
+std::string ContactInstantMessenger::getImAddress() const
+{
+    return m_im_address;
+}
+
+void ContactInstantMessenger::setImAddress(std::string imAddress)
+{
+    m_im_address = imAddress;
+}
+
+ContactInstantMessengerType ContactInstantMessenger::getType() const
+{
+    return m_type;
+}
+
+void ContactInstantMessenger::setType(ContactInstantMessengerType type)
+{
+    m_type = type;
+}
+
+std::string ContactInstantMessenger::getLabel() const
+{
+    return m_label;
+}
+
+void ContactInstantMessenger::setLabel(const std::string &value)
+{
+    m_is_label_set = true;
+    m_label = value;
+}
+
+bool ContactInstantMessenger::isLabelSet() const
+{
+    return m_is_label_set;
+}
+
+void ContactInstantMessenger::unsetLabel()
+{
+    m_is_label_set = false;
+}
+
+void ContactInstantMessenger::importFromContactsRecord(
+        contacts_record_h contacts_record, unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_get_child_record_at_p(contacts_record,
+            _contacts_contact.messenger, index, &child_record);
+    if ( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err ) {
+        LOGW("Failed contacts_record_get_child_record_at_p(): %s, %d",
+                ContactUtil::getContactErrorMessage(err).c_str(), err);
+        return;
+    }
+
+    char* imAddress = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_messenger.im_id, &imAddress);
+    if (!imAddress) {
+        return;
+    }
+
+    m_im_address = std::string(imAddress);
+
+    int type = 0;
+    ContactUtil::getIntFromRecord(child_record, _contacts_messenger.type, &type);
+
+    ContactInstantMessengerType imType;;
+
+    switch (type) {
+        case CONTACTS_MESSENGER_TYPE_CUSTOM:
+            imType = CONTACT_IM_TYPE_CUSTOM;
+            break;
+        case CONTACTS_MESSENGER_TYPE_GOOGLE:
+            imType = CONTACT_IM_TYPE_GOOGLE;
+            break;
+        case CONTACTS_MESSENGER_TYPE_WLM:
+            imType = CONTACT_IM_TYPE_WLM;
+            break;
+        case CONTACTS_MESSENGER_TYPE_YAHOO:
+            imType = CONTACT_IM_TYPE_YAHOO;
+            break;
+        case CONTACTS_MESSENGER_TYPE_FACEBOOK:
+            imType = CONTACT_IM_TYPE_FACEBOOK;
+            break;
+        case CONTACTS_MESSENGER_TYPE_ICQ:
+            imType = CONTACT_IM_TYPE_ICQ;
+            break;
+        case CONTACTS_MESSENGER_TYPE_AIM:
+            imType = CONTACT_IM_TYPE_AIM;
+            break;
+        case CONTACTS_MESSENGER_TYPE_QQ:
+            imType = CONTACT_IM_TYPE_QQ;
+            break;
+        case CONTACTS_MESSENGER_TYPE_JABBER:
+            imType = CONTACT_IM_TYPE_JABBER;
+            break;
+        case CONTACTS_MESSENGER_TYPE_SKYPE:
+            imType = CONTACT_IM_TYPE_SKYPE;
+            break;
+        case CONTACTS_MESSENGER_TYPE_IRC:
+            imType = CONTACT_IM_TYPE_IRC;
+            break;
+        case CONTACTS_MESSENGER_TYPE_OTHER:
+        default:
+            imType = CONTACT_IM_TYPE_OTHER;
+            break;
+    }
+    m_type = imType;
+
+    char* label = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_messenger.label, &label);
+    if (label) {
+        setLabel(std::string(label));
+    }
+}
+
+void ContactInstantMessenger::exportToContactsRecord(
+        contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_create(_contacts_messenger._uri, &child_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&child_record, contactsDeleter);
+
+    ContactUtil::setStrInRecord(child_record, _contacts_messenger.im_id,
+            getImAddress().c_str());
+
+    int type_to_set = 0;
+    switch (m_type) {
+        case CONTACT_IM_TYPE_GOOGLE:
+            type_to_set = CONTACTS_MESSENGER_TYPE_GOOGLE;
+            break;
+        case CONTACT_IM_TYPE_WLM:
+            type_to_set = CONTACTS_MESSENGER_TYPE_WLM;
+            break;
+        case CONTACT_IM_TYPE_YAHOO:
+            type_to_set = CONTACTS_MESSENGER_TYPE_YAHOO;
+            break;
+        case CONTACT_IM_TYPE_FACEBOOK:
+            type_to_set = CONTACTS_MESSENGER_TYPE_FACEBOOK;
+            break;
+        case CONTACT_IM_TYPE_ICQ:
+            type_to_set = CONTACTS_MESSENGER_TYPE_ICQ;
+            break;
+        case CONTACT_IM_TYPE_AIM:
+            type_to_set = CONTACTS_MESSENGER_TYPE_AIM;
+            break;
+        case CONTACT_IM_TYPE_QQ:
+            type_to_set = CONTACTS_MESSENGER_TYPE_QQ;
+            break;
+        case CONTACT_IM_TYPE_JABBER:
+            type_to_set = CONTACTS_MESSENGER_TYPE_JABBER;
+            break;
+        case CONTACT_IM_TYPE_SKYPE:
+            type_to_set = CONTACTS_MESSENGER_TYPE_SKYPE;
+            break;
+        case CONTACT_IM_TYPE_IRC:
+            type_to_set = CONTACTS_MESSENGER_TYPE_IRC;
+            break;
+        case CONTACT_IM_TYPE_CUSTOM:
+            type_to_set = CONTACTS_MESSENGER_TYPE_CUSTOM;
+            break;
+        case CONTACT_IM_TYPE_OTHER:
+        default:
+            type_to_set = CONTACTS_MESSENGER_TYPE_OTHER;
+            break;
+    }
+
+    ContactUtil::setIntInRecord(child_record,_contacts_messenger.type,
+            type_to_set);
+
+    if(isLabelSet()) {
+        ContactUtil::setStrInRecord(child_record,_contacts_messenger.label,
+                getLabel().c_str());
+    }
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.messenger, child_record);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    record.release();
+}
+
+}
+}
diff --git a/src/Contact/ContactInstantMessenger.h b/src/Contact/ContactInstantMessenger.h
new file mode 100644 (file)
index 0000000..d72a48a
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactInstantMessenger.h
+ */
+
+#ifndef _TIZEN_CONTACT_CONTACT_INSTANT_MESSENGER_H_
+#define _TIZEN_CONTACT_CONTACT_INSTANT_MESSENGER_H_
+
+#include <memory>
+#include <ctime>
+#include <string>
+#include <vector>
+#include <contacts.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactInstantMessenger;
+typedef std::shared_ptr<ContactInstantMessenger> ContactInstantMessengerPtr;
+typedef std::vector<ContactInstantMessengerPtr> ContactInstantMessengerPtrVector;
+
+enum ContactInstantMessengerType {
+    CONTACT_IM_TYPE_OTHER,
+    CONTACT_IM_TYPE_GOOGLE,
+    CONTACT_IM_TYPE_WLM,
+    CONTACT_IM_TYPE_YAHOO,
+    CONTACT_IM_TYPE_FACEBOOK,
+    CONTACT_IM_TYPE_ICQ,
+    CONTACT_IM_TYPE_AIM,
+    CONTACT_IM_TYPE_QQ,
+    CONTACT_IM_TYPE_JABBER,
+    CONTACT_IM_TYPE_SKYPE,
+    CONTACT_IM_TYPE_IRC,
+    CONTACT_IM_TYPE_CUSTOM
+};
+
+class ContactInstantMessenger {
+public:
+    ContactInstantMessenger();
+    virtual ~ContactInstantMessenger();
+
+    std::string getImAddress() const;
+    void setImAddress(std::string imAddress);
+    ContactInstantMessengerType getType() const;
+    void setType(ContactInstantMessengerType type);
+    std::string getLabel() const;
+    void setLabel(const std::string &value);
+    bool isLabelSet() const;
+    void unsetLabel();
+    void importFromContactsRecord(contacts_record_h contacts_record,
+            unsigned int index);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+
+private:
+    std::string m_im_address;
+    ContactInstantMessengerType m_type;
+    std::string m_label;
+    bool m_is_label_set;
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // _TIZEN_CONTACT_CONTACT_INSTANT_MESSENGER_H_
diff --git a/src/Contact/ContactManager.cpp b/src/Contact/ContactManager.cpp
new file mode 100755 (executable)
index 0000000..43be6be
--- /dev/null
@@ -0,0 +1,955 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactManager.cpp
+ */
+
+#include "ContactManager.h"
+#include "Contact.h"
+#include "Person.h"
+#include "JSPerson.h"
+#include "JSAddressBook.h"
+#include "ContactUtil.h"
+#include "PersonSearchEngine.h"
+#include <map>
+#include <memory>
+#include <Logger.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <JSWebAPIErrorFactory.h>
+#include <contacts.h>
+#include <PlatformException.h>
+#include <Commons/Regex.h>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace Common;
+
+namespace {
+const char* TOKEN_DELIMITER = " ,:";
+}
+
+ContactManager::ContactManager() :
+        SecurityAccessor(),
+        m_listener_counter(1)
+{
+    int error_code = contacts_connect();
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_connect()");
+    }
+
+    try {
+        m_unified_address_book = AddressBookPtr(new AddressBook());
+    }
+    catch (const std::bad_alloc &err) {
+        LOGE("Memory allocation error, msg: %s", err.what());
+        error_code = contacts_disconnect();
+        if(CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                    "contacts_disconnect()").c_str());
+        }
+        throw UnknownException("Cannot instantiate ContactManager");
+    }
+    m_unified_address_book->setAddressBookId(AddressBook::UNIFIED_ADDRESS_BOOK_ID);
+    m_unified_address_book->setName(AddressBook::UNIFIED_ADDRESS_BOOK_NAME);
+    m_unified_address_book->setReadOnly(false);
+    m_unified_address_book->setIsUnified(true);
+}
+
+ContactManager::~ContactManager()
+{
+    int error_code = 0;
+
+    if(!m_listeners.empty()) {
+        error_code = contacts_db_remove_changed_cb_with_info(_contacts_person._uri,
+                personsDBChangeCallback, NULL);
+
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                    "contacts_db_remove_changed_cb_with_info()").c_str());
+        }
+    }
+
+    error_code = contacts_disconnect();
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                "contacts_disconnect()").c_str());
+    }
+}
+
+ContactManager& ContactManager::getInstance()
+{
+    static ContactManager instance;
+    return instance;
+}
+
+gboolean ContactManager::getAddressBooksCallback(void *data)
+{
+    auto callback = static_cast<GetAddressBooksCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    auto address_books = callback->getAddressBooks();
+    if (!address_books) {
+        LOGE("address books is null");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(error);
+        }
+        else {
+            JSObjectRef arr = ptrVectorToJSObjectArray<JSAddressBook, AddressBookPtr>(
+                    *address_books, context);
+            callback->callSuccessCallback(arr);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getAddressBooksCallback fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getAddressBooksCallback fails");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* ContactManager::getAddressBooksThread(void *data)
+{
+    auto callback = static_cast<GetAddressBooksCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        contacts_list_h address_book_list = NULL;
+
+        int error_code = contacts_db_get_all_records(_contacts_address_book._uri, 0, 0,
+                &address_book_list);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_get_all_records()");
+        }
+
+        contacts_list_h_ptr contacts_list_ptr(&address_book_list, contactsListDeleter);
+
+        int record_count = 0;
+        error_code = contacts_list_get_count(*contacts_list_ptr, &record_count);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_list_get_count()");
+        }
+
+        error_code = contacts_list_first(*contacts_list_ptr);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_list_first()");
+        }
+
+        auto ab_vector = std::shared_ptr<AddressBookPtrVector>(
+                new AddressBookPtrVector());
+
+        for (unsigned int i = 0; i < record_count; i++) {
+            contacts_record_h contacts_record = NULL;
+            error_code = contacts_list_get_current_record_p(*contacts_list_ptr,
+                    &contacts_record);
+
+            if(CONTACTS_ERROR_NONE != error_code) {
+                LOGW("Failed contacts_list_get_current_record_p(): %s, %d",
+                        ContactUtil::getContactErrorMessage(error_code).c_str(), error_code);
+                continue;
+            }
+
+            int id = 0;
+            int mode = 0;
+            char *name = NULL;
+
+            try {
+                ContactUtil::getIntFromRecord(contacts_record,
+                        _contacts_address_book.id, &id);
+
+                ContactUtil::getIntFromRecord(contacts_record,
+                        _contacts_address_book.mode, &mode);
+
+                ContactUtil::getStrFromRecord(contacts_record,
+                        _contacts_address_book.name, &name);
+            }
+            catch (...) {
+                LOGW("Fail to get data from address book");
+                continue;
+            }
+
+            AddressBookPtr ab = AddressBookPtr(new AddressBook());
+            ab->setAddressBookId(id);
+            ab->setName(name);
+            ab->setReadOnly(CONTACTS_ADDRESS_BOOK_MODE_READONLY == mode);
+
+            ab_vector->push_back(ab);
+
+            int error_code = contacts_list_next(*contacts_list_ptr);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                        "contacts_list_next()").c_str());
+            }
+        }
+
+        callback->setAddressBooks(ab_vector);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getAddressBooksThread fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch (...) {
+        LOGE("getAddressBooksThread fails");
+        callback->setError("UnknownError", "getAddressBooksThread fails");
+    }
+
+    guint id = g_idle_add(getAddressBooksCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    return NULL;
+}
+
+void ContactManager::getAddressBooks(GetAddressBooksCallbackData *callback)
+{
+    pthread_t thread;
+    if(pthread_create(&thread, NULL, getAddressBooksThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+    if(pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+AddressBookPtr ContactManager::getUnifiedAddressBook()
+{
+    return m_unified_address_book;
+}
+
+AddressBookPtr ContactManager::getDefaultAddressBook()
+{
+    return getAddressBook(AddressBook::DEFAULT_ADDRESS_BOOK_ID);
+}
+
+AddressBookPtr ContactManager::getAddressBook(long address_book_id)
+{
+
+    contacts_record_h contacts_record;
+    int error_code = contacts_db_get_record(_contacts_address_book._uri,
+            address_book_id, &contacts_record);
+    if (CONTACTS_ERROR_NONE != error_code || NULL == contacts_record) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException<NotFoundException>(error_code, "contacts_db_get_record()");
+    }
+
+    contacts_record_h_ptr contacts_record_ptr(&contacts_record, contactsDeleter);
+
+    int mode = 0;
+    error_code = contacts_record_get_int(*contacts_record_ptr,
+            _contacts_address_book.mode, &mode);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_record_get_int()").c_str());
+    }
+
+    char *name = NULL;
+    error_code = contacts_record_get_str_p(*contacts_record_ptr,
+            _contacts_address_book.name, &name);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGW("Failed contacts_record_get_str_p(): %s, %d",
+                ContactUtil::getContactErrorMessage(error_code).c_str(), error_code);
+    }
+
+    AddressBookPtr address_book;
+    try {
+        address_book = AddressBookPtr(new AddressBook());
+    }
+    catch (const std::bad_alloc &err) {
+        LOGE("Memory allocation error, msg: %s", err.what());
+        throw UnknownException("Memory allocation error");
+    }
+    address_book->setAddressBookId(address_book_id);
+    address_book->setName(name);
+    address_book->setReadOnly(CONTACTS_ADDRESS_BOOK_MODE_READONLY == mode);
+
+    return address_book;
+}
+
+void ContactManager::addAddressBook(AddressBookPtr address_book)
+{
+    contacts_record_h contacts_record;
+    int ret = contacts_record_create(_contacts_address_book._uri, &contacts_record);
+    if (CONTACTS_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ContactUtil::throwContactException(ret, "contacts_record_create()");
+    }
+    contacts_record_h_ptr contacts_record_ptr(&contacts_record, contactsDeleter);
+
+    ret = contacts_record_set_str(*contacts_record_ptr, _contacts_address_book.name,
+        address_book->getName().c_str());
+    if (CONTACTS_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ContactUtil::throwContactException(ret, "contacts_record_set_str()");
+    }
+
+    contacts_address_book_mode_e mode = address_book->getReadOnly() ?
+        CONTACTS_ADDRESS_BOOK_MODE_READONLY : CONTACTS_ADDRESS_BOOK_MODE_NONE;
+    ret = contacts_record_set_int(*contacts_record_ptr, _contacts_address_book.mode,
+        static_cast<int>(mode));
+    if (CONTACTS_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ContactUtil::throwContactException(ret, "contacts_record_set_int()");
+    }
+
+    ret = contacts_record_set_int(*contacts_record_ptr, _contacts_address_book.account_id,
+        static_cast<int>(address_book->getAccountId()));
+    if (CONTACTS_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ContactUtil::throwContactException(ret, "contacts_record_set_int()");
+    }
+
+    int address_book_id;
+    ret = contacts_db_insert_record(*contacts_record_ptr, &address_book_id);
+    if (CONTACTS_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ContactUtil::throwContactException(ret, "contacts_db_insert_record()");
+    }
+
+    address_book->setAddressBookId(static_cast<long>(address_book_id));
+}
+
+void ContactManager::removeAddressBook(long address_book_id)
+{
+    AddressBookPtr address_book = getAddressBook(address_book_id);
+    if (address_book->getIsUnified()) {
+        LOGE("Unified address book can not be deleted");
+        throw InvalidValuesException("Unified addresss book can not be deleted");
+    }
+
+    if (address_book->getAddressBookId() == AddressBook::DEFAULT_ADDRESS_BOOK_ID) {
+        LOGE("Default address book can not be deleted");
+        throw InvalidValuesException("Default address book can not be deleted");
+    }
+
+    int ret = contacts_db_delete_record(_contacts_address_book._uri,
+        static_cast<int>(address_book_id));
+    if (CONTACTS_ERROR_NONE != ret) {
+        LOGE("ret: %d", ret);
+        ContactUtil::throwContactException(ret, "contacts_db_delete_record()");
+    }
+}
+
+PersonPtr ContactManager::get(long person_id)
+{
+    int error_code = 0;
+    contacts_record_h contacts_record = NULL;
+
+    error_code = contacts_db_get_record(_contacts_person._uri, person_id,
+            &contacts_record);
+    if(CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException<NotFoundException>(error_code, "contacts_db_get_record()");
+    }
+
+    contacts_record_h_ptr contacts_record_ptr(&contacts_record, contactsDeleter);
+
+    PersonPtr person = PersonPtr(new (std::nothrow) Person());
+    if(!person) {
+        LOGE("Memory allocation error");
+        throw UnknownException("Memory allocation error");
+    }
+    person->importFromRecord(*contacts_record_ptr);
+
+    return person;
+}
+
+void ContactManager::update(PersonPtr person)
+{
+    int err = 0;
+
+    contacts_record_h contacts_record = NULL;
+
+    err = contacts_db_get_record(_contacts_person._uri, person->getId(), &contacts_record);
+    if (CONTACTS_ERROR_NONE != err || contacts_record == NULL) {
+        LOGE("ret: %d", err);
+        if (CONTACTS_ERROR_NO_DATA == err) {
+            ContactUtil::throwContactException<NotFoundException>(err, "contacts_db_get_record()");
+        }
+        ContactUtil::throwContactException(err, "contacts_db_get_record()");
+    }
+
+
+    contacts_record_h_ptr contacts_record_ptr(&contacts_record, contactsDeleter);
+    person->exportToRecord(*contacts_record_ptr);
+
+    err = contacts_db_update_record(*contacts_record_ptr);
+    if (err != CONTACTS_ERROR_NONE) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_db_update_record()");
+    }
+}
+
+gboolean ContactManager::batchOperationCallback(void *data)
+{
+    auto callback = static_cast<BatchOperationCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            callback->callSuccessCallback();
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Uknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* ContactManager::updateBatchThread(void* data)
+{
+    auto callback = static_cast<UpdateBatchCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    auto persons = callback->getPersons();
+    if (!persons) {
+        LOGE("persons is null");
+        return NULL;
+    }
+
+    try {
+        contacts_list_h contacts_list = NULL;
+
+        int error_code = contacts_list_create(&contacts_list);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_list_create()");
+        }
+
+        contacts_list_h_ptr contacts_list_ptr(&contacts_list,
+                contactsListDeleter);
+
+        auto it = persons->begin();
+        auto ite = persons->end();
+
+        for(; it != ite; ++it) {
+            PersonPtr person = *it;
+            contacts_record_h contacts_record = NULL;
+            error_code = contacts_db_get_record(_contacts_person._uri,
+                    person->getId(), &contacts_record);
+            if(CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException<NotFoundException>(error_code, "contacts_db_get_record()");
+            }
+
+            person->exportToRecord(contacts_record);
+
+            error_code = contacts_list_add(*contacts_list_ptr,
+                    contacts_record);
+            if(CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_list_add()");
+            }
+        }
+
+        error_code = contacts_db_update_records(*contacts_list_ptr);
+        if(CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_update_records()");
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+    }
+    catch (...) {
+        LOGE("updateBatchThread fails");
+        callback->setError("UnknownError", "updateBatchThread fails");
+    }
+
+    guint id = g_idle_add(batchOperationCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    return NULL;
+}
+
+void ContactManager::updateBatch(UpdateBatchCallbackData* callback)
+{
+    pthread_t thread;
+    if(pthread_create(&thread, NULL, updateBatchThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+    if(pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void ContactManager::remove(long person_id)
+{
+    int error_code = contacts_db_delete_record(_contacts_person._uri, person_id);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException<NotFoundException>(error_code, "contacts_db_delete_record()");
+    }
+}
+
+void* ContactManager::removeBatchThread(void *data)
+{
+    auto callback = static_cast<RemoveBatchCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    auto person_ids = callback->getPersonIds();
+    if (!person_ids) {
+        LOGE("persons is null");
+        return NULL;
+    }
+
+    try {
+        int size = person_ids->size();
+        int ids[size];
+        memset(ids, 0, sizeof(int)*size);
+        for(int i = 0; i < size; i++) {
+            ids[i] = (*person_ids)[i];
+            if(ids[i] < 0){
+                LOGE("id < 0");
+                throw InvalidValuesException("id < 0");
+            }
+        }
+        int error_code = contacts_db_delete_records(_contacts_person._uri,
+                ids, size);
+        if(CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_delete_records()");
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+    }
+    catch (...) {
+        LOGE("removeBatchThread fails");
+        callback->setError("UnknownError", "removeBatchThread fails");
+    }
+
+    guint id = g_idle_add(batchOperationCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    return NULL;
+}
+
+void ContactManager::removeBatch(RemoveBatchCallbackData *callback)
+{
+    pthread_t thread;
+    if(pthread_create(&thread, NULL, removeBatchThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+    if(pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+gboolean ContactManager::findCallback(void *data)
+{
+    auto callback = static_cast<FindCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            auto persons = callback->getPersons();
+            if (!persons) {
+                LOGE("persons is null");
+                return false;
+            }
+            JSObjectRef arr = ptrVectorToJSObjectArray<JSPerson, PersonPtr>(
+                    *persons, context);
+            callback->callSuccessCallback(arr);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Find callback fails");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* ContactManager::findThread(void *data)
+{
+    auto callback = static_cast<FindCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        PersonSearchEngine search_engine;
+
+        Tizen::SortModePtr sort_mode = callback->getSortMode();
+        Tizen::AbstractFilterPtr filter = callback->getFilter();
+
+        if (filter) {
+            search_engine.applyFilter(filter);
+        }
+        if (sort_mode) {
+            search_engine.applySortMode(sort_mode);
+        }
+
+        callback->setPersons(search_engine.find());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+    }
+    catch (...) {
+        LOGE("UnknownError");
+        callback->setError("UnknownError", "Find method fails");
+    }
+    guint id = g_idle_add(findCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    return NULL;
+}
+
+void ContactManager::find(FindCallbackData *callback)
+{
+    pthread_t thread;
+    if(pthread_create(&thread, NULL, findThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+    if(pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+long ContactManager::addChangeListener(PersonChangeCallbackPtr callback)
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    long listener_id = m_listener_counter++;
+
+    if(m_listeners.empty()) {
+        int error_code = contacts_db_add_changed_cb_with_info(_contacts_person._uri,
+                personsDBChangeCallback, static_cast<void*>(this));
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_add_changed_cb_with_info()");
+        }
+    }
+
+    m_listeners.insert(ListenerPair(listener_id, callback));
+
+    return listener_id;
+}
+
+void ContactManager::removeChangeListener(JSContextRef context, long watch_id)
+{
+    std::lock_guard<std::mutex> lock(m_mutex);
+    ListenersMap::iterator it = m_listeners.find(watch_id);
+
+    if (it != m_listeners.end()) {
+        JSContextRef global_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        if (it->second->getContext() != global_ctx) {
+            LOGE("No listener witch such id in current context");
+            throw NotFoundException("No listener with such id in current context");
+        }
+
+        it->second->setActive(false);
+        m_listeners.erase(it);
+
+        if(m_listeners.empty()) {
+            int error_code = contacts_db_remove_changed_cb_with_info(
+                    _contacts_person._uri,
+                    personsDBChangeCallback, static_cast<void*>(this));
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("%s", ContactUtil::getContactErrorString(error_code,
+                        "contacts_db_remove_changed_cb_with_info()").c_str());
+            }
+        }
+    }
+    else {
+        LOGE("No listener with id: %d", watch_id);
+        throw NotFoundException("No listener with such id");
+    }
+}
+
+gboolean ContactManager::changeCallbackFunc(void *data)
+{
+    auto hold = static_cast<PersonChangeListenerHolder*>(data);
+    if (!hold) {
+        LOGE("listener holder is null");
+        return false;
+    }
+
+    std::unique_ptr<PersonChangeListenerHolder> holder(hold);
+
+    auto callback = holder->callback;
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    try {
+        if (holder->added_persons) {
+            callback->onpersonsadded(*holder->added_persons);
+        } else if (holder->updated_persons) {
+            callback->onpersonsupdated(*holder->updated_persons);
+        } else if (holder->removed_ids) {
+            callback->onpersonsremoved(*holder->removed_ids);
+        } else {
+            LOGW("Callback called with no data");
+        }
+    }
+    catch (const Common::BasePlatformException &err) {
+        LOGE("Persons change listener failed: %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+
+    return false;
+}
+
+void ContactManager::personsDBChangeCallback(const char* view_uri, char* changes,
+        void* user_data)
+{
+    if (NULL == changes) {
+        LOGW("changes is NULL");
+        return;
+    }
+    if (strlen(changes) == 0) {
+        LOGW("changes is empty");
+        return;
+    }
+    if (NULL == user_data) {
+        LOGW("ContactManager pointer is NULL in user_data");
+        return;
+    }
+
+    LongVector added;
+    LongVector updated;
+    StringVector removed;
+
+    ContactManager *mgr = static_cast<ContactManager*>(user_data);
+
+    char* tmp = strdup(changes);
+
+    char* token = strtok(tmp, TOKEN_DELIMITER);
+    while (token) {
+        if (WrtDeviceApis::Commons::validate("^[0-9]+$", token,
+                WrtDeviceApis::Commons::VALIDATE_MATCH_FULL)) {
+            int type = atoi(token);
+            token = strtok(NULL, TOKEN_DELIMITER);
+            if (!token) {
+                break;
+            }
+            if (WrtDeviceApis::Commons::validate("^[0-9]+$", token,
+                    WrtDeviceApis::Commons::VALIDATE_MATCH_FULL)) {
+                int person_id = atoi(token);
+                switch(type) {
+                    case CONTACTS_CHANGE_INSERTED:
+                        added.push_back(person_id);
+                        break;
+                    case CONTACTS_CHANGE_UPDATED:
+                        updated.push_back(person_id);
+                        break;
+                    case CONTACTS_CHANGE_DELETED:
+                        removed.push_back(std::to_string(person_id));
+                        break;
+                }
+            }
+        }
+
+        token = strtok(NULL, TOKEN_DELIMITER);
+    }
+    free(tmp);
+
+    std::shared_ptr<PersonPtrVector> added_persons(new PersonPtrVector());
+    std::shared_ptr<PersonPtrVector> updated_persons(new PersonPtrVector());
+    std::shared_ptr<StringVector> removed_persons(new StringVector(removed));
+
+    auto it_a = added.begin();
+    auto ite_a = added.end();
+
+    for(; it_a != ite_a; ++it_a) {
+        try {
+            PersonPtr person = Person::getPersonById(*it_a);
+            added_persons->push_back(person);
+        }
+        catch (...) {
+            LOGW("Failed to get person");
+        }
+    }
+
+    auto it_u = updated.begin();
+    auto ite_u = updated.end();
+
+    for(; it_u != ite_u; ++it_u) {
+        try {
+            PersonPtr person = Person::getPersonById(*it_u);
+            updated_persons->push_back(person);
+        }
+        catch (...) {
+            LOGW("Failed to get person");
+        }
+    }
+
+    ListenersMap listeners;
+
+    {
+        std::lock_guard<std::mutex> lock(mgr->m_mutex);
+        listeners = mgr->m_listeners;
+    }
+
+    auto it_l = listeners.begin();
+    auto ite_l = listeners.end();
+
+    for(; it_l != ite_l; ++it_l) {
+        std::pair<long, PersonChangeCallbackPtr> cb = *it_l;
+
+        if(!added_persons->empty()) {
+            PersonChangeListenerHolder* holder =
+                    new(std::nothrow) PersonChangeListenerHolder();
+
+            holder->added_persons = added_persons;
+            holder->callback = cb.second;
+
+            if (!g_idle_add(changeCallbackFunc, holder)) {
+                LOGE("g_idle_add_fails");
+                delete holder;
+                holder = NULL;
+            }
+        }
+        if(!updated_persons->empty()) {
+            PersonChangeListenerHolder* holder =
+                    new(std::nothrow) PersonChangeListenerHolder();
+
+            holder->updated_persons = updated_persons;
+            holder->callback = cb.second;
+
+            if (!g_idle_add(changeCallbackFunc, holder)) {
+                LOGE("g_idle_add_fails");
+                delete holder;
+                holder = NULL;
+            }
+        }
+        if(!removed_persons->empty()) {
+            PersonChangeListenerHolder* holder =
+                    new(std::nothrow) PersonChangeListenerHolder();
+
+            holder->removed_ids = removed_persons;
+            holder->callback = cb.second;
+
+            if (!g_idle_add(changeCallbackFunc, holder)) {
+                LOGE("g_idle_add_fails");
+                delete holder;
+                holder = NULL;
+            }
+        }
+    }
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactManager.h b/src/Contact/ContactManager.h
new file mode 100644 (file)
index 0000000..ad6d7b8
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactManager.h
+ */
+
+#ifndef __TIZEN_CONTACT_CONTACT_MANAGER_H__
+#define __TIZEN_CONTACT_CONTACT_MANAGER_H__
+
+#include <string>
+#include <vector>
+#include <map>
+#include <mutex>
+#include <CallbackUserData.h>
+#include <SecurityAccessor.h>
+#include <glib.h>
+#include "Person.h"
+#include "PersonChangeCallback.h"
+#include "ContactRef.h"
+#include "AddressBook.h"
+#include "ContactManagerCallbackData.h"
+#include "PersonChangeCallback.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+typedef std::map<long, PersonChangeCallbackPtr> PersonChangeCallbackMap;
+typedef std::vector<long> LongVector;
+typedef std::vector<std::string> StringVector;
+
+class ContactManager : public Common::SecurityAccessor
+{
+public:
+    static ContactManager& getInstance();
+
+    virtual ~ContactManager();
+
+    void getAddressBooks(GetAddressBooksCallbackData* callback);
+    AddressBookPtr getUnifiedAddressBook();
+    AddressBookPtr getDefaultAddressBook();
+    AddressBookPtr getAddressBook(long address_book_id);
+    void addAddressBook(AddressBookPtr address_book);
+    void removeAddressBook(long address_book_id);
+    PersonPtr get(long person_id);
+    void update(PersonPtr person);
+    void updateBatch(UpdateBatchCallbackData* callback);
+    void remove(long person_id);
+    void removeBatch(RemoveBatchCallbackData* callback);
+    void find(FindCallbackData *callback);
+    long addChangeListener(PersonChangeCallbackPtr callback);
+    void removeChangeListener(JSContextRef context, long watch_id);
+
+private:
+    typedef std::pair<long, PersonChangeCallbackPtr> ListenerPair;
+
+    ContactManager();
+    ContactManager(const ContactManager&);
+    ContactManager& operator=(const ContactManager&);
+
+    long m_listener_counter;
+    typedef std::map<long, PersonChangeCallbackPtr> ListenersMap;
+    ListenersMap m_listeners;
+
+    AddressBookPtr m_unified_address_book;
+
+    static void personsDBChangeCallback(const char* view_uri, char* changes, void* user_data);
+    static gboolean getAddressBooksCallback(void *data);
+    static void* getAddressBooksThread(void *data);
+    static gboolean batchOperationCallback(void *data);
+    static void* updateBatchThread(void *data);
+    static void* removeBatchThread(void *data);
+    static void* findThread(void *data);
+    static gboolean findCallback(void *data);
+    static gboolean changeCallbackFunc(void *data);
+
+    std::mutex m_mutex;
+
+    struct PersonChangeListenerHolder {
+        PersonChangeCallbackPtr callback;
+        std::shared_ptr<PersonPtrVector> added_persons;
+        std::shared_ptr<PersonPtrVector> updated_persons;
+        std::shared_ptr<StringVector> removed_ids;
+    };
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif //__TIZEN_CONTACT_CONTACT_MANAGER_H__
diff --git a/src/Contact/ContactManagerCallbackData.cpp b/src/Contact/ContactManagerCallbackData.cpp
new file mode 100644 (file)
index 0000000..ca2fa18
--- /dev/null
@@ -0,0 +1,158 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactManagerCallbacks.cpp
+ */
+
+#include "ContactManagerCallbackData.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+BatchOperationCallbackData::BatchOperationCallbackData(JSContextRef globalCtx):
+        Common::CallbackUserData(globalCtx),
+        m_is_error(false)
+{
+}
+
+BatchOperationCallbackData::~BatchOperationCallbackData()
+{
+}
+
+void BatchOperationCallbackData::setError(const std::string &err_name,
+        const std::string &err_message)
+{
+    m_err_name = err_name;
+    m_err_message = err_message;
+    m_is_error = true;
+}
+
+bool BatchOperationCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+std::string BatchOperationCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string BatchOperationCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+UpdateBatchCallbackData::UpdateBatchCallbackData(JSContextRef globalCtx):
+        BatchOperationCallbackData(globalCtx)
+{
+}
+
+UpdateBatchCallbackData::~UpdateBatchCallbackData()
+{
+}
+
+void UpdateBatchCallbackData::setPersons(std::shared_ptr<PersonPtrVector> persons)
+{
+    m_persons = persons;
+}
+
+std::shared_ptr<PersonPtrVector> UpdateBatchCallbackData::getPersons() const
+{
+    return m_persons;
+}
+
+RemoveBatchCallbackData::RemoveBatchCallbackData(JSContextRef globalCtx):
+        BatchOperationCallbackData(globalCtx)
+{
+}
+
+RemoveBatchCallbackData::~RemoveBatchCallbackData()
+{
+}
+
+void RemoveBatchCallbackData::setPersonIds(std::shared_ptr<LongVector> person_ids)
+{
+    m_person_ids = person_ids;
+}
+
+std::shared_ptr<LongVector> RemoveBatchCallbackData::getPersonIds() const
+{
+    return m_person_ids;
+}
+
+GetAddressBooksCallbackData::GetAddressBooksCallbackData(JSContextRef globalCtx):
+        BatchOperationCallbackData(globalCtx)
+{
+}
+
+GetAddressBooksCallbackData::~GetAddressBooksCallbackData()
+{
+}
+
+void GetAddressBooksCallbackData::setAddressBooks(
+        std::shared_ptr<AddressBookPtrVector> address_books)
+{
+    m_address_books = address_books;
+}
+
+std::shared_ptr<AddressBookPtrVector> GetAddressBooksCallbackData::getAddressBooks() const
+{
+    return m_address_books;
+}
+
+FindCallbackData::FindCallbackData(JSContextRef globalCtx):
+        BatchOperationCallbackData(globalCtx)
+{
+}
+
+FindCallbackData::~FindCallbackData()
+{
+}
+
+void FindCallbackData::setFilter(Tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+Tizen::AbstractFilterPtr FindCallbackData::getFilter() const
+{
+    return m_filter;
+}
+
+void FindCallbackData::setSortMode(Tizen::SortModePtr sort_mode)
+{
+    m_sort_mode = sort_mode;
+}
+
+Tizen::SortModePtr FindCallbackData::getSortMode() const
+{
+    return m_sort_mode;
+}
+
+void FindCallbackData::setPersons(std::shared_ptr<PersonPtrVector> persons)
+{
+    m_persons = persons;
+}
+
+std::shared_ptr<PersonPtrVector> FindCallbackData::getPersons() const
+{
+    return m_persons;
+}
+
+}
+}
diff --git a/src/Contact/ContactManagerCallbackData.h b/src/Contact/ContactManagerCallbackData.h
new file mode 100644 (file)
index 0000000..37dcb12
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactManagerCallbacks.h
+ */
+
+#ifndef __CONTACT_MANAGER_CALLBACK_DATA_H__
+#define __CONTACT_MANAGER_CALLBACK_DATA_H__
+
+#include <CallbackUserData.h>
+#include <memory>
+#include "Person.h"
+#include "AddressBook.h"
+#include <AbstractFilter.h>
+#include <SortMode.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+typedef std::vector<long> LongVector;
+
+class BatchOperationCallbackData : public Common::CallbackUserData
+{
+public:
+    BatchOperationCallbackData(JSContextRef globalCtx);
+    virtual ~BatchOperationCallbackData();
+
+    void setError(const std::string &err_name,
+            const std::string &err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+private:
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+};
+
+class UpdateBatchCallbackData : public BatchOperationCallbackData
+{
+public:
+    UpdateBatchCallbackData(JSContextRef globalCtx);
+    virtual ~UpdateBatchCallbackData();
+
+    void setPersons(std::shared_ptr<PersonPtrVector> persons);
+    std::shared_ptr<PersonPtrVector> getPersons() const;
+
+private:
+    std::shared_ptr<PersonPtrVector> m_persons;
+};
+
+class RemoveBatchCallbackData : public BatchOperationCallbackData
+{
+public:
+    RemoveBatchCallbackData(JSContextRef globalCtx);
+    virtual ~RemoveBatchCallbackData();
+
+    void setPersonIds(std::shared_ptr<LongVector> person_ids);
+    std::shared_ptr<LongVector> getPersonIds() const;
+
+private:
+    std::shared_ptr<LongVector> m_person_ids;
+};
+
+class GetAddressBooksCallbackData : public BatchOperationCallbackData
+{
+public:
+    GetAddressBooksCallbackData(JSContextRef globalCtx);
+    virtual ~GetAddressBooksCallbackData();
+
+    void setAddressBooks(std::shared_ptr<AddressBookPtrVector> address_books);
+    std::shared_ptr<AddressBookPtrVector> getAddressBooks() const;
+
+private:
+    std::shared_ptr<AddressBookPtrVector> m_address_books;
+};
+
+class FindCallbackData : public BatchOperationCallbackData
+{
+public:
+    FindCallbackData(JSContextRef globalCtx);
+    virtual ~FindCallbackData();
+
+    void setFilter(Tizen::AbstractFilterPtr filter);
+    Tizen::AbstractFilterPtr getFilter() const;
+
+    void setSortMode(Tizen::SortModePtr sort_mode);
+    Tizen::SortModePtr getSortMode() const;
+
+    void setPersons(std::shared_ptr<PersonPtrVector> persons);
+    std::shared_ptr<PersonPtrVector> getPersons() const;
+
+private:
+    Tizen::AbstractFilterPtr m_filter;
+    Tizen::SortModePtr m_sort_mode;
+    std::shared_ptr<PersonPtrVector> m_persons;
+};
+
+}
+}
+
+#endif
diff --git a/src/Contact/ContactName.cpp b/src/Contact/ContactName.cpp
new file mode 100644 (file)
index 0000000..9f23114
--- /dev/null
@@ -0,0 +1,376 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include "ContactName.h"
+#include "ContactUtil.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+ContactName::ContactName()
+{
+    m_prefix = "";
+    m_suffix = "";
+    m_first_name = "";
+    m_middle_name = "";
+    m_last_name = "";
+    m_phonetic_first_name = "";
+    m_phonetic_last_name = "";
+    m_display_name = "";
+    for (int i = 0; i < CONTACT_NAME_NUMBER_OF_ATTRIBUTES; i++) {
+        m_is_set[i] = false;
+    }
+}
+
+ContactName::~ContactName()
+{
+
+}
+
+std::string ContactName::getAttribute(ContactNameAttribute attribute) const
+{
+    switch (attribute) {
+        case CONTACT_NAME_ATTRIBUTE_PREFIX:
+            return m_prefix;
+        case CONTACT_NAME_ATTRIBUTE_SUFFIX:
+            return m_suffix;
+        case CONTACT_NAME_ATTRIBUTE_FIRST_NAME:
+            return m_first_name;
+        case CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME:
+            return m_middle_name;
+        case CONTACT_NAME_ATTRIBUTE_LAST_NAME:
+            return m_last_name;
+        case CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME:
+            return m_phonetic_first_name;
+        case CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME:
+            return m_phonetic_middle_name;
+        case CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME:
+            return m_phonetic_last_name;
+        case CONTACT_NAME_ATTRIBUTE_DISPLAY_NAME:
+            return m_display_name;
+        default:
+            throw DeviceAPI::Common::NotSupportedException("Not an attribute");
+    }
+}
+
+void ContactName::setAttribute(ContactNameAttribute attribute,
+        const std::string &value)
+{
+    switch (attribute) {
+        case CONTACT_NAME_ATTRIBUTE_PREFIX:
+            m_is_set[CONTACT_NAME_ATTRIBUTE_PREFIX] = true;
+            m_prefix = value;
+            break;
+        case CONTACT_NAME_ATTRIBUTE_SUFFIX:
+            m_is_set[CONTACT_NAME_ATTRIBUTE_SUFFIX] = true;
+            m_suffix = value;
+            break;
+        case CONTACT_NAME_ATTRIBUTE_FIRST_NAME:
+            m_is_set[CONTACT_NAME_ATTRIBUTE_FIRST_NAME] = true;
+            m_first_name = value;
+            break;
+        case CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME:
+            m_is_set[CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME] = true;
+            m_middle_name = value;
+            break;
+        case CONTACT_NAME_ATTRIBUTE_LAST_NAME:
+            m_is_set[CONTACT_NAME_ATTRIBUTE_LAST_NAME] = true;
+            m_last_name = value;
+            break;
+        case CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME:
+            m_is_set[CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME] = true;
+            m_phonetic_first_name = value;
+            break;
+        case CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME:
+            m_is_set[CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME] = true;
+            m_phonetic_middle_name = value;
+            break;
+        case CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME:
+            m_is_set[CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME] = true;
+            m_phonetic_last_name = value;
+            break;
+        case CONTACT_NAME_ATTRIBUTE_DISPLAY_NAME:
+            m_is_set[CONTACT_NAME_ATTRIBUTE_DISPLAY_NAME] = true;
+            m_display_name = value;
+            break;
+        default:
+            throw DeviceAPI::Common::NotSupportedException("Not an attribute");
+    }
+}
+
+bool ContactName::isSet(ContactNameAttribute attribute) const
+{
+    return m_is_set[attribute];
+}
+
+void ContactName::setIsSet(ContactNameAttribute attribute, bool is_set)
+{
+    m_is_set[attribute] = is_set;
+}
+
+JSValueRef ContactName::getJSNicknames(JSContextRef global_ctx)
+{
+    return m_nicknames.getJSArray(global_ctx);
+}
+
+std::vector<std::string> ContactName::getNicknames() const
+{
+    return m_nicknames;
+}
+
+void ContactName::setNicknames(const std::vector<std::string> &nicknames)
+{
+    m_is_set[CONTACT_NAME_ATTRIBUTE_NICKNAMES] = true;
+    m_nicknames = nicknames;
+}
+
+void ContactName::checkDisplayName()
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_name_display_order_e display_order = CONTACTS_NAME_DISPLAY_ORDER_FIRSTLAST;
+    err = contacts_setting_get_name_display_order(&display_order);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_setting_get_name_display_order()");
+    }
+
+    switch (display_order) {
+        case CONTACTS_NAME_DISPLAY_ORDER_LASTFIRST:
+            setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_DISPLAY_NAME,
+                    m_last_name + ", " + m_first_name);
+            break;
+
+        default:
+            setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_DISPLAY_NAME,
+                    m_first_name + " " + m_last_name);
+            break;
+    }
+}
+
+void ContactName::importFromContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    if (!contacts_record) {
+        LOGW("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+    int count = 0;
+    err = contacts_record_get_child_record_count(contacts_record,
+            _contacts_contact.name, &count);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_get_child_record_count()");
+    }
+
+    if (count > 1) {
+        LOGW("More than one ContactName for one Contact");
+        throw Common::UnknownException("More than one ContactName for one Contact");
+    }
+    contacts_record_h contact_name = NULL;
+    err = contacts_record_get_child_record_at_p(contacts_record,
+            _contacts_contact.name, 0, &contact_name);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_get_child_record_at_p()");
+    }
+
+    //Documentation says:
+    //  child_record MUST NOT be released by you.
+    //  It is released when the parent record handle is destroyed.
+    //so it won't be protected by unique_ptr.
+
+    char *char_value = NULL;
+
+    ContactUtil::getStrFromRecord(contact_name, _contacts_name.prefix,
+            &char_value);
+    if (char_value) {
+        setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PREFIX,
+                char_value);
+    }
+
+    ContactUtil::getStrFromRecord(contact_name, _contacts_name.suffix,
+            &char_value);
+    if (char_value) {
+        setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_SUFFIX,
+                char_value);
+    }
+
+    ContactUtil::getStrFromRecord(contact_name, _contacts_name.first,
+            &char_value);
+    if (char_value) {
+        setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_FIRST_NAME,
+                char_value);
+    }
+
+    ContactUtil::getStrFromRecord(contact_name, _contacts_name.addition,
+            &char_value);
+    if (char_value) {
+        setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME,
+                char_value);
+    }
+
+    ContactUtil::getStrFromRecord(contact_name, _contacts_name.last,
+            &char_value);
+    if (char_value) {
+        setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_LAST_NAME,
+                char_value);
+    }
+
+    ContactUtil::getStrFromRecord(contact_name, _contacts_name.phonetic_first,
+            &char_value);
+    if (char_value) {
+        setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME,
+                char_value);
+    }
+
+    ContactUtil::getStrFromRecord(contact_name, _contacts_name.phonetic_middle,
+            &char_value);
+    if (char_value) {
+        setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME,
+                char_value);
+    }
+
+    ContactUtil::getStrFromRecord(contact_name, _contacts_name.phonetic_last,
+            &char_value);
+    if (char_value) {
+        setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME,
+                char_value);
+    }
+
+    err = contacts_record_get_child_record_count(contacts_record,
+            _contacts_contact.nickname, &count);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_get_child_record_count()");
+    }
+
+    std::vector<std::string> nicknames;
+    for (int i = 0; i < count; i++) {
+        contacts_record_h nickname = NULL;
+        err = contacts_record_get_child_record_at_p(contacts_record,
+                _contacts_contact.nickname, i, &nickname);
+        if(CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_record_get_child_record_at_p()");
+        }
+        ContactUtil::getStrFromRecord(nickname,
+                _contacts_nickname.name, &char_value);
+
+        if (char_value) {
+            nicknames.push_back(char_value);
+        }
+    }
+    setNicknames(nicknames);
+
+    checkDisplayName();
+}
+
+void ContactName::exportToContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGW("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    contacts_record_h contact_name = NULL;
+    err = contacts_record_create(_contacts_name._uri, &contact_name);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+
+    //contact_name starts to be protected by unique_ptr
+    contacts_record_h_ptr contacts_name_ptr(&contact_name, contactsDeleter);
+
+    if (isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PREFIX)) {
+        ContactUtil::setStrInRecord(*contacts_name_ptr, _contacts_name.prefix,
+                getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PREFIX).c_str());
+    }
+    if (isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_SUFFIX)) {
+        ContactUtil::setStrInRecord(*contacts_name_ptr, _contacts_name.suffix,
+                getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_SUFFIX).c_str());
+    }
+    if (isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_FIRST_NAME)) {
+        ContactUtil::setStrInRecord(*contacts_name_ptr, _contacts_name.first,
+                getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_FIRST_NAME).c_str());
+    }
+    if (isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME)) {
+        ContactUtil::setStrInRecord(*contacts_name_ptr, _contacts_name.addition,
+                getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME).c_str());
+    }
+    if (isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_LAST_NAME)) {
+        ContactUtil::setStrInRecord(*contacts_name_ptr, _contacts_name.last,
+                getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_LAST_NAME).c_str());
+    }
+    if (isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME)) {
+        ContactUtil::setStrInRecord(*contacts_name_ptr, _contacts_name.phonetic_first,
+                getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME).c_str());
+    }
+    if (isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME)) {
+        ContactUtil::setStrInRecord(*contacts_name_ptr, _contacts_name.phonetic_middle,
+                getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME).c_str());
+    }
+    if (isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME)) {
+        ContactUtil::setStrInRecord(*contacts_name_ptr, _contacts_name.phonetic_last,
+                getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME).c_str());
+    }
+
+    //contact_name is being added as a child to contacts_record
+    //and in future will be destroyed by contacts_record's contactsDeleter
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.name, *contacts_name_ptr);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    //and now unique_ptr can be released - contacts_name is protected
+    //by its parent (contacts_record)
+    contacts_name_ptr.release();
+
+    ContactUtil::clearAllContactRecord(contacts_record,_contacts_contact.nickname);
+    size_t size = m_nicknames.size();
+    for(size_t i = 0; i < size; i++){
+        contacts_record_h nickname = NULL;
+        err = contacts_record_create(_contacts_nickname._uri, &nickname);
+        if(CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_record_create()");
+        }
+
+        contacts_record_h_ptr nickname_ptr(&nickname, contactsDeleter);
+        std::vector<std::string> nicknames = getNicknames();
+
+        ContactUtil::setStrInRecord(*nickname_ptr, _contacts_nickname.name,
+                nicknames.at(i).c_str());
+        err = contacts_record_add_child_record(contacts_record,
+                _contacts_contact.nickname, *nickname_ptr);
+        if(CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+        }
+        nickname_ptr.release();
+    }
+
+    checkDisplayName();
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactName.h b/src/Contact/ContactName.h
new file mode 100644 (file)
index 0000000..e7271c7
--- /dev/null
@@ -0,0 +1,85 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_CONTACT_NAME_H__
+#define __TIZEN_CONTACT_CONTACT_NAME_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <contacts.h>
+
+#include <JSVector.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactName;
+typedef std::shared_ptr<ContactName> ContactNamePtr;
+
+enum ContactNameAttribute{
+    CONTACT_NAME_ATTRIBUTE_PREFIX,
+    CONTACT_NAME_ATTRIBUTE_SUFFIX,
+    CONTACT_NAME_ATTRIBUTE_FIRST_NAME,
+    CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME,
+    CONTACT_NAME_ATTRIBUTE_LAST_NAME,
+    CONTACT_NAME_ATTRIBUTE_NICKNAMES,
+    CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME,
+    CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME,
+    CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME,
+    CONTACT_NAME_ATTRIBUTE_DISPLAY_NAME,
+    CONTACT_NAME_NUMBER_OF_ATTRIBUTES
+};
+
+class ContactName {
+public:
+    ContactName();
+    virtual ~ContactName();
+
+    std::string getAttribute(ContactNameAttribute attribute) const;
+    void setAttribute(ContactNameAttribute attribute,
+            const std::string &value);
+    bool isSet(ContactNameAttribute attribute) const;
+    void setIsSet(ContactNameAttribute attribute, bool is_set);
+
+    JSValueRef getJSNicknames(JSContextRef global_ctx);
+    std::vector<std::string> getNicknames() const;
+    void setNicknames(const std::vector<std::string> &nicknames);
+
+    void importFromContactsRecord(contacts_record_h contacts_record);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+
+private:
+    std::string m_prefix;
+    std::string m_suffix;
+    std::string m_first_name;
+    std::string m_middle_name;
+    std::string m_last_name;
+    Common::JSStringVector m_nicknames;
+    std::string m_phonetic_first_name;
+    std::string m_phonetic_middle_name;
+    std::string m_phonetic_last_name;
+    std::string m_display_name;
+    bool m_is_set[ContactNameAttribute::CONTACT_NAME_NUMBER_OF_ATTRIBUTES];
+
+    void checkDisplayName();
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif
diff --git a/src/Contact/ContactOrganization.cpp b/src/Contact/ContactOrganization.cpp
new file mode 100644 (file)
index 0000000..ce85ff5
--- /dev/null
@@ -0,0 +1,274 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactOrganization.cpp
+ */
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "ContactUtil.h"
+#include "ContactOrganization.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+ContactOrganization::ContactOrganization()
+{
+    m_name = "";
+    m_is_name_set = false;
+    m_department = "";
+    m_is_department_set = false;
+    m_title = "";
+    m_is_title_set = false;
+    m_role = "";
+    m_is_role_set = false;
+    m_logo_uri = "";
+    m_is_logo_uri_set = false;
+}
+
+ContactOrganization::~ContactOrganization()
+{
+
+}
+
+std::string ContactOrganization::getName() const
+{
+    return m_name;
+}
+
+bool ContactOrganization::isNameSet() const
+{
+    return m_is_name_set;
+}
+
+void ContactOrganization::setName(const std::string &value)
+{
+    m_name = value;
+    m_is_name_set = true;
+}
+
+void ContactOrganization::unsetName()
+{
+    m_is_name_set = false;
+}
+
+std::string ContactOrganization::getDepartment() const
+{
+    return m_department;
+}
+
+bool ContactOrganization::isDepartmentSet() const
+{
+    return m_is_department_set;
+}
+
+void ContactOrganization::setDepartment(const std::string &value)
+{
+    m_department = value;
+    m_is_department_set = true;
+}
+
+void ContactOrganization::unsetDepartment()
+{
+    m_is_department_set = false;
+}
+
+std::string ContactOrganization::getTitle() const
+{
+    return m_title;
+}
+
+bool ContactOrganization::isTitleSet() const
+{
+    return m_is_title_set;
+}
+
+void ContactOrganization::setTitle(const std::string &value)
+{
+    m_title = value;
+    m_is_title_set = true;
+}
+
+void ContactOrganization::unsetTitle()
+{
+    m_is_title_set = false;
+}
+
+std::string ContactOrganization::getRole() const
+{
+    return m_role;
+}
+
+bool ContactOrganization::isRoleSet() const
+{
+    return m_is_role_set;
+}
+
+void ContactOrganization::setRole(const std::string &value)
+{
+    m_role = value;
+    m_is_role_set = true;
+}
+
+void ContactOrganization::unsetRole()
+{
+    m_is_role_set = false;
+}
+
+std::string ContactOrganization::getLogoURI() const
+{
+    return m_logo_uri;
+}
+
+bool ContactOrganization::isLogoURISet() const
+{
+    return m_is_logo_uri_set;
+}
+
+void ContactOrganization::setLogoURI(const std::string &value)
+{
+    m_logo_uri = value;
+    m_is_logo_uri_set = true;
+}
+
+void ContactOrganization::unsetLogoURI()
+{
+    m_is_logo_uri_set = false;
+}
+
+void ContactOrganization::importFromContactsRecord(contacts_record_h contacts_record,
+        unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_get_child_record_at_p(contacts_record,
+            _contacts_contact.company, index, &child_record);
+    if ( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err ) {
+        LOGW("Failed contacts_record_get_child_record_at_p(): %s, %d",
+                ContactUtil::getContactErrorMessage(err).c_str(), err);
+        return;
+    }
+
+    char* char_value = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_company.name, &char_value);
+    if (!char_value) {
+        unsetName();
+    }
+    else {
+        setName(std::string(char_value));
+    }
+
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_company.department, &char_value);
+    if (!char_value) {
+        unsetDepartment();
+    }
+    else {
+        setDepartment(std::string(char_value));
+    }
+
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_company.job_title, &char_value);
+    if(!char_value){
+        unsetTitle();
+    } else {
+        setTitle(std::string(char_value));
+    }
+
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_company.role, &char_value);
+    if(!char_value){
+        unsetRole();
+    } else {
+        setRole(std::string(char_value));
+    }
+
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_company.logo, &char_value);
+    if(!char_value){
+        unsetLogoURI();
+    } else {
+        setLogoURI(std::string(char_value));
+    }
+}
+
+void ContactOrganization::exportToContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h organization_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_create(_contacts_company._uri, &organization_record);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&organization_record, contactsDeleter);
+
+    if (isNameSet()) {
+        ContactUtil::setStrInRecord(organization_record,
+                _contacts_company.name, getName().c_str());
+    }
+
+    if(isDepartmentSet()){
+        ContactUtil::setStrInRecord(organization_record,
+                _contacts_company.department,
+                getDepartment().c_str());
+    }
+
+    if (isTitleSet()) {
+        ContactUtil::setStrInRecord(organization_record,
+                _contacts_company.job_title,
+                getTitle().c_str());
+    }
+
+    if (isRoleSet()) {
+        ContactUtil::setStrInRecord(organization_record,
+                _contacts_company.role,
+                getRole().c_str());
+    }
+
+    if (isLogoURISet()) {
+          std::string path = ContactUtil::convertUriToPath(getLogoURI());
+          ContactUtil::setStrInRecord(organization_record,
+                  _contacts_company.logo,
+                  path.c_str());
+    }
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.company, organization_record);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    record.release();
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactOrganization.h b/src/Contact/ContactOrganization.h
new file mode 100644 (file)
index 0000000..e4e61fe
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactOrganization.h
+ */
+
+#ifndef __TIZEN_CONTACT_CONTACT_ORGANIZATION_H__
+#define __TIZEN_CONTACT_CONTACT_ORGANIZATION_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+#include "contacts.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactOrganization;
+typedef std::shared_ptr<ContactOrganization> ContactOrganizationPtr;
+typedef std::vector<ContactOrganizationPtr> ContactOrganizationPtrVector;
+
+class ContactOrganization {
+public:
+    ContactOrganization();
+    virtual ~ContactOrganization();
+
+    std::string getName() const;
+    bool isNameSet() const;
+    void setName(const std::string &);
+    void unsetName();
+
+    std::string getDepartment() const;
+    bool isDepartmentSet() const;
+    void setDepartment(const std::string &);
+    void unsetDepartment();
+
+    std::string getTitle() const;
+    bool isTitleSet() const;
+    void setTitle(const std::string &);
+    void unsetTitle();
+
+    std::string getRole() const;
+    bool isRoleSet() const;
+    void setRole(const std::string &);
+    void unsetRole();
+
+    std::string getLogoURI() const;
+    bool isLogoURISet() const;
+    void setLogoURI(const std::string &);
+    void unsetLogoURI();
+
+    void importFromContactsRecord(contacts_record_h contacts_record,
+            unsigned int index);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+
+private:
+    std::string m_name;
+    bool m_is_name_set;
+    std::string m_department;
+    bool m_is_department_set;
+    std::string m_title;
+    bool m_is_title_set;
+    std::string m_role;
+    bool m_is_role_set;
+    std::string m_logo_uri;
+    bool m_is_logo_uri_set;
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_CONTACT_ORGANIZATION_H__
diff --git a/src/Contact/ContactPhoneNumber.cpp b/src/Contact/ContactPhoneNumber.cpp
new file mode 100644 (file)
index 0000000..21e95c5
--- /dev/null
@@ -0,0 +1,294 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <PlatformException.h>
+#include <Logger.h>
+#include "ContactUtil.h"
+#include "ContactPhoneNumber.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+ContactPhoneNumber::ContactPhoneNumber()
+{
+    m_phone_number = "";
+    m_is_default = false;
+    m_label = "";
+    m_is_label_set = false;
+    m_types.push_back(ContactUtil::CONTACT_TYPE_VOICE);
+}
+
+ContactPhoneNumber::~ContactPhoneNumber()
+{
+
+}
+
+std::string ContactPhoneNumber::getPhoneNumber()
+{
+    return m_phone_number;
+}
+
+void ContactPhoneNumber::setPhoneNumber(const std::string &phone_number)
+{
+    m_phone_number = phone_number;
+}
+
+bool ContactPhoneNumber::getIsDefault()
+{
+    return m_is_default;
+}
+
+void ContactPhoneNumber::setIsDefault(bool is_default)
+{
+    m_is_default = is_default;
+}
+
+std::vector<std::string> ContactPhoneNumber::getTypes()
+{
+    return m_types;
+}
+
+JSValueRef ContactPhoneNumber::getJSTypes(JSContextRef global_ctx)
+{
+    return m_types.getJSArray(global_ctx);
+}
+
+void ContactPhoneNumber::setTypes(const std::vector<std::string> &types)
+{
+    m_types = types;
+}
+
+void ContactPhoneNumber::importFromContactsRecord(contacts_record_h contacts_record,
+        unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_get_child_record_at_p(contacts_record,
+            _contacts_contact.number, index, &child_record);
+    if ( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err ) {
+        LOGW("%s", ContactUtil::getContactErrorString(err, "contacts_record_get_child_record_at_p()").c_str());
+        return;
+    }
+
+    char* phone = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_number.number, &phone);
+    if(!phone){
+        return;
+    }
+
+    m_phone_number = std::string(phone);
+
+    bool is_default = false;
+    ContactUtil::getBoolFromRecord(child_record,
+            _contacts_number.is_default, &is_default);
+    m_is_default = is_default;
+
+    int type = 0;
+       ContactUtil::getIntFromRecord(child_record,
+               _contacts_number.type, &type);
+
+    m_types.clear();
+    if (type & CONTACTS_NUMBER_TYPE_HOME) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_HOME);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_WORK) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_WORK);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_VOICE) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_VOICE);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_FAX) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_FAX);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_MSG) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_MSG);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_CELL) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_CELL);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_PAGER) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_PAGER);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_BBS) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_BBS);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_MODEM) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_MODEM);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_CAR) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_CAR);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_ISDN) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_ISDN);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_VIDEO) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_VIDEO);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_PCS) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_PCS);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_ASSISTANT) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_ASSISTANT);
+    }
+    if (type & CONTACTS_NUMBER_TYPE_CUSTOM) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_CUSTOM);
+    }
+    if (!type) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_OTHER);
+    }
+
+    if (0 == m_types.size()) {
+        m_types.push_back(ContactUtil::CONTACT_TYPE_VOICE);
+    }
+
+    char* label = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_number.label, &label);
+    if (label) {
+        setLabel(std::string(label));
+    }
+}
+
+void ContactPhoneNumber::exportToContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h phone_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_create(_contacts_number._uri, &phone_record);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&phone_record, contactsDeleter);
+
+    ContactUtil::setStrInRecord(phone_record,
+            _contacts_number.number,
+            getPhoneNumber().c_str());
+
+    ContactUtil::setBoolInRecord(phone_record,
+            _contacts_number.is_default,
+            getIsDefault());
+
+    int type_to_set = 0;
+    auto types = getTypes();
+    for (size_t i = 0; i < types.size(); i++) {
+        switch (ContactUtil::stringToContactPhoneNumberType(types[i])) {
+            case CONTACT_PHONE_NUMBER_TYPE_HOME:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_HOME;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_WORK:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_WORK;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_FAX:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_FAX;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_MSG:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_MSG;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_CELL:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_CELL;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_PAGER:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_PAGER;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_BBS:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_BBS;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_MODEM:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_MODEM;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_CAR:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_CAR;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_ISDN:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_ISDN;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_VIDEO:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_VIDEO;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_PCS:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_PCS;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_ASSISTANT:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_ASSISTANT;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_CUSTOM:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_CUSTOM;
+                break;
+            case CONTACT_PHONE_NUMBER_TYPE_OTHER:
+                type_to_set = 0;
+                break;
+            default:
+                type_to_set = type_to_set | CONTACTS_NUMBER_TYPE_VOICE;
+                break;
+        }
+        if (!type_to_set) {
+            break;
+        }
+    }
+
+    ContactUtil::setIntInRecord(phone_record,_contacts_number.type,
+            type_to_set);
+
+    if (isLabelSet()) {
+        ContactUtil::setStrInRecord(phone_record,_contacts_number.label,
+                getLabel().c_str());
+    }
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.number, phone_record);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    record.release();
+}
+
+bool ContactPhoneNumber::isLabelSet() const
+{
+    return m_is_label_set;
+}
+
+std::string ContactPhoneNumber::getLabel() const
+{
+    return m_label;
+}
+
+void ContactPhoneNumber::setLabel(std::string label)
+{
+    m_label = label;
+    m_is_label_set = true;
+}
+
+void ContactPhoneNumber::unsetLabel()
+{
+    m_is_label_set = false;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactPhoneNumber.h b/src/Contact/ContactPhoneNumber.h
new file mode 100644 (file)
index 0000000..fba47a5
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_CONTACT_PHONE_NUMBER_H__
+#define __TIZEN_CONTACT_CONTACT_PHONE_NUMBER_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <JSVector.h>
+#include <contacts.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactPhoneNumber;
+typedef std::shared_ptr<ContactPhoneNumber> ContactPhoneNumberPtr;
+typedef std::vector<ContactPhoneNumberPtr> ContactPhoneNumberPtrVector;
+
+enum ContactPhoneNumberType {
+    CONTACT_PHONE_NUMBER_TYPE_WORK,
+    CONTACT_PHONE_NUMBER_TYPE_HOME,
+    CONTACT_PHONE_NUMBER_TYPE_VOICE,
+    CONTACT_PHONE_NUMBER_TYPE_FAX,
+    CONTACT_PHONE_NUMBER_TYPE_MSG,
+    CONTACT_PHONE_NUMBER_TYPE_CELL,
+    CONTACT_PHONE_NUMBER_TYPE_PAGER,
+    CONTACT_PHONE_NUMBER_TYPE_BBS,
+    CONTACT_PHONE_NUMBER_TYPE_MODEM,
+    CONTACT_PHONE_NUMBER_TYPE_CAR,
+    CONTACT_PHONE_NUMBER_TYPE_ISDN,
+    CONTACT_PHONE_NUMBER_TYPE_VIDEO,
+    CONTACT_PHONE_NUMBER_TYPE_PCS,
+    CONTACT_PHONE_NUMBER_TYPE_ASSISTANT,
+    CONTACT_PHONE_NUMBER_TYPE_OTHER,
+    CONTACT_PHONE_NUMBER_TYPE_CUSTOM
+};
+
+typedef std::vector<ContactPhoneNumberType> ContactPhoneNumberTypeVector;
+
+class ContactPhoneNumber {
+
+public:
+    ContactPhoneNumber();
+    virtual ~ContactPhoneNumber();
+
+    std::string getPhoneNumber();
+    void setPhoneNumber(const std::string &phone_number);
+    bool getIsDefault();
+    void setIsDefault(bool is_default);
+    std::vector<std::string> getTypes();
+    void setTypes(const std::vector<std::string> &types);
+    JSValueRef getJSTypes(JSContextRef global_ctx);
+    void importFromContactsRecord(contacts_record_h contacts_record,
+            unsigned int index);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+    bool isLabelSet() const;
+    std::string getLabel() const;
+    void setLabel(std::string label);
+    void unsetLabel();
+
+private:
+    std::string m_phone_number;
+    bool m_is_default;
+    Common::JSStringVector m_types;
+    bool m_is_label_set;
+    std::string m_label;
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif
diff --git a/src/Contact/ContactRef.cpp b/src/Contact/ContactRef.cpp
new file mode 100644 (file)
index 0000000..504ce10
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactRef.cpp
+ */
+
+#include "ContactRef.h"
+#include "ContactManager.h"
+#include "AddressBook.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+ContactRef::ContactRef():
+        m_address_book_id(0),
+        m_contact_id(0)
+{
+}
+
+ContactRef::~ContactRef()
+{
+}
+
+int ContactRef::getAddressBookId()
+{
+    return m_address_book_id;
+}
+
+std::string ContactRef::getAddressBookIdString()
+{
+    return m_address_book_id_str;
+}
+
+void ContactRef::setAddressBookId(int addressBookId)
+{
+    m_address_book_id = addressBookId;
+    m_address_book_id_str = std::to_string(addressBookId);
+}
+
+void ContactRef::setAddressBookIdString(std::string id)
+{
+    m_address_book_id_str = id;
+    m_address_book_id = std::stoi(id);
+}
+
+int ContactRef::getContactId()
+{
+    return m_contact_id;
+}
+
+std::string ContactRef::getContactIdString()
+{
+    return m_contact_id_str;
+}
+
+void ContactRef::setContactId(int contactId)
+{
+    m_contact_id = contactId;
+    m_contact_id_str = std::to_string(contactId);
+}
+
+void ContactRef::setContactIdString(std::string id)
+{
+    m_contact_id_str = id;
+    m_contact_id = std::stoi(id);
+}
+
+bool ContactRef::isValid()
+{
+    try {
+        AddressBookPtr address_book =
+                ContactManager::getInstance().getAddressBook(m_address_book_id);
+        address_book->get(m_contact_id);
+    }
+    catch (...) {
+        return false;
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactRef.h b/src/Contact/ContactRef.h
new file mode 100644 (file)
index 0000000..0b69a95
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactRef.h
+ */
+
+#ifndef __TIZEN_CONTACT_CONTACT_REF_H__
+#define __TIZEN_CONTACT_CONTACT_REF_H__
+
+#include <string>
+#include <memory>
+#include <Export.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class DLL_EXPORT ContactRef;
+typedef std::shared_ptr<ContactRef> ContactRefPtr;
+
+class DLL_EXPORT ContactRef {
+
+public:
+    ContactRef();
+    virtual ~ContactRef();
+
+    int getAddressBookId();
+    std::string getAddressBookIdString();
+    void setAddressBookId(int);
+    void setAddressBookIdString(std::string);
+    int getContactId();
+    std::string getContactIdString();
+    void setContactId(int);
+    void setContactIdString(std::string);
+
+    bool isValid();
+
+private:
+    int m_address_book_id;
+    int m_contact_id;
+    std::string m_address_book_id_str;
+    std::string m_contact_id_str;
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif //__TIZEN_CONTACT_CONTACT_REF_H__
diff --git a/src/Contact/ContactRelationship.cpp b/src/Contact/ContactRelationship.cpp
new file mode 100644 (file)
index 0000000..fc2105c
--- /dev/null
@@ -0,0 +1,265 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactRelationship.cpp
+ */
+
+#include "ContactRelationship.h"
+#include <Logger.h>
+#include <PlatformException.h>
+#include "ContactUtil.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+ContactRelationship::ContactRelationship():
+        m_is_label_set(false)
+{
+}
+
+ContactRelationship::~ContactRelationship()
+{
+}
+
+std::string ContactRelationship::getRelativeName() const
+{
+    return m_relative_name;
+}
+
+void ContactRelationship::setRelativeName(std::string relative_name)
+{
+    m_relative_name = relative_name;
+}
+
+ContactRelationshipType ContactRelationship::getType() const
+{
+    return m_type;
+}
+
+void ContactRelationship::setType(ContactRelationshipType type)
+{
+    m_type = type;
+}
+
+std::string ContactRelationship::getLabel() const
+{
+    return m_label;
+}
+
+void ContactRelationship::setLabel(const std::string &value)
+{
+    m_is_label_set = true;
+    m_label = value;
+}
+
+bool ContactRelationship::isLabelSet() const
+{
+    return m_is_label_set;
+}
+
+void ContactRelationship::unsetLabel()
+{
+    m_is_label_set = false;
+}
+
+void ContactRelationship::importFromContactsRecord(
+        contacts_record_h contacts_record, unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_get_child_record_at_p(contacts_record,
+            _contacts_contact.relationship, index, &child_record);
+    if ( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err ) {
+        LOGW("%s", ContactUtil::getContactErrorString(err, "contacts_record_get_child_record_at_p()").c_str());
+        return;
+    }
+
+    char* relative = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_relationship.name, &relative);
+    if (!relative) {
+        return;
+    }
+
+    m_relative_name = std::string(relative);
+
+    int type = 0;
+    ContactUtil::getIntFromRecord(child_record, _contacts_relationship.type, &type);
+
+    ContactRelationshipType relationshipType;;
+
+    switch (type) {
+        case CONTACTS_RELATIONSHIP_TYPE_CUSTOM:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_CUSTOM;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_ASSISTANT:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_ASSISTANT;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_BROTHER:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_BROTHER;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_CHILD:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_CHILD;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_DOMESTIC_PARTNER;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_FATHER:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_FATHER;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_FRIEND:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_FRIEND;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_MANAGER:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_MANAGER;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_MOTHER:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_MOTHER;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_PARENT:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_PARENT;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_PARTNER:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_PARTNER;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_REFERRED_BY;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_RELATIVE:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_RELATIVE;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_SISTER:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_SISTER;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_SPOUSE:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_SPOUSE;
+            break;
+        case CONTACTS_RELATIONSHIP_TYPE_OTHER:
+        default:
+            relationshipType = CONTACT_RELATIONSHIP_TYPE_OTHER;
+            break;
+    }
+    m_type = relationshipType;
+
+    char* label = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_relationship.label, &label);
+    if (label) {
+        setLabel(std::string(label));
+    }
+}
+
+void ContactRelationship::exportToContactsRecord(
+        contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_create(_contacts_relationship._uri, &child_record);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&child_record, contactsDeleter);
+
+    ContactUtil::setStrInRecord(child_record, _contacts_relationship.name,
+            getRelativeName().c_str());
+
+    int type_to_set = 0;
+    switch (m_type) {
+        case CONTACT_RELATIONSHIP_TYPE_ASSISTANT:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_ASSISTANT;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_BROTHER:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_BROTHER;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_CHILD:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_CHILD;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_DOMESTIC_PARTNER:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_DOMESTIC_PARTNER;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_FATHER:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_FATHER;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_FRIEND:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_FRIEND;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_MANAGER:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_MANAGER;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_MOTHER:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_MOTHER;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_PARENT:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_PARENT;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_PARTNER:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_PARTNER;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_REFERRED_BY:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_REFERRED_BY;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_RELATIVE:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_RELATIVE;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_SISTER:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_SISTER;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_SPOUSE:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_SPOUSE;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_CUSTOM:
+            type_to_set = CONTACTS_RELATIONSHIP_TYPE_CUSTOM;
+            break;
+        case CONTACT_RELATIONSHIP_TYPE_OTHER:
+        default:
+            type_to_set = CONTACTS_MESSENGER_TYPE_OTHER;
+            break;
+    }
+
+    ContactUtil::setIntInRecord(child_record,_contacts_relationship.type,
+            type_to_set);
+
+    if (isLabelSet()) {
+        ContactUtil::setStrInRecord(child_record,_contacts_relationship.label,
+                getLabel().c_str());
+    }
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.relationship, child_record);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    record.release();
+}
+
+}
+}
diff --git a/src/Contact/ContactRelationship.h b/src/Contact/ContactRelationship.h
new file mode 100644 (file)
index 0000000..0987937
--- /dev/null
@@ -0,0 +1,85 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ContactRelationship.h
+ */
+
+#ifndef _TIZEN_CONTACT_CONTACT_RELATIONSHIP_H_
+#define _TIZEN_CONTACT_CONTACT_RELATIONSHIP_H_
+
+#include <memory>
+#include <ctime>
+#include <string>
+#include <vector>
+#include <contacts.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactRelationship;
+typedef std::shared_ptr<ContactRelationship> ContactRelationshipPtr;
+typedef std::vector<ContactRelationshipPtr> ContactRelationshipPtrVector;
+
+enum ContactRelationshipType {
+    CONTACT_RELATIONSHIP_TYPE_OTHER,
+    CONTACT_RELATIONSHIP_TYPE_ASSISTANT,
+    CONTACT_RELATIONSHIP_TYPE_BROTHER,
+    CONTACT_RELATIONSHIP_TYPE_CHILD,
+    CONTACT_RELATIONSHIP_TYPE_DOMESTIC_PARTNER,
+    CONTACT_RELATIONSHIP_TYPE_FATHER,
+    CONTACT_RELATIONSHIP_TYPE_FRIEND,
+    CONTACT_RELATIONSHIP_TYPE_MANAGER,
+    CONTACT_RELATIONSHIP_TYPE_MOTHER,
+    CONTACT_RELATIONSHIP_TYPE_PARENT,
+    CONTACT_RELATIONSHIP_TYPE_PARTNER,
+    CONTACT_RELATIONSHIP_TYPE_REFERRED_BY,
+    CONTACT_RELATIONSHIP_TYPE_RELATIVE,
+    CONTACT_RELATIONSHIP_TYPE_SISTER,
+    CONTACT_RELATIONSHIP_TYPE_SPOUSE,
+    CONTACT_RELATIONSHIP_TYPE_CUSTOM
+};
+
+class ContactRelationship {
+public:
+    ContactRelationship();
+    virtual ~ContactRelationship();
+
+    std::string getRelativeName() const;
+    void setRelativeName(std::string relative_name);
+    ContactRelationshipType getType() const;
+    void setType(ContactRelationshipType type);
+    std::string getLabel() const;
+    void setLabel(const std::string &value);
+    bool isLabelSet() const;
+    void unsetLabel();
+    void importFromContactsRecord(contacts_record_h contacts_record,
+            unsigned int index);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+
+private:
+    std::string m_relative_name;;
+    ContactRelationshipType m_type;
+    std::string m_label;
+    bool m_is_label_set;
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // _TIZEN_CONTACT_CONTACT_RELATIONSHIP_H_
diff --git a/src/Contact/ContactSearchEngine.cpp b/src/Contact/ContactSearchEngine.cpp
new file mode 100644 (file)
index 0000000..2b21728
--- /dev/null
@@ -0,0 +1,1554 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ContactSearchEngine.h"
+
+#include <contacts.h>
+#include <ctime>
+#include <algorithm>
+#include <limits>
+#include <iomanip>
+#include "Contact.h"
+#include "ContactUtil.h"
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace Tizen;
+using namespace Common;
+
+void ContactSearchEngine::getQueryResults(contacts_query_h query,
+        contacts_filter_h filter, unsigned int property_id, LongSetPtr result)
+{
+    int error_code = contacts_query_set_filter(query, filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_set_filter()");
+    }
+
+    contacts_list_h list = NULL;
+    error_code = contacts_db_get_records_with_query(query, 0, 0, &list);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_db_get_records_with_query()");
+    }
+    contacts_list_h_ptr list_ptr(&list, contactsListDeleter);
+
+    int record_count = 0;
+    error_code = contacts_list_get_count(*list_ptr, &record_count);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_list_get_count()");
+    }
+
+    contacts_list_first(*list_ptr);
+    for (int i = 0; i < record_count; i++) {
+        contacts_record_h record;
+        error_code = contacts_list_get_current_record_p(*list_ptr, &record);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_list_get_current_record_p()");
+        }
+
+        int value = 0;
+        error_code = contacts_record_get_int(record, property_id, &value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_record_get_int()");
+        }
+
+        result->insert(value);
+        error_code = contacts_list_next(*list_ptr);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_list_next()").c_str());
+        }
+    }
+}
+
+ContactSearchEngine::PropertiesMap ContactSearchEngine::s_properties_map = {
+        {"id",                      { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.id, PrimitiveType_Long } },
+        {"personId",                { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.person_id, PrimitiveType_Long } },
+        {"addressBookId",           { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.address_book_id, PrimitiveType_Long } },
+        {"lastUpdated",             { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.changed_time, PrimitiveType_Long } },
+        {"isFavorite",              { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.is_favorite, PrimitiveType_Boolean } },
+        {"name.prefix",             { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.prefix, PrimitiveType_String } },
+        {"name.suffix",             { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.suffix, PrimitiveType_String } },
+        {"name.firstName",          { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.first, PrimitiveType_String } },
+        {"name.middleName",         { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.addition, PrimitiveType_String } },
+        {"name.lastName",           { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.last, PrimitiveType_String } },
+        {"name.nicknames",          { _contacts_nickname._uri, _contacts_nickname.contact_id, _contacts_nickname.name, PrimitiveType_String } },
+        {"name.phoneticFirstName",  { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.phonetic_first, PrimitiveType_String } },
+        {"name.phoneticMiddleName",  { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.phonetic_middle, PrimitiveType_String } },
+        {"name.phoneticLastName",   { _contacts_name._uri, _contacts_name.contact_id, _contacts_name.phonetic_last, PrimitiveType_String } },
+        {"name.displayName",        { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.display_name, PrimitiveType_String } },
+        {"addresses.country",       { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.country, PrimitiveType_String } },
+        {"addresses.region",        { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.region, PrimitiveType_String } },
+        {"addresses.city",          { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.locality, PrimitiveType_String } },
+        {"addresses.streetAddress", { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.street, PrimitiveType_String } },
+        {"addresses.additionalInformation", { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.extended, PrimitiveType_String } },
+        {"addresses.postalCode",    { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.postal_code, PrimitiveType_String } },
+        {"addresses.isDefault",     { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.is_default, PrimitiveType_Boolean } },
+        {"addresses.types",         { _contacts_address._uri, _contacts_address.contact_id, _contacts_address.type, PrimitiveType_Long } },
+        {"photoURI",                { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.image_thumbnail_path, PrimitiveType_String } },
+        {"phoneNumbers.number",     { _contacts_number._uri, _contacts_number.contact_id, _contacts_number.number, PrimitiveType_String } },
+        {"phoneNumbers.isDefault",  { _contacts_number._uri, _contacts_number.contact_id, _contacts_number.is_default, PrimitiveType_Boolean } },
+        {"phoneNumbers.types",      { _contacts_number._uri, _contacts_number.contact_id, _contacts_number.type, PrimitiveType_Long } },
+        {"emails.email",            { _contacts_email._uri, _contacts_email.contact_id, _contacts_email.email, PrimitiveType_String } },
+        {"emails.isDefault",        { _contacts_email._uri, _contacts_email.contact_id, _contacts_email.is_default, PrimitiveType_Boolean } },
+        {"emails.types",            { _contacts_email._uri, _contacts_email.contact_id, _contacts_email.type, PrimitiveType_Long } },
+        {"birthday",                { _contacts_event._uri, _contacts_event.contact_id, _contacts_event.date, PrimitiveType_Long } },
+        {"anniversaries.date",      { _contacts_event._uri, _contacts_event.contact_id, _contacts_event.date, PrimitiveType_Long } },
+        {"anniversaries.label",     { _contacts_event._uri, _contacts_event.contact_id, _contacts_event.label, PrimitiveType_String } },
+        {"organizations.name",      { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.name, PrimitiveType_String } },
+        {"organizations.department",{ _contacts_company._uri, _contacts_company.contact_id, _contacts_company.department, PrimitiveType_String } },
+        {"organizations.title",     { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.job_title, PrimitiveType_String } },
+        {"organizations.role",      { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.role, PrimitiveType_String } },
+        {"organizations.logoURI",   { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.logo, PrimitiveType_String } },
+        {"organizations.assistant", { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.assistant_name, PrimitiveType_String } },
+        {"organizations.location",  { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.location, PrimitiveType_String } },
+        {"organizations.description",  { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.description, PrimitiveType_String } },
+        {"organizations.phoneticName", { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.phonetic_name, PrimitiveType_String } },
+        {"organizations.type",      { _contacts_company._uri, _contacts_company.contact_id, _contacts_company.type, PrimitiveType_Long } },
+        {"notes",                   { _contacts_note._uri, _contacts_note.contact_id, _contacts_note.note, PrimitiveType_String } },
+        {"urls.url",                { _contacts_url._uri, _contacts_url.contact_id, _contacts_url.url, PrimitiveType_String } },
+        {"urls.type",               { _contacts_url._uri, _contacts_url.contact_id, _contacts_url.type, PrimitiveType_Long } },
+        {"ringtoneURI",             { _contacts_simple_contact._uri, _contacts_simple_contact.id, _contacts_simple_contact.ringtone_path, PrimitiveType_String } },
+        {"groupIds",                { _contacts_group_relation._uri, _contacts_group_relation.contact_id, _contacts_group_relation.group_id, PrimitiveType_Long } }
+};
+
+namespace {
+std::string toDateDbStr(const tm &date)
+{
+    std::stringstream ss;
+    ss << std::setfill('0') << std::setiosflags(std::ios::right) <<
+            std::setw(4) << (date.tm_year + 1900);
+    ss << std::setfill('0') << std::setiosflags(std::ios::right) <<
+            std::setw(2) << (date.tm_mon + 1);
+    ss << std::setfill('0') << std::setiosflags(std::ios::right) <<
+            std::setw(2) << date.tm_mday;
+
+    return ss.str();
+}
+
+int strToInt(const std::string &str)
+{
+    int result = 0;
+
+    std::istringstream iss(str);
+    iss >> result;
+
+    return result;
+}
+
+int toDateDbInt(const tm &date)
+{
+    return strToInt(toDateDbStr(date));
+}
+}
+
+ContactSearchEngine::ContactSearchEngine() :
+        m_addressbook_id(0),
+        m_is_addressbook_id_is_set(false),
+        m_is_filter_set(false),
+        m_is_sort_mode_set(false)
+{
+}
+
+ContactSearchEngine::~ContactSearchEngine()
+{
+}
+
+void ContactSearchEngine::setAddressBookId(long id)
+{
+    m_addressbook_id = id;
+    m_is_addressbook_id_is_set = true;
+}
+
+void ContactSearchEngine::applyFilter(AbstractFilterPtr filter, int depth)
+{
+    if (!filter) {
+        return;
+    }
+
+    switch (filter->getFilterType()) {
+        case ATTRIBUTE_FILTER: {
+            AttributeFilterPtr attribute_filter =
+                    std::dynamic_pointer_cast<AttributeFilter>(filter);
+            if (!attribute_filter) {
+                LOGE("Could not cast AbstractFilterPtr to AttributeFilterPtr");
+                throw Common::UnknownException("Wrong filter type");
+            }
+            this->applyAttributeFilter(attribute_filter, depth);
+            break;
+        }
+        case ATTRIBUTE_RANGE_FILTER: {
+            AttributeRangeFilterPtr attribute_range_filter =
+                    std::dynamic_pointer_cast<AttributeRangeFilter>(filter);
+            if (!attribute_range_filter) {
+                LOGE("Could not cast AbstractFilterPtr to AttributeRangeFilterPtr");
+                throw Common::UnknownException("Wrong filter type");
+            }
+            this->applyAttributeRangeFilter(attribute_range_filter, depth);
+            break;
+        }
+        case COMPOSITE_FILTER: {
+            CompositeFilterPtr composite_filter =
+                    std::dynamic_pointer_cast<CompositeFilter>(filter);
+            if (!composite_filter) {
+                LOGE("Could not cast AbstractFilterPtr to CompositeFilterPtr");
+                throw Common::UnknownException("Wrong filter type");
+            }
+
+            LongSetPtrVectorPtr idSets = LongSetPtrVectorPtr(new LongSetPtrVector());
+            m_contact_id_set_array_stack.push(idSets);
+
+            AbstractFilterPtrVector filters = composite_filter->getFilters();
+            for_each(filters.begin(), filters.end(),
+                        [this, depth] (AbstractFilterPtr filter_ptr) {
+                this->applyFilter(filter_ptr, depth + 1);
+            });
+
+            idSets = m_contact_id_set_array_stack.top();
+            m_contact_id_set_array_stack.pop();
+
+            CompositeFilterType type = composite_filter->getType();
+
+            LongSetPtr idSet = LongSetPtr(new LongSet());
+
+            if (UNION == type) {
+                getUnion(idSets, idSet);
+            }
+            else if (INTERSECTION == type) {
+                getIntersection(idSets, idSet);
+            }
+
+            if (!depth) {
+                m_filtered_contact_ids = idSet;
+            }
+            else if (idSet) {
+                LongSetPtrVectorPtr parentIdSets = m_contact_id_set_array_stack.top();
+                parentIdSets->push_back(idSet);
+            }
+
+            break;
+        }
+        default:
+            LOGE("Wrong filter type");
+            throw Common::UnknownException("Wrong filter type");
+    }
+
+    if (m_filtered_contact_ids) {
+        m_is_filter_set = true;
+    }
+}
+
+void ContactSearchEngine::setSortMode(SortModePtr attr)
+{
+    if (!attr) {
+        return;
+    }
+
+    m_sort_mode = attr;
+    std::string attr_name = m_sort_mode->getAttributeName();
+
+    PropertiesMap::iterator iter =
+            s_properties_map.find(m_sort_mode->getAttributeName());
+    if (s_properties_map.end() == iter) {
+        std::string msg = "SortMode don't support ";
+        msg += attr_name;
+        LOGE("%s", msg.c_str());
+        throw Common::UnknownException(msg.c_str());
+    }
+
+    m_is_sort_mode_set = true;
+}
+
+std::shared_ptr<ContactPtrVector> ContactSearchEngine::find()
+{
+    std::shared_ptr<ContactPtrVector> result;
+    unsigned int length = 0;
+
+    if (m_is_filter_set) {
+        if (m_is_sort_mode_set) {
+            LongVectorPtr ids = LongVectorPtr(new LongVector());
+
+            PropertiesMap::iterator iter =
+                    s_properties_map.find(m_sort_mode->getAttributeName());
+            FilterPropertyStruct property = iter->second;
+
+            length = m_filtered_contact_ids->size();
+
+            if (length) {
+                sortContacts(property, ids, (ASC == m_sort_mode->getOrder()),
+                            m_filtered_contact_ids);
+                result = getContacts(ids);
+            }
+            else {
+                std::shared_ptr<ContactPtrVector> contacts(new ContactPtrVector());
+                result = contacts;
+            }
+        }
+        else {
+            length = m_filtered_contact_ids->size();
+            if (length) {
+                result = getContacts(m_filtered_contact_ids);
+            }
+            else {
+                std::shared_ptr<ContactPtrVector> contacts(new ContactPtrVector());
+                result = contacts;
+            }
+        }
+    }
+    else {
+        if (m_is_sort_mode_set) {
+            PropertiesMap::iterator iter =
+                    s_properties_map.find(m_sort_mode->getAttributeName());
+            FilterPropertyStruct property = iter->second;
+
+            result = getAllContactsSorted(property,
+                    (ASC == m_sort_mode->getOrder()));
+        }
+        else {
+            result = getAllContacts();
+        }
+    }
+
+    return result;
+}
+
+void ContactSearchEngine::applyAttributeFilter(AttributeFilterPtr filter, int depth)
+{
+    FilterMatchFlag matchFlag = filter->getMatchFlag();
+    std::string attrName = filter->getAttributeName();
+    AnyPtr matchValue = filter->getMatchValue();
+
+    if (filter->getMatchValue()->isNullOrUndefined()) {
+        matchFlag = EXISTS;
+    }
+
+    LongSetPtr idSet = LongSetPtr(new LongSet());
+    if ("id" == attrName) {
+        if(EXISTS != matchFlag) {
+            idSet->insert(matchValue->toLong());
+
+            if (!depth) {
+                m_filtered_contact_ids = idSet;
+            }
+            else {
+                LongSetPtrVectorPtr parentIdSets = m_contact_id_set_array_stack.top();
+                parentIdSets->push_back(idSet);
+            }
+        }
+        return;
+    }
+    else if ("addresses.types" == attrName ||
+            "emails.types" == attrName ||
+            "phoneNumbers.types" == attrName ||
+            "urls.type" == attrName) {
+        if (!depth) {
+            m_filtered_contact_ids = LongSetPtr();
+        }
+
+        return;
+    }
+
+    PropertiesMap::iterator iter =  s_properties_map.find(attrName);
+    if (iter == s_properties_map.end()) {
+        LOGE("No attribute name for filter");
+        throw NotFoundException("There is no attribute name for filter");
+    }
+
+    FilterPropertyStruct properties = iter->second;
+
+    if(PrimitiveType_Boolean == properties.type) {
+        bool value = true;
+        if (EXISTS != matchFlag) {
+            value = matchValue->toBool();
+        }
+
+        queryAttributeBool(properties, idSet, value);
+    }
+    else if (PrimitiveType_String == properties.type) {
+        std::string value = "";
+
+        if (EXISTS != matchFlag) {
+            if("photoURI" == attrName
+                    || "ringtoneURI" == attrName
+                    || "organizations.logoURI" == attrName) {
+                value = ContactUtil::convertUriToPath(matchValue->toString());
+            }
+            else {
+                value = matchValue->toString();
+            }
+        }
+
+        contacts_match_str_flag_e flag = CONTACTS_MATCH_EXISTS;
+
+        if (EXACTLY == matchFlag) {
+            flag = CONTACTS_MATCH_EXACTLY;
+        }
+        else if (FULLSTRING == matchFlag) {
+            flag = CONTACTS_MATCH_FULLSTRING;
+        }
+        else if (CONTAINS == matchFlag) {
+            flag = CONTACTS_MATCH_CONTAINS;
+        }
+        else if (STARTSWITH == matchFlag) {
+            flag = CONTACTS_MATCH_STARTSWITH;
+        }
+        else if (ENDSWITH == matchFlag) {
+            flag = CONTACTS_MATCH_ENDSWITH;
+        }
+        else if (EXISTS == matchFlag) {
+            flag = CONTACTS_MATCH_EXISTS;
+        }
+
+        queryAttributeString(properties, idSet, flag, value.c_str());
+    }
+    else if (PrimitiveType_Long == properties.type) {
+        int value = 0;
+
+        if (EXISTS != matchFlag) {
+            if ("lastUpdated" == attrName) {
+                time_t tmpTime = mktime(matchValue->toDateTm());
+                value = (int)tmpTime;
+            }
+            else if ("birthday" == attrName || "anniversaries.date" == attrName) {
+                value = toDateDbInt(*matchValue->toDateTm());
+            }
+            else {
+                value = matchValue->toLong();
+            }
+        }
+
+        contacts_match_int_flag_e flag;
+        if (EXISTS == matchFlag) {
+            flag = CONTACTS_MATCH_GREATER_THAN_OR_EQUAL;
+            value = 0;
+        }
+        else if (STARTSWITH == matchFlag || CONTAINS == matchFlag) {
+            flag = CONTACTS_MATCH_GREATER_THAN_OR_EQUAL;
+        }
+        else if (ENDSWITH == matchFlag) {
+            flag = CONTACTS_MATCH_LESS_THAN_OR_EQUAL;
+        }
+        else {
+            flag = CONTACTS_MATCH_EQUAL;
+        }
+
+        if ("birthday" == attrName || "anniversaries.date" == attrName) {
+            queryAttributeDate(attrName, properties, idSet, flag, value);
+        }
+        else {
+            queryAttributeInt(properties, idSet, flag, value);
+        }
+    }
+
+    if (!depth) {
+        m_filtered_contact_ids = idSet;
+    }
+    else {
+        if (idSet) {
+            LongSetPtrVectorPtr parentIdSets = m_contact_id_set_array_stack.top();
+            parentIdSets->push_back(idSet);
+        }
+    }
+}
+
+void ContactSearchEngine::applyAttributeRangeFilter(
+        AttributeRangeFilterPtr filter, int depth)
+{
+    LongSetPtr idSet = LongSetPtr(new LongSet());
+
+    std::string attrName = filter->getAttributeName();
+
+    bool initialValueIsSet = !filter->getInitialValue()->isNullOrUndefined();
+    bool endValueIsSet = !filter->getEndValue()->isNullOrUndefined();
+    AnyPtr initialValue = filter->getInitialValue();
+    AnyPtr endValue = filter->getEndValue();
+
+    if(!initialValueIsSet && !endValueIsSet) {
+        if (!depth) {
+            m_filtered_contact_ids = LongSetPtr();
+        }
+        return;
+    }
+
+    if("addresses.types" == attrName
+            || "emails.types" == attrName
+            || "phoneNumbers.types" == attrName
+            || "urls.type" == attrName) {
+        if (!depth) {
+            m_filtered_contact_ids = LongSetPtr();
+        }
+        return;
+    }
+
+    PropertiesMap::iterator iter = s_properties_map.find(attrName);
+
+    if (iter == s_properties_map.end()) {
+        LOGE("There is no attribute name for filter");
+        throw NotFoundException("There is no attribute name for filter");
+    }
+    FilterPropertyStruct properties = iter->second;
+
+    if (PrimitiveType_Boolean == properties.type) {
+        bool initialValueBool = false;
+        bool endValueBool = false;
+
+        if (initialValueIsSet) {
+            initialValueBool = initialValue->toBool();
+
+        }
+        if (endValueIsSet) {
+            endValueBool = endValue->toBool();
+        }
+
+        queryAttributeRangeBool(properties, idSet, initialValueIsSet,
+                initialValueBool, endValueIsSet, endValueBool);
+    }
+    else if (PrimitiveType_String == properties.type) {
+        const char *initialValueCStr = NULL;
+        const char *endValueCStr = NULL;
+
+        std::string initialValueStr;
+        std::string endValueStr;
+
+        if (initialValueIsSet) {
+            initialValueStr = initialValue->toString();
+            initialValueCStr = initialValueStr.c_str();
+        }
+        if (endValueIsSet) {
+            endValueStr = endValue->toString();
+            endValueCStr = endValueStr.c_str();
+        }
+
+        queryAttributeRangeString(properties, idSet, initialValueCStr,
+                endValueCStr);
+    }
+    else if (PrimitiveType_Long == properties.type) {
+        int initialValueInt = 0;
+        int endValueInt = 0;
+
+        if("lastUpdated" == attrName) {
+            if (initialValueIsSet) {
+                time_t tmpTime = mktime(initialValue->toDateTm());
+                initialValueInt = (int)tmpTime;
+            }
+            if (endValueIsSet) {
+                time_t tmpTime = mktime(endValue->toDateTm());
+                endValueInt = (int)tmpTime;
+            }
+        }
+        else if ("birthday" == attrName || "anniversaries.date" == attrName) {
+            if (initialValueIsSet) {
+                initialValueInt = toDateDbInt(*initialValue->toDateTm());
+            }
+            if (endValueIsSet) {
+                endValueInt = toDateDbInt(*endValue->toDateTm());
+            }
+        }
+        else {
+            if (initialValueIsSet) {
+                initialValueInt = initialValue->toLong();
+            }
+            if (endValueIsSet) {
+                endValueInt = endValue->toLong();
+            }
+        }
+
+        if ("birthday" == attrName || "anniversaries.date" == attrName) {
+            queryAttributeRangeDate(attrName, properties, idSet,
+                    initialValueIsSet, initialValueInt, endValueIsSet,
+                    endValueInt);
+        }
+        else {
+            queryAttributeRangeInt(properties, idSet, initialValueIsSet,
+                    initialValueInt, endValueIsSet, endValueInt);
+        }
+    }
+
+    if (!depth) {
+        m_filtered_contact_ids = idSet;
+    }
+    else {
+        LongSetPtrVectorPtr parentIdSets = m_contact_id_set_array_stack.top();
+        parentIdSets->push_back(idSet);
+    }
+}
+
+std::shared_ptr<ContactPtrVector> ContactSearchEngine::getAllContactsSorted(
+        FilterPropertyStruct& attributeProperties, bool is_ascending)
+{
+    std::shared_ptr<ContactPtrVector> contacts(new ContactPtrVector());
+
+    std::shared_ptr<ContactPtrVector> allContacts = getAllContacts();
+    LongVectorPtr sortedIds = LongVectorPtr(new LongVector());
+
+    sortContacts(attributeProperties, sortedIds, is_ascending);
+
+    std::map<int, ContactPtr> contactMap;
+
+    ContactPtrVector::iterator citer;
+    for (citer = allContacts->begin(); citer != allContacts->end(); citer++) {
+        ContactPtr contact = *citer;
+        contactMap.insert(std::pair<int, ContactPtr>(contact->getId(), contact));
+    }
+
+    LongVector::iterator iter;
+    for(iter = sortedIds->begin(); iter != sortedIds->end(); iter++) {
+        int id = *iter;
+
+        std::map<int, ContactPtr>::iterator idPair = contactMap.find(id);
+        if (idPair == contactMap.end()) {
+            LOGW("no contact id: %d", id);
+            continue;
+        }
+        contacts->push_back(idPair->second);
+    }
+
+    return contacts;
+}
+
+std::shared_ptr<ContactPtrVector> ContactSearchEngine::getAllContacts()
+{
+    int error_code = 0;
+
+    std::shared_ptr<ContactPtrVector> contacts(new ContactPtrVector());
+    contacts_list_h list = NULL;
+    contacts_list_h_ptr list_ptr(NULL, contactsListDeleter);
+
+    if(!m_is_addressbook_id_is_set) {
+        error_code = contacts_db_get_all_records(_contacts_contact._uri, 0, 0, &list);
+        if(CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_get_all_records()");
+        }
+        list_ptr = contacts_list_h_ptr(&list, contactsListDeleter);
+    }
+    else {
+        contacts_query_h query = NULL;
+        contacts_filter_h filter = NULL;
+
+        error_code = contacts_query_create(_contacts_contact._uri, &query);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_query_create()");
+        }
+        contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+        error_code = contacts_filter_create(_contacts_contact._uri, &filter);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+        }
+        contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+        error_code = contacts_filter_add_int(filter, _contacts_contact.address_book_id, CONTACTS_MATCH_EQUAL, m_addressbook_id);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+
+        error_code = contacts_query_set_filter(query, filter);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_query_set_filter()");
+        }
+
+        error_code = contacts_db_get_records_with_query(query, 0, 0, &list);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_db_get_records_with_query()");
+        }
+        list_ptr = contacts_list_h_ptr(&list, contactsListDeleter);
+    }
+
+    int record_count = 0;
+    error_code = contacts_list_get_count(*list_ptr, &record_count);
+    if(CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_list_get_count()");
+    }
+
+    contacts_list_first(*list_ptr);
+    for (int i = 0; i < record_count; i++) {
+        contacts_record_h record;
+
+        error_code = contacts_list_get_current_record_p(*list_ptr, &record);
+        if (CONTACTS_ERROR_NONE != error_code || !record) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_list_get_current_record_p()").c_str());
+            continue;
+        }
+
+        ContactPtr contact(new Contact());
+        contact->importFromContactsRecord(record);
+
+        contacts->push_back(contact);
+        error_code = contacts_list_next(*list_ptr);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_list_next()").c_str());
+        }
+    }
+
+    return contacts;
+}
+
+std::shared_ptr<ContactPtrVector> ContactSearchEngine::getContacts(LongVectorPtr ids)
+{
+    std::shared_ptr<ContactPtrVector> contacts(new ContactPtrVector());
+
+    LongVector::iterator iter;
+    for (iter = ids->begin(); iter != ids->end(); iter++) {
+        try {
+            ContactPtr contact = getContact(*iter);
+            if (contact) {
+                contacts->push_back(contact);
+            }
+        }
+        catch (const BasePlatformException &err) {
+            LOGW("BasePlatformException caught, name: %s, message: %s",
+                    err.getName().c_str(), err.getMessage().c_str());
+            continue;
+        }
+    }
+
+    return contacts;
+}
+
+std::shared_ptr<ContactPtrVector> ContactSearchEngine::getContacts(LongSetPtr ids)
+{
+    std::shared_ptr<ContactPtrVector> contacts(new ContactPtrVector());
+
+    for (LongSet::iterator iter = ids->begin(); iter != ids->end(); iter++) {
+        try {
+            ContactPtr contact = getContact(*iter);
+            if (contact) {
+                contacts->push_back(contact);
+            }
+        }
+        catch (const BasePlatformException &err) {
+            LOGW("BasePlatformException caught, %d, %d", err.getName().c_str(),
+                    err.getMessage().c_str());
+            continue;
+        }
+    }
+    return contacts;
+}
+
+ContactPtr ContactSearchEngine::getContact(int id)
+{
+    int error_code = 0;
+    contacts_record_h record = NULL;
+
+    error_code = contacts_db_get_record(_contacts_contact._uri, id, &record);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("%s", ContactUtil::getContactErrorString(error_code,
+                "contacts_db_get_record()").c_str());
+        return ContactPtr();
+    }
+    contacts_record_h_ptr record_ptr(&record, contactsDeleter);
+
+    if (m_is_addressbook_id_is_set) {
+        int addressBookId = 0;
+
+        error_code = contacts_record_get_int(*record_ptr,
+                _contacts_contact.address_book_id, &addressBookId);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("%s", ContactUtil::getContactErrorString(error_code, "contacts_record_get_int()").c_str());
+            return ContactPtr();
+        }
+
+        if (addressBookId != m_addressbook_id) {
+            LOGE("Wrong address book");
+            return ContactPtr();
+        }
+    }
+
+    ContactPtr contact(new Contact());
+    contact->importFromContactsRecord(*record_ptr);
+
+    return contact;
+}
+
+void ContactSearchEngine::queryAttributeBool(
+        FilterPropertyStruct& attributeProperties, LongSetPtr result,
+        bool match_value)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+
+    int error_code = contacts_query_create(view_uri, &query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_filter_create(view_uri, &filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+    contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+    error_code = contacts_filter_add_bool(*filter_ptr, property_id, match_value);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_add_bool()");
+    }
+
+    this->getQueryResults(*query_ptr, *filter_ptr, property_contact_id, result);
+}
+
+void ContactSearchEngine::queryAttributeInt(
+        FilterPropertyStruct& attributeProperties, LongSetPtr result,
+        contacts_match_int_flag_e match, int match_value)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+
+    int error_code = contacts_query_create(view_uri, &query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_filter_create(view_uri, &filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+    contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+    error_code = contacts_filter_add_int(*filter_ptr, property_id, match, match_value);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+    }
+
+    this->getQueryResults(*query_ptr, *filter_ptr, property_contact_id, result);
+}
+
+void ContactSearchEngine::queryAttributeDate(std::string& attrName,
+        FilterPropertyStruct& attributeProperties, LongSetPtr result,
+        contacts_match_int_flag_e match, int match_value)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+
+    int error_code = contacts_query_create(view_uri, &query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_filter_create(view_uri, &filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+    contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+    error_code = contacts_filter_add_int(*filter_ptr, property_id, match, match_value);
+    if (error_code != CONTACTS_ERROR_NONE) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+    }
+
+    if ("birthday" == attrName) {
+        error_code = contacts_filter_add_operator(*filter_ptr, CONTACTS_FILTER_OPERATOR_AND);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+        }
+
+        error_code = contacts_filter_add_int(*filter_ptr, _contacts_event.type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_EVENT_TYPE_BIRTH);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+
+    }
+    else if ("anniversaries.date" == attrName) {
+        error_code = contacts_filter_add_operator(*filter_ptr, CONTACTS_FILTER_OPERATOR_AND);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+        }
+
+        error_code = contacts_filter_add_int(*filter_ptr, _contacts_event.type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_EVENT_TYPE_ANNIVERSARY);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+    }
+
+    this->getQueryResults(*query_ptr, *filter_ptr, property_contact_id, result);
+}
+
+void ContactSearchEngine::queryAttributeString(
+        FilterPropertyStruct& attributeProperties, LongSetPtr result,
+        contacts_match_str_flag_e match, const char* match_value)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+
+    int error_code = contacts_query_create(view_uri, &query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_filter_create(view_uri, &filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+    contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+    if (_contacts_number.number == property_id
+            && CONTACTS_MATCH_CONTAINS == match) {
+        property_id = _contacts_number.normalized_number;
+    }
+
+    error_code = contacts_filter_add_str(*filter_ptr, property_id,
+            match, match_value);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_add_str()");
+    }
+
+    this->getQueryResults(*query_ptr, *filter_ptr, property_contact_id, result);
+}
+
+void ContactSearchEngine::queryAttributeRangeBool(
+        FilterPropertyStruct& attributeProperties, LongSetPtr result,
+        bool initial_value_is_set, bool initial_value, bool end_value_is_set,
+        bool end_value)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+
+    int error_code = contacts_query_create(view_uri, &query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_filter_create(view_uri, &filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+    contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+    if (initial_value_is_set && end_value_is_set) {
+        if (initial_value == end_value) {
+            if (initial_value) {
+                error_code = contacts_filter_add_bool(*filter_ptr, property_id,
+                        true);
+                if (CONTACTS_ERROR_NONE != error_code) {
+                    LOGE("ret: %d", error_code);
+                    ContactUtil::throwContactException(error_code, "contacts_filter_add_bool()");
+                }
+            }
+            else if (!end_value) {
+                error_code = contacts_filter_add_bool(*filter_ptr, property_id,
+                        false);
+                if (CONTACTS_ERROR_NONE != error_code) {
+                    LOGE("ret: %d", error_code);
+                    ContactUtil::throwContactException(error_code, "contacts_filter_add_bool()");
+                }
+            }
+        }
+    }
+    else if (initial_value_is_set) {
+        if(initial_value) {
+            error_code = contacts_filter_add_bool(*filter_ptr, property_id, true);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_bool()");
+            }
+        }
+    }
+    else if (end_value_is_set) {
+        if (!end_value) {
+            error_code = contacts_filter_add_bool(*filter_ptr, property_id, false);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_bool()");
+            }
+        }
+    }
+
+    this->getQueryResults(*query_ptr, *filter_ptr, property_contact_id, result);
+}
+
+void ContactSearchEngine::queryAttributeRangeDate(std::string& attrName,
+        FilterPropertyStruct& attributeProperties, LongSetPtr result,
+        bool initial_value_is_set, int initial_value, bool end_value_is_set,
+        int end_value)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+
+    int error_code = contacts_query_create(view_uri, &query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_filter_create(view_uri, &filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+    contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+    if (initial_value_is_set && end_value_is_set) {
+        error_code = contacts_filter_add_int(*filter_ptr, property_id,
+                CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+
+        error_code = contacts_filter_add_operator(*filter_ptr,
+                CONTACTS_FILTER_OPERATOR_AND);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+        }
+
+        error_code = contacts_filter_add_int(*filter_ptr, property_id,
+                CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+    }
+    else if (initial_value_is_set) {
+        error_code = contacts_filter_add_int(*filter_ptr, property_id,
+                CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+    }
+    else if (end_value_is_set) {
+        error_code = contacts_filter_add_int(*filter_ptr, property_id,
+                CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+    }
+
+    if ("birthday" == attrName) {
+        error_code = contacts_filter_add_operator(*filter_ptr,
+                CONTACTS_FILTER_OPERATOR_AND);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+        }
+
+        error_code = contacts_filter_add_int(*filter_ptr, _contacts_event.type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_EVENT_TYPE_BIRTH);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+    }
+    else if ("anniversaries.date" == attrName){
+        error_code = contacts_filter_add_operator(*filter_ptr,
+                CONTACTS_FILTER_OPERATOR_AND);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+        }
+
+        error_code = contacts_filter_add_int(*filter_ptr, _contacts_event.type,
+                CONTACTS_MATCH_EQUAL, CONTACTS_EVENT_TYPE_ANNIVERSARY);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+    }
+
+    this->getQueryResults(*query_ptr, *filter_ptr, property_contact_id, result);
+}
+
+void ContactSearchEngine::queryAttributeRangeInt(
+        FilterPropertyStruct& attributeProperties, LongSetPtr result,
+        bool initial_value_is_set, int initial_value, bool end_value_is_set,
+        int end_value)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+
+    int error_code = contacts_query_create(view_uri, &query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_filter_create(view_uri, &filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+    contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+    if(initial_value_is_set && end_value_is_set) {
+        contacts_filter_h sub_filter = NULL;
+
+        error_code = contacts_filter_create(view_uri, &sub_filter);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+        }
+        contacts_filter_h_ptr sub_filter_ptr(&sub_filter, contactsFilterDeleter);
+
+        error_code = contacts_filter_add_int(*sub_filter_ptr, property_id,
+                CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+
+        error_code = contacts_filter_add_operator(*sub_filter_ptr,
+                CONTACTS_FILTER_OPERATOR_AND);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+        }
+
+        error_code = contacts_filter_add_int(*sub_filter_ptr, property_id,
+                CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+
+        error_code = contacts_filter_add_filter(*filter_ptr, *sub_filter_ptr);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_filter()");
+        }
+    }
+    else if (initial_value_is_set) {
+        error_code = contacts_filter_add_int(*filter_ptr, property_id,
+                CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+    }
+    else if (end_value_is_set) {
+        error_code = contacts_filter_add_int(*filter_ptr, property_id,
+                CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+        }
+    }
+
+    this->getQueryResults(*query_ptr, *filter_ptr, property_contact_id, result);
+}
+
+void ContactSearchEngine::queryAttributeRangeString(
+        FilterPropertyStruct& attributeProperties, LongSetPtr result,
+        const char* initial_value, const char* end_value)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+
+    int error_code = contacts_query_create(view_uri, &query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_filter_create(view_uri, &filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+    contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+    if (initial_value && end_value) {
+        contacts_filter_h sub_filter = NULL;
+
+        error_code = contacts_filter_create(view_uri, &sub_filter);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+        }
+        contacts_filter_h_ptr sub_filter_ptr(&sub_filter, contactsFilterDeleter);
+
+        // TODO To be supported start
+        error_code = contacts_filter_add_str(*sub_filter_ptr, property_id,
+                CONTACTS_MATCH_STARTSWITH, initial_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_str()");
+        }
+
+        error_code = contacts_filter_add_operator(*sub_filter_ptr,
+                CONTACTS_FILTER_OPERATOR_AND);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+        }
+
+        error_code = contacts_filter_add_str(*sub_filter_ptr, property_id,
+                CONTACTS_MATCH_ENDSWITH, end_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_str()");
+        }
+
+        error_code = contacts_filter_add_filter(*filter_ptr, *sub_filter_ptr);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_filter()");
+        }
+    }
+    else if (initial_value) {
+        error_code = contacts_filter_add_str(*filter_ptr, property_id,
+                CONTACTS_MATCH_STARTSWITH, initial_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_str()");
+        }
+    }
+    else if (end_value) {
+        error_code = contacts_filter_add_str(*filter_ptr, property_id,
+                CONTACTS_MATCH_ENDSWITH, end_value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGE("ret: %d", error_code);
+            ContactUtil::throwContactException(error_code, "contacts_filter_add_str()");
+        }
+    }
+
+    this->getQueryResults(*query_ptr, *filter_ptr, property_contact_id, result);
+}
+
+void ContactSearchEngine::sortContacts(FilterPropertyStruct& attributeProperties,
+        LongVectorPtr result,
+        bool is_ascending, LongSetPtr idSet)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    int error_code = 0;
+    contacts_query_h query = NULL;
+    contacts_filter_h filter = NULL;
+    contacts_list_h list = NULL;
+
+    error_code = contacts_query_create(view_uri, &query);
+    if(CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_filter_create(view_uri, &filter);
+    if(CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+    contacts_filter_h_ptr filter_ptr(&filter, contactsFilterDeleter);
+
+    LongSet::iterator iter = idSet->begin();
+    if (iter != idSet->end()) {
+        error_code = contacts_filter_add_int(*filter_ptr, property_contact_id,
+                CONTACTS_MATCH_EQUAL, *iter);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                    "contacts_filter_add_int()").c_str());
+        }
+        for (; iter != idSet->end(); iter++) {
+            error_code = contacts_filter_add_operator(*filter_ptr,
+                    CONTACTS_FILTER_OPERATOR_OR);
+            if (CONTACTS_ERROR_NONE != error_code){
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+            }
+
+            error_code = contacts_filter_add_int(*filter_ptr, property_contact_id,
+                    CONTACTS_MATCH_EQUAL, *iter);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+            }
+        }
+    }
+
+    error_code = contacts_query_set_sort(*query_ptr, property_id, is_ascending);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_set_sort()");
+    }
+
+    error_code = contacts_query_set_filter(*query_ptr, *filter_ptr);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_set_filter()");
+    }
+
+    error_code = contacts_db_get_records_with_query(*query_ptr, 0, 0, &list);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_db_get_records_with_query()");
+    }
+    contacts_list_h_ptr list_ptr(&list, contactsListDeleter);
+
+    int record_count = 0;
+    error_code = contacts_list_get_count(*list_ptr, &record_count);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_list_get_count()");
+    }
+
+    LongSet overlappingIds;
+
+    contacts_list_first(*list_ptr);
+    for (int i = 0; i < record_count; i++)
+    {
+        contacts_record_h record;
+        error_code = contacts_list_get_current_record_p(*list_ptr, &record);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("Failed contacts_list_get_current_record_p(): %s, %d",
+                    ContactUtil::getContactErrorMessage(error_code).c_str(), error_code);
+            continue;
+        }
+
+        int value = 0;
+        error_code = contacts_record_get_int(record, property_contact_id, &value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("Failed contacts_record_get_int(): %s, %d",
+                    ContactUtil::getContactErrorMessage(error_code).c_str(), error_code);
+            continue;
+        }
+
+        if(overlappingIds.find(value) == overlappingIds.end()) {
+            result->push_back(value);
+            overlappingIds.insert(value);
+        }
+
+        error_code = contacts_list_next(*list_ptr);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                    "contacts_list_next()").c_str());
+        }
+    }
+}
+
+void ContactSearchEngine::sortContacts(FilterPropertyStruct& attributeProperties,
+        LongVectorPtr result,
+        bool is_ascending)
+{
+    const char* view_uri = attributeProperties.view_uri;
+    unsigned int property_contact_id = attributeProperties.property_contact_id;
+    unsigned int property_id = attributeProperties.property_id;
+
+    int error_code = 0;
+    contacts_query_h query = NULL;
+    contacts_list_h list = NULL;
+
+    error_code = contacts_query_create(view_uri, &query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_create()");
+    }
+    contacts_query_h_ptr query_ptr(&query, contactsQueryDeleter);
+
+    error_code = contacts_query_set_sort(*query_ptr, property_id, is_ascending);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_set_sort()");
+    }
+
+    error_code = contacts_db_get_records_with_query(*query_ptr, 0, 0, &list);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_db_get_records_with_query()");
+    }
+    contacts_list_h_ptr list_ptr(&list, contactsListDeleter);
+
+    int record_count = 0;
+    error_code = contacts_list_get_count(*list_ptr, &record_count);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_list_get_count()");
+    }
+
+    LongSet overlappingIds;
+
+    contacts_list_first(*list_ptr);
+    for(int i = 0; i < record_count; i++) {
+        contacts_record_h record;
+        error_code = contacts_list_get_current_record_p(*list_ptr, &record);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                    "contacts_list_get_current_record_p()").c_str());
+            continue;
+        }
+
+        int value = 0;
+        error_code = contacts_record_get_int(record, property_contact_id, &value);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                    "contacts_record_get_int()").c_str());
+            continue;
+        }
+
+        if(overlappingIds.find(value) == overlappingIds.end()) {
+            result->push_back(value);
+            overlappingIds.insert(value);
+        }
+
+        error_code = contacts_list_next(*list_ptr);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                    "contacts_list_next()").c_str());
+        }
+    }
+}
+
+void ContactSearchEngine::getIntersection(LongSetPtrVectorPtr idSets,
+        LongSetPtr result)
+{
+    LongSetPtrVector::iterator i;
+
+    if(idSets->size() == 0) {
+        result = LongSetPtr();
+        return;
+    }
+    else if(idSets->size() == 1) {
+        *result = **(idSets->begin());
+        return;
+    }
+
+    LongSetPtrVector::iterator minIter;
+    LongSetPtrVector::size_type minSize =
+            std::numeric_limits<LongSetPtrVector::size_type>::max();
+
+    for(i = idSets->begin(); i != idSets->end(); i++) {
+        LongSetPtr idSet = *i;
+        LongSetPtrVector::size_type size = idSet->size();
+        if(minSize > size)
+        {
+            minSize = size;
+            minIter = i;
+        }
+    }
+
+    LongSetPtr p = *minIter;
+    LongSetPtrVectorPtr sa = LongSetPtrVectorPtr(new LongSetPtrVector());
+    for(i = idSets->begin(); i != idSets->end(); i++) {
+        if(minIter != i) {
+            sa->push_back(*i);
+        }
+    }
+
+    for(LongSet::iterator iter = p->begin(); iter != p->end(); iter++) {
+        bool excluded = false;
+        int value = *iter;
+
+        for(i = sa->begin(); i != sa->end(); i++) {
+            LongSetPtr idSet = *i;
+            if(idSet->find(value) == idSet->end()) {
+                excluded = true;
+                break;
+            }
+        }
+
+        if (!excluded) {
+            result->insert(value);
+        }
+    }
+}
+
+void ContactSearchEngine::getUnion(LongSetPtrVectorPtr idSets,
+        LongSetPtr result)
+{
+    if (!idSets->size()) {
+        result = LongSetPtr();
+        return;
+    }
+    else if (1 == idSets->size()) {
+        *result = **(idSets->begin());
+        return;
+    }
+
+    for (LongSetPtrVector::iterator i = idSets->begin(); i != idSets->end(); i++) {
+        LongSetPtr ids = *i;
+        for(LongSet::iterator j = ids->begin(); j != ids->end(); j++) {
+            result->insert(*j);
+        }
+    }
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactSearchEngine.h b/src/Contact/ContactSearchEngine.h
new file mode 100644 (file)
index 0000000..cea0a59
--- /dev/null
@@ -0,0 +1,131 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _PLATFORM_CONTACT_CONTACT_SEARCH_ENGINE_H_
+#define _PLATFORM_CONTACT_CONTACT_SEARCH_ENGINE_H_
+
+#include <string>
+#include <map>
+#include <set>
+#include <vector>
+#include <stack>
+#include <memory>
+#include "AddressBook.h"
+#include "Contact.h"
+#include <contacts.h>
+#include <AbstractFilter.h>
+#include <AttributeFilter.h>
+#include <AttributeRangeFilter.h>
+#include <CompositeFilter.h>
+#include <SortMode.h>
+#include <Any.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace Tizen;
+
+class ContactSearchEngine;
+typedef std::shared_ptr<ContactSearchEngine> ContactSearchEnginePtr;
+
+class ContactSearchEngine
+{
+public:
+    ContactSearchEngine();
+    virtual ~ContactSearchEngine();
+
+    void setAddressBookId(long id);
+    void applyFilter(AbstractFilterPtr filter, int depth = 0);
+    void setSortMode(SortModePtr sort_mode);
+
+    std::shared_ptr<ContactPtrVector> find();
+
+private:
+    typedef std::vector<long> LongVector;
+    typedef std::shared_ptr<LongVector> LongVectorPtr;
+
+    typedef std::set<long> LongSet;
+    typedef std::shared_ptr<LongSet> LongSetPtr;
+
+    typedef std::vector<LongSetPtr> LongSetPtrVector;
+    typedef std::shared_ptr<LongSetPtrVector> LongSetPtrVectorPtr;
+
+    void applyAttributeFilter(AttributeFilterPtr filter, int depth);
+    void applyAttributeRangeFilter(AttributeRangeFilterPtr filter, int depth);
+
+    void createQuery(const char* view_uri, contacts_query_h* query,
+            contacts_filter_h* filter);
+    void getQueryResults(contacts_query_h query, contacts_filter_h filter,
+            unsigned int property_id, LongSetPtr result);
+
+    struct FilterPropertyStruct {
+        const char* view_uri;
+        const unsigned int property_contact_id;
+        const unsigned int property_id;
+        const PrimitiveType type;
+    };
+
+    typedef std::map<std::string, FilterPropertyStruct> PropertiesMap;
+    static PropertiesMap s_properties_map;
+
+    long m_addressbook_id;
+    bool m_is_addressbook_id_is_set;
+    bool m_is_filter_set;
+    bool m_is_sort_mode_set;
+
+    std::stack<LongSetPtrVectorPtr> m_contact_id_set_array_stack;
+    LongSetPtr m_filtered_contact_ids;
+    LongVectorPtr m_sorted_contact_ids;
+
+    SortModePtr m_sort_mode;
+
+    std::shared_ptr<ContactPtrVector> getAllContactsSorted(FilterPropertyStruct& attributeProperties,
+            bool is_ascending);
+    std::shared_ptr<ContactPtrVector> getAllContacts();
+    std::shared_ptr<ContactPtrVector> getContacts(LongVectorPtr ids);
+    std::shared_ptr<ContactPtrVector> getContacts(LongSetPtr ids);
+    ContactPtr getContact(int id);
+
+    void queryAttributeDate(std::string& attrName, FilterPropertyStruct& attributeProperties, LongSetPtr result,
+        contacts_match_int_flag_e match, int match_value);
+    void queryAttributeBool(FilterPropertyStruct& attributeProperties, LongSetPtr result,
+            bool match_value);
+    void queryAttributeInt(FilterPropertyStruct& attributeProperties, LongSetPtr result,
+            contacts_match_int_flag_e match, int match_value);
+    void queryAttributeString(FilterPropertyStruct& attributeProperties, LongSetPtr result,
+            contacts_match_str_flag_e match, const char* match_value);
+    void queryAttributeRangeBool(FilterPropertyStruct& attributeProperties, LongSetPtr result,
+            bool initial_value_is_set, bool initial_value, bool end_value_is_set, bool end_value);
+    void queryAttributeRangeDate(std::string& attrName, FilterPropertyStruct& attributeProperties, LongSetPtr result,
+            bool initial_value_is_set, int initial_value, bool end_value_is_set, int end_value);
+    void queryAttributeRangeInt(FilterPropertyStruct& attributeProperties, LongSetPtr result,
+            bool initial_value_is_set, int initial_value, bool end_value_is_set, int end_value);
+    void queryAttributeRangeString(FilterPropertyStruct& attributeProperties, LongSetPtr result,
+            const char* initial_value, const char* end_value);
+    void sortContacts(FilterPropertyStruct& attributeProperties, LongVectorPtr result,
+            bool is_ascending, LongSetPtr ids);
+    void sortContacts(FilterPropertyStruct& attributeProperties, LongVectorPtr result,
+            bool is_ascending);
+
+    void getIntersection(LongSetPtrVectorPtr idSets, LongSetPtr result);
+    void getUnion(LongSetPtrVectorPtr idSets, LongSetPtr result);
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // _PLATFORM_CONTACT_CONTACT_SEARCH_ENGINE_H_
diff --git a/src/Contact/ContactUtil.cpp b/src/Contact/ContactUtil.cpp
new file mode 100644 (file)
index 0000000..f76f15b
--- /dev/null
@@ -0,0 +1,754 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ContactUtil.h"
+#include <PlatformException.h>
+#include <algorithm>
+#include <iomanip>
+#include <Logger.h>
+#include <time.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+const char* ContactUtil::CONTACT_TYPE_NONE = "NONE";
+const char* ContactUtil::CONTACT_TYPE_WORK = "WORK";
+const char* ContactUtil::CONTACT_TYPE_HOME = "HOME";
+const char* ContactUtil::CONTACT_TYPE_PREF = "PREF";
+const char* ContactUtil::CONTACT_TYPE_VOICE = "VOICE";
+const char* ContactUtil::CONTACT_TYPE_FAX = "FAX";
+const char* ContactUtil::CONTACT_TYPE_MSG = "MSG";
+const char* ContactUtil::CONTACT_TYPE_CELL = "CELL";
+const char* ContactUtil::CONTACT_TYPE_PAGER = "PAGER";
+const char* ContactUtil::CONTACT_TYPE_BBS = "BBS";
+const char* ContactUtil::CONTACT_TYPE_MODEM = "MODEM";
+const char* ContactUtil::CONTACT_TYPE_CAR = "CAR";
+const char* ContactUtil::CONTACT_TYPE_ISDN = "ISDN";
+const char* ContactUtil::CONTACT_TYPE_VIDEO = "VIDEO";
+const char* ContactUtil::CONTACT_TYPE_PCS = "PCS";
+const char* ContactUtil::CONTACT_TYPE_HOMEPAGE = "HOMEPAGE";
+const char* ContactUtil::CONTACT_TYPE_BLOG = "BLOG";
+const char* ContactUtil::CONTACT_TYPE_ASSISTANT = "ASSISTANT";
+const char* ContactUtil::CONTACT_TYPE_CUSTOM = "CUSTOM";
+const char* ContactUtil::CONTACT_TYPE_OTHER = "OTHER";
+
+const char* ContactUtil::CONTACT_RELATIONSHIP_OTHER = "OTHER";
+const char* ContactUtil::CONTACT_RELATIONSHIP_ASSISTANT = "ASSISTANT";
+const char* ContactUtil::CONTACT_RELATIONSHIP_BROTHER = "BROTHER";
+const char* ContactUtil::CONTACT_RELATIONSHIP_CHILD = "CHILD";
+const char* ContactUtil::CONTACT_RELATIONSHIP_DOMESTIC_PARTNER = "DOMESTIC_PARTNER";
+const char* ContactUtil::CONTACT_RELATIONSHIP_FATHER = "FATHER";
+const char* ContactUtil::CONTACT_RELATIONSHIP_FRIEND = "FRIEND";
+const char* ContactUtil::CONTACT_RELATIONSHIP_MANAGER = "MANAGER";
+const char* ContactUtil::CONTACT_RELATIONSHIP_MOTHER = "MOTHER";
+const char* ContactUtil::CONTACT_RELATIONSHIP_PARENT = "PARENT";
+const char* ContactUtil::CONTACT_RELATIONSHIP_PARTNER = "PARTNER";
+const char* ContactUtil::CONTACT_RELATIONSHIP_REFERRED_BY = "REFERRED_BY";
+const char* ContactUtil::CONTACT_RELATIONSHIP_RELATIVE = "RELATIVE";
+const char* ContactUtil::CONTACT_RELATIONSHIP_SISTER = "SISTER";
+const char* ContactUtil::CONTACT_RELATIONSHIP_SPOUSE = "SPOUSE";
+const char* ContactUtil::CONTACT_RELATIONSHIP_CUSTOM = "CUSTOM";
+
+const char* ContactUtil::CONTACT_IM_OTHER = "OTHER";
+const char* ContactUtil::CONTACT_IM_GOOGLE = "GOOGLE";
+const char* ContactUtil::CONTACT_IM_WLM = "WLM";
+const char* ContactUtil::CONTACT_IM_YAHOO = "YAHOO";
+const char* ContactUtil::CONTACT_IM_FACEBOOK = "FACEBOOK";
+const char* ContactUtil::CONTACT_IM_ICQ = "ICQ";
+const char* ContactUtil::CONTACT_IM_AIM = "AIM";
+const char* ContactUtil::CONTACT_IM_QQ = "QQ";
+const char* ContactUtil::CONTACT_IM_JABBER = "JABBER";
+const char* ContactUtil::CONTACT_IM_SKYPE = "SKYPE";
+const char* ContactUtil::CONTACT_IM_IRC = "IRC";
+const char* ContactUtil::CONTACT_IM_CUSTOM = "CUSTOM";
+
+void contactsDeleter(contacts_record_h *contacts_record)
+{
+    int error_code = contacts_record_destroy(*contacts_record, true);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("%s", ContactUtil::getContactErrorString(error_code, "contacts_record_destroy()").c_str());
+    }
+}
+
+void contactsListDeleter(contacts_list_h *contacts_list)
+{
+    int error_code = contacts_list_destroy(*contacts_list, true);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("%s", ContactUtil::getContactErrorString(error_code, "contacts_list_destroy()").c_str());
+    }
+}
+
+void contactsFilterDeleter(contacts_filter_h *contacts_filter)
+{
+    int error_code = contacts_filter_destroy(*contacts_filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("%s", ContactUtil::getContactErrorString(error_code, "contacts_filter_destroy()").c_str());
+    }
+}
+
+void contactsQueryDeleter(contacts_query_h *contacts_query)
+{
+    int error_code = contacts_query_destroy(*contacts_query);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("%s", ContactUtil::getContactErrorString(error_code, "contacts_query_destroy()").c_str());
+    }
+}
+
+ContactAddressType ContactUtil::stringToContactAddressType(std::string type)
+{
+    std::transform(type.begin(), type.end(), type.begin(), ::toupper);
+    if (CONTACT_TYPE_NONE == type) {
+        return ContactAddressType::CONTACT_ADDRESS_TYPE_NONE;
+    }
+    if (CONTACT_TYPE_WORK == type) {
+        return ContactAddressType::CONTACT_ADDRESS_TYPE_WORK;
+    }
+    if (CONTACT_TYPE_HOME == type) {
+        return ContactAddressType::CONTACT_ADDRESS_TYPE_HOME;
+    }
+    if (CONTACT_TYPE_PREF == type) {
+        return ContactAddressType::CONTACT_ADDRESS_TYPE_PREF;
+    }
+    if (CONTACT_TYPE_OTHER == type) {
+        return ContactAddressType::CONTACT_ADDRESS_TYPE_OTHER;
+    }
+    if (CONTACT_TYPE_CUSTOM == type) {
+        return ContactAddressType::CONTACT_ADDRESS_TYPE_CUSTOM;
+    }
+    std::string exception = "Not supported type: ";
+    exception += type;
+    throw TypeMismatchException(exception.c_str());
+}
+
+std::string ContactUtil::contactAddressTypeToString(ContactAddressType type)
+{
+    switch (type) {
+        case ContactAddressType::CONTACT_ADDRESS_TYPE_NONE:
+            return CONTACT_TYPE_NONE;
+        case ContactAddressType::CONTACT_ADDRESS_TYPE_WORK:
+            return CONTACT_TYPE_WORK;
+        case ContactAddressType::CONTACT_ADDRESS_TYPE_HOME:
+            return CONTACT_TYPE_HOME;
+        case ContactAddressType::CONTACT_ADDRESS_TYPE_PREF:
+            return CONTACT_TYPE_PREF;
+        case ContactAddressType::CONTACT_ADDRESS_TYPE_OTHER:
+            return CONTACT_TYPE_OTHER;
+        case ContactAddressType::CONTACT_ADDRESS_TYPE_CUSTOM:
+            return CONTACT_TYPE_CUSTOM;
+        default:
+            std::string exception = "Not supported type: ";
+            exception += type;
+            throw TypeMismatchException(exception.c_str());
+    }
+}
+
+ContactEmailAddressType ContactUtil::stringToContactEmailAddressType(std::string type)
+{
+    std::transform(type.begin(), type.end(), type.begin(), ::toupper);
+    if (CONTACT_TYPE_NONE == type) {
+        return ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_NONE;
+    }
+    if (CONTACT_TYPE_WORK == type) {
+        return ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_WORK;
+    }
+    if (CONTACT_TYPE_HOME == type) {
+        return ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_HOME;
+    }
+    if (CONTACT_TYPE_PREF == type) {
+        return ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_PREF;
+    }
+    if (CONTACT_TYPE_OTHER == type) {
+        return ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_OTHER;
+    }
+    if (CONTACT_TYPE_CUSTOM == type) {
+        return ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_CUSTOM;
+    }
+    std::string exception = "Not supported type: ";
+    exception += type;
+    throw TypeMismatchException(exception.c_str());
+}
+
+std::string ContactUtil::contactEmailAddressTypeToString(ContactEmailAddressType type)
+{
+    switch (type) {
+        case ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_NONE:
+            return CONTACT_TYPE_NONE;
+        case ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_WORK:
+            return CONTACT_TYPE_WORK;
+        case ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_HOME:
+            return CONTACT_TYPE_HOME;
+        case ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_PREF:
+            return CONTACT_TYPE_PREF;
+        case ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_OTHER:
+            return CONTACT_TYPE_OTHER;
+        case ContactEmailAddressType::CONTACT_EMAIL_ADDRESS_TYPE_CUSTOM:
+            return CONTACT_TYPE_CUSTOM;
+        default:
+            std::string exception = "Not supported type: ";
+            exception += type;
+            throw TypeMismatchException(exception.c_str());
+    }
+}
+
+ContactPhoneNumberType ContactUtil::stringToContactPhoneNumberType(std::string type)
+{
+    std::transform(type.begin(), type.end(), type.begin(), ::toupper);
+    if (CONTACT_TYPE_WORK == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_WORK;
+    }
+    if (CONTACT_TYPE_HOME == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_HOME;
+    }
+    if (CONTACT_TYPE_VOICE == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_VOICE;
+    }
+    if (CONTACT_TYPE_FAX == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_FAX;
+    }
+    if (CONTACT_TYPE_MSG == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_MSG;
+    }
+    if (CONTACT_TYPE_CELL == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_CELL;
+    }
+    if (CONTACT_TYPE_PAGER == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_PAGER;
+    }
+    if (CONTACT_TYPE_BBS == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_BBS;
+    }
+    if (CONTACT_TYPE_MODEM == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_MODEM;
+    }
+    if (CONTACT_TYPE_CAR == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_CAR;
+    }
+    if (CONTACT_TYPE_ISDN == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_ISDN;
+    }
+    if (CONTACT_TYPE_VIDEO == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_VIDEO;
+    }
+    if (CONTACT_TYPE_PCS == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_PCS;
+    }
+    if (CONTACT_TYPE_ASSISTANT == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_ASSISTANT;
+    }
+    if (CONTACT_TYPE_OTHER == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_OTHER;
+    }
+    if (CONTACT_TYPE_CUSTOM == type) {
+        return ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_CUSTOM;
+    }
+    std::string exception = "Not supported type: ";
+    exception += type;
+    throw TypeMismatchException(exception.c_str());
+}
+
+std::string ContactUtil::contactPhoneNumberTypeToString(ContactPhoneNumberType type)
+{
+    switch (type) {
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_WORK:
+            return CONTACT_TYPE_WORK;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_HOME:
+            return CONTACT_TYPE_HOME;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_VOICE:
+            return CONTACT_TYPE_VOICE;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_FAX:
+            return CONTACT_TYPE_FAX;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_MSG:
+            return CONTACT_TYPE_MSG;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_CELL:
+            return CONTACT_TYPE_CELL;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_PAGER:
+            return CONTACT_TYPE_PAGER;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_BBS:
+            return CONTACT_TYPE_BBS;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_MODEM:
+            return CONTACT_TYPE_MODEM;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_CAR:
+            return CONTACT_TYPE_CAR;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_ISDN:
+            return CONTACT_TYPE_ISDN;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_VIDEO:
+            return CONTACT_TYPE_VIDEO;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_PCS:
+            return CONTACT_TYPE_PCS;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_ASSISTANT:
+            return CONTACT_TYPE_ASSISTANT;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_OTHER:
+            return CONTACT_TYPE_OTHER;
+        case ContactPhoneNumberType::CONTACT_PHONE_NUMBER_TYPE_CUSTOM:
+            return CONTACT_TYPE_CUSTOM;
+        default:
+            std::string exception = "Not supported type: ";
+            exception += type;
+            throw TypeMismatchException(exception.c_str());
+    }
+}
+
+ContactWebSiteType ContactUtil::stringToContactWebSiteType(std::string type)
+{
+    std::transform(type.begin(), type.end(), type.begin(), ::toupper);
+    if (CONTACT_TYPE_HOMEPAGE == type) {
+        return ContactWebSiteType::CONTACT_WEB_SITE_TYPE_HOMEPAGE;
+    }
+    if (CONTACT_TYPE_BLOG == type) {
+        return ContactWebSiteType::CONTACT_WEB_SITE_TYPE_BLOG;
+    }
+    std::string exception = "Not supported type: ";
+    exception += type;
+    throw TypeMismatchException(exception.c_str());
+}
+
+std::string ContactUtil::contactWebSiteTypeToString(ContactWebSiteType type)
+{
+    switch (type) {
+        case ContactWebSiteType::CONTACT_WEB_SITE_TYPE_HOMEPAGE:
+            return CONTACT_TYPE_HOMEPAGE;
+        case ContactWebSiteType::CONTACT_WEB_SITE_TYPE_BLOG:
+            return CONTACT_TYPE_BLOG;
+        default:
+            std::string exception = "Not supported type: ";
+            exception += type;
+            throw TypeMismatchException(exception.c_str());
+    }
+}
+
+ContactRelationshipType ContactUtil::stringToRelationshipType(std::string type)
+{
+    std::transform(type.begin(), type.end(), type.begin(), ::toupper);
+    if (CONTACT_RELATIONSHIP_OTHER == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_OTHER;
+    }
+    if (CONTACT_RELATIONSHIP_ASSISTANT == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_ASSISTANT;
+    }
+    if (CONTACT_RELATIONSHIP_BROTHER == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_BROTHER;
+    }
+    if (CONTACT_RELATIONSHIP_CHILD == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_CHILD;
+    }
+    if (CONTACT_RELATIONSHIP_DOMESTIC_PARTNER == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_DOMESTIC_PARTNER;
+    }
+    if (CONTACT_RELATIONSHIP_FATHER == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_FATHER;
+    }
+    if (CONTACT_RELATIONSHIP_FRIEND == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_FRIEND;
+    }
+    if (CONTACT_RELATIONSHIP_MANAGER == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_MANAGER;
+    }
+    if (CONTACT_RELATIONSHIP_MOTHER == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_MOTHER;
+    }
+    if (CONTACT_RELATIONSHIP_PARENT == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_PARENT;
+    }
+    if (CONTACT_RELATIONSHIP_PARTNER == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_PARTNER;
+    }
+    if (CONTACT_RELATIONSHIP_DOMESTIC_PARTNER == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_DOMESTIC_PARTNER;
+    }
+    if (CONTACT_RELATIONSHIP_REFERRED_BY == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_REFERRED_BY;
+    }
+    if (CONTACT_RELATIONSHIP_RELATIVE == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_RELATIVE;
+    }
+    if (CONTACT_RELATIONSHIP_SISTER == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_SISTER;
+    }
+    if (CONTACT_RELATIONSHIP_SPOUSE == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_SPOUSE;
+    }
+    if (CONTACT_RELATIONSHIP_CUSTOM == type) {
+        return ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_CUSTOM;
+    }
+    std::string exception = "Not supported type: ";
+    exception += type;
+    throw TypeMismatchException(exception.c_str());
+}
+
+std::string ContactUtil::contactRelationshipTypeToString(ContactRelationshipType type)
+{
+    switch (type) {
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_OTHER:
+            return CONTACT_RELATIONSHIP_OTHER;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_ASSISTANT:
+            return CONTACT_RELATIONSHIP_ASSISTANT;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_BROTHER:
+            return CONTACT_RELATIONSHIP_BROTHER;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_CHILD:
+            return CONTACT_RELATIONSHIP_CHILD;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_DOMESTIC_PARTNER:
+            return CONTACT_RELATIONSHIP_DOMESTIC_PARTNER;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_FATHER:
+            return CONTACT_RELATIONSHIP_FATHER;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_FRIEND:
+            return CONTACT_RELATIONSHIP_FRIEND;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_MANAGER:
+            return CONTACT_RELATIONSHIP_MANAGER;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_MOTHER:
+            return CONTACT_RELATIONSHIP_MOTHER;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_PARENT:
+            return CONTACT_RELATIONSHIP_PARENT;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_PARTNER:
+            return CONTACT_RELATIONSHIP_PARTNER;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_REFERRED_BY:
+            return CONTACT_RELATIONSHIP_REFERRED_BY;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_RELATIVE:
+            return CONTACT_RELATIONSHIP_RELATIVE;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_SISTER:
+            return CONTACT_RELATIONSHIP_SISTER;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_SPOUSE:
+            return CONTACT_RELATIONSHIP_SPOUSE;
+        case ContactRelationshipType::CONTACT_RELATIONSHIP_TYPE_CUSTOM:
+            return CONTACT_RELATIONSHIP_CUSTOM;
+        default:
+            std::string exception = "Not supported type: ";
+            exception += type;
+            throw TypeMismatchException(exception.c_str());
+    }
+}
+
+ContactInstantMessengerType ContactUtil::stringToInstantMessengerType(std::string type)
+{
+    std::transform(type.begin(), type.end(), type.begin(), ::toupper);
+    if (CONTACT_IM_OTHER == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_OTHER;
+    }
+    if (CONTACT_IM_GOOGLE == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_GOOGLE;
+    }
+    if (CONTACT_IM_WLM == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_WLM;
+    }
+    if (CONTACT_IM_YAHOO== type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_YAHOO;
+    }
+    if (CONTACT_IM_FACEBOOK == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_FACEBOOK;
+    }
+    if (CONTACT_IM_ICQ == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_ICQ;
+    }
+    if (CONTACT_IM_AIM == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_AIM;
+    }
+    if (CONTACT_IM_QQ == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_QQ;
+    }
+    if (CONTACT_IM_JABBER == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_JABBER;
+    }
+    if (CONTACT_IM_SKYPE == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_SKYPE;
+    }
+    if (CONTACT_IM_IRC == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_IRC;
+    }
+    if (CONTACT_IM_CUSTOM == type) {
+        return ContactInstantMessengerType::CONTACT_IM_TYPE_CUSTOM;
+    }
+    std::string exception = "Not supported type: ";
+    exception += type;
+    throw TypeMismatchException(exception.c_str());
+}
+
+std::string ContactUtil::contactInstantMessengerTypeToString(ContactInstantMessengerType type)
+{
+    switch (type) {
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_OTHER:
+            return CONTACT_IM_OTHER;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_GOOGLE:
+            return CONTACT_IM_GOOGLE;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_WLM:
+            return CONTACT_IM_WLM;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_YAHOO:
+            return CONTACT_IM_YAHOO;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_FACEBOOK:
+            return CONTACT_IM_FACEBOOK;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_ICQ:
+            return CONTACT_IM_ICQ;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_AIM:
+            return CONTACT_IM_AIM;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_QQ:
+            return CONTACT_IM_QQ;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_JABBER:
+            return CONTACT_IM_JABBER;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_SKYPE:
+            return CONTACT_IM_SKYPE;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_IRC:
+            return CONTACT_IM_IRC;
+        case ContactInstantMessengerType::CONTACT_IM_TYPE_CUSTOM:
+            return CONTACT_IM_CUSTOM;
+        default:
+            std::string exception = "Not supported type: ";
+            exception += type;
+            throw TypeMismatchException(exception.c_str());
+    }
+}
+
+std::string ContactUtil::convertUriToPath(const std::string &str)
+{
+    std::string result;
+
+    std::string schema ("file://");
+    unsigned found = str.find(schema);
+    if (found != std::string::npos) {
+        result = str.substr(schema.size());
+    }
+    else {
+        result = str;
+    }
+
+    return result;
+}
+
+std::string ContactUtil::convertPathToUri(const std::string &str)
+{
+    std::string result;
+
+    std::string schema("file://");
+    unsigned found = str.find(schema);
+    if (found != std::string::npos) {
+        result = str;
+    }
+    else {
+        result = schema + str;
+    }
+
+    return result;
+}
+
+void ContactUtil::getStrFromRecord(contacts_record_h record,
+        unsigned int property_id,
+        char **value)
+{
+    int err = contacts_record_get_str_p(record, property_id, value);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_get_str_p()");
+    }
+}
+
+void ContactUtil::getIntFromRecord(contacts_record_h record,
+        unsigned int property_id,
+        int *value)
+{
+    int err = contacts_record_get_int(record, property_id, value);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_get_int()");
+    }
+}
+
+void ContactUtil::getBoolFromRecord(contacts_record_h record,
+        unsigned int property_id,
+        bool *value)
+{
+    int err = contacts_record_get_bool(record, property_id, value);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_get_bool()");
+    }
+}
+
+void ContactUtil::setStrInRecord(contacts_record_h record,
+        unsigned int property_id,
+        const char *value)
+{
+    int err = contacts_record_set_str(record, property_id, value);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_set_str()");
+    }
+}
+
+void ContactUtil::setIntInRecord(contacts_record_h record,
+        unsigned int property_id,
+        int value)
+{
+    int err = contacts_record_set_int(record, property_id, value);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_set_int()");
+    }
+}
+
+void ContactUtil::setBoolInRecord(contacts_record_h record,
+        unsigned int property_id,
+        bool value)
+{
+    int err = contacts_record_set_bool(record, property_id, value);
+    if (CONTACTS_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_set_bool()");
+    }
+}
+
+void ContactUtil::clearAllContactRecord(contacts_record_h contacts_record,
+        unsigned int property_id)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h phone_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    int record_count = 0;
+    err = contacts_record_get_child_record_count(contacts_record,
+            property_id, &record_count);
+    if( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err)
+    {
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_get_child_record_count()");
+    }
+
+    for (int i = record_count - 1; i >= 0; i--) {
+        err = contacts_record_get_child_record_at_p(contacts_record,
+                property_id, i, &phone_record);
+        if(CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_record_get_child_record_at_p()");
+        }
+
+        err = contacts_record_remove_child_record(contacts_record,
+                property_id, phone_record);
+        if(CONTACTS_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            ContactUtil::throwContactException(err, "contacts_record_remove_child_record()");
+        }
+    }
+}
+
+int ContactUtil::getNumberOfChildRecord(contacts_record_h contacts_record,
+        unsigned int property_id)
+{
+    int err = CONTACTS_ERROR_NONE;
+    int child_count = 0;
+    err = contacts_record_get_child_record_count(contacts_record, property_id, &child_count);
+    if( CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_get_child_record_count()");
+    }
+
+    return child_count;
+}
+
+int ContactUtil::toDateDbInt(const tm& date)
+{
+    std::stringstream ss;
+    ss << std::setfill('0') << setiosflags(std::ios::right) << std::setw(4) << (date.tm_year + 1900);
+    ss << std::setfill('0') << setiosflags(std::ios::right) << std::setw(2) << (date.tm_mon + 1);
+    ss << std::setfill('0') << setiosflags(std::ios::right) << std::setw(2) << (date.tm_mday);
+    std::string str = ss.str();
+
+    int result = 0;
+    std::istringstream iss(str);
+    iss >> result;
+
+    return result;
+}
+
+std::tm ContactUtil::toTimeT(int date)
+{
+    std::tm dateTm;
+    memset(&dateTm, 0 ,sizeof(tm));
+
+    if(date < 0){
+        throw Common::InvalidValuesException("Invalid data type");
+    }
+
+    int section0to3 = date / 10000;
+    int section4to5 = (date/100) % 100;
+    int section6to7 = date % 100;
+
+    dateTm.tm_year = section0to3 - 1900;
+    dateTm.tm_mon = section4to5 -1;
+    dateTm.tm_mday = section6to7;
+
+    return dateTm;
+}
+
+int ContactUtil::toIntId(std::string value)
+{
+    int result;
+    char *end;
+    result = std::strtol(value.c_str(), &end, 10);
+
+    if (value[0] == '\0' || *end != '\0' || result < 0) {
+        std::string msg = "Value " + value + " is invalid";
+        LOGE("%s", msg.c_str());
+        throw Common::InvalidValuesException(msg.c_str());
+    }
+
+    return result;
+}
+
+std::string ContactUtil::getContactErrorMessage(const int errorCode) {
+    switch (errorCode) {
+        case CONTACTS_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case CONTACTS_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case CONTACTS_ERROR_FILE_NO_SPACE:
+            return "FS full";
+        case CONTACTS_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case CONTACTS_ERROR_NOT_SUPPORTED:
+            return "Not supported";
+        case CONTACTS_ERROR_NO_DATA:
+            return "Requested data does not exist";
+        case CONTACTS_ERROR_DB_LOCKED:
+            return "Database table locked or file locked";
+        case CONTACTS_ERROR_DB:
+            return "Unknown DB error";
+        case CONTACTS_ERROR_IPC_NOT_AVALIABLE:
+            return "IPC server is not available";
+        case CONTACTS_ERROR_IPC:
+            return "Unknown IPC error";
+        case CONTACTS_ERROR_SYSTEM:
+            return "Internal system module error";
+        case CONTACTS_ERROR_INTERNAL:
+            return "Implementation Error, Temporary Use";
+        case CONTACTS_ERROR_NONE:
+            return "Successful";
+        default:
+            return "Unknown error";
+    }
+}
+
+std::string ContactUtil::getContactErrorString(const int ret, const std::string& hint)
+{
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getContactErrorMessage(ret) << ", " << ret;
+    return ss.str();
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactUtil.h b/src/Contact/ContactUtil.h
new file mode 100644 (file)
index 0000000..a926282
--- /dev/null
@@ -0,0 +1,206 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_CONTACT_UTIL_H__
+#define __TIZEN_CONTACT_CONTACT_UTIL_H__
+
+#include "ContactAddress.h"
+#include "ContactEmailAddress.h"
+#include "ContactPhoneNumber.h"
+#include "ContactWebSite.h"
+#include "ContactRelationship.h"
+#include "ContactInstantMessenger.h"
+#include <memory>
+#include "contacts.h"
+#include <ctime>
+#include <string>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+void contactsDeleter(contacts_record_h *contacts_record);
+typedef std::unique_ptr<contacts_record_h, void(*)(contacts_record_h *)> contacts_record_h_ptr;
+
+void contactsListDeleter(contacts_list_h *contacts_list);
+typedef std::unique_ptr<contacts_list_h, void(*)(contacts_list_h *)> contacts_list_h_ptr;
+
+void contactsFilterDeleter(contacts_filter_h *contacts_filter);
+typedef std::unique_ptr<contacts_filter_h, void(*)(contacts_filter_h *)> contacts_filter_h_ptr;
+
+void contactsQueryDeleter(contacts_query_h *contacts_query);
+typedef std::unique_ptr<contacts_query_h, void(*)(contacts_query_h *)> contacts_query_h_ptr;
+
+class ContactUtil {
+public:
+    static ContactAddressType stringToContactAddressType(std::string type);
+    static std::string contactAddressTypeToString(ContactAddressType type);
+    static ContactEmailAddressType stringToContactEmailAddressType(std::string type);
+    static std::string contactEmailAddressTypeToString(ContactEmailAddressType type);
+    static ContactPhoneNumberType stringToContactPhoneNumberType(std::string type);
+    static std::string contactPhoneNumberTypeToString(ContactPhoneNumberType type);
+    static ContactWebSiteType stringToContactWebSiteType(std::string type);
+    static std::string contactWebSiteTypeToString(ContactWebSiteType type);
+    static ContactRelationshipType stringToRelationshipType(std::string type);
+    static std::string contactRelationshipTypeToString(ContactRelationshipType type);
+    static ContactInstantMessengerType stringToInstantMessengerType(std::string type);
+    static std::string contactInstantMessengerTypeToString(ContactInstantMessengerType type);
+
+    /**
+     * @brief   Removes file:// prefix from URI or do nothing
+     *          when path without mentioned prefix was passed
+     *
+     * @param[in]   std::string      The string with URI to file
+     *
+     * @return converted path
+     */
+    static std::string convertUriToPath(const std::string &str);
+
+    /**
+     * @brief   Adds file:// prefix to path or do nothing,
+     *          when uri with mentioned prefix was passed
+     *
+     * @param[in]   std::string        The string with path to file
+     *
+     * @return converted URI
+     */
+    static std::string convertPathToUri(const std::string &str);;
+
+    static void getStrFromRecord(contacts_record_h record,
+            unsigned int property_id,
+            char **value);
+
+    static void getIntFromRecord(contacts_record_h record,
+            unsigned int property_id,
+            int *value);
+
+    static void getBoolFromRecord(contacts_record_h record,
+            unsigned int property_id,
+            bool *value);
+
+    static void setStrInRecord(contacts_record_h record,
+            unsigned int property_id,
+            const char *value);
+
+    static void setIntInRecord(contacts_record_h record,
+            unsigned int property_id,
+            int value);
+
+    static void setBoolInRecord(contacts_record_h record,
+            unsigned int property_id,
+            bool value);
+
+    static void clearAllContactRecord(contacts_record_h contacts_record,
+            unsigned int property_id);
+
+    static int getNumberOfChildRecord(contacts_record_h contacts_record,
+            unsigned int property_id);
+
+    static int toDateDbInt(const std::tm& date);
+    static std::tm toTimeT(int date);
+
+    static int toIntId(std::string);
+
+    static std::string getContactErrorMessage(const int errorCode);
+    static std::string getContactErrorString(const int ret, const std::string& hint);
+
+    template<class T = DeviceAPI::Common::UnknownException>
+    static void throwContactException(const int errorCode,
+            const std::string& hint)
+    {
+        std::string message = getContactErrorString(errorCode, hint);
+        LOGE("%s", message.c_str());
+        throw T(message.c_str());
+    }
+
+    static const char* CONTACT_TYPE_NONE;
+    static const char* CONTACT_TYPE_WORK;
+    static const char* CONTACT_TYPE_HOME;
+    static const char* CONTACT_TYPE_PREF;
+    static const char* CONTACT_TYPE_VOICE;
+    static const char* CONTACT_TYPE_FAX;
+    static const char* CONTACT_TYPE_MSG;
+    static const char* CONTACT_TYPE_CELL;
+    static const char* CONTACT_TYPE_PAGER;
+    static const char* CONTACT_TYPE_BBS;
+    static const char* CONTACT_TYPE_MODEM;
+    static const char* CONTACT_TYPE_CAR;
+    static const char* CONTACT_TYPE_ISDN;
+    static const char* CONTACT_TYPE_VIDEO;
+    static const char* CONTACT_TYPE_PCS;
+    static const char* CONTACT_TYPE_HOMEPAGE;
+    static const char* CONTACT_TYPE_BLOG;
+    static const char* CONTACT_TYPE_ASSISTANT;
+    static const char* CONTACT_TYPE_OTHER;
+    static const char* CONTACT_TYPE_CUSTOM;
+
+    static const char* CONTACT_RELATIONSHIP_OTHER;
+    static const char* CONTACT_RELATIONSHIP_ASSISTANT;
+    static const char* CONTACT_RELATIONSHIP_BROTHER;
+    static const char* CONTACT_RELATIONSHIP_CHILD;
+    static const char* CONTACT_RELATIONSHIP_DOMESTIC_PARTNER;
+    static const char* CONTACT_RELATIONSHIP_FATHER;
+    static const char* CONTACT_RELATIONSHIP_FRIEND;
+    static const char* CONTACT_RELATIONSHIP_MANAGER;
+    static const char* CONTACT_RELATIONSHIP_MOTHER;
+    static const char* CONTACT_RELATIONSHIP_PARENT;
+    static const char* CONTACT_RELATIONSHIP_PARTNER;
+    static const char* CONTACT_RELATIONSHIP_REFERRED_BY;
+    static const char* CONTACT_RELATIONSHIP_RELATIVE;
+    static const char* CONTACT_RELATIONSHIP_SISTER;
+    static const char* CONTACT_RELATIONSHIP_SPOUSE;
+    static const char* CONTACT_RELATIONSHIP_CUSTOM;
+
+    static const char* CONTACT_IM_OTHER;
+    static const char* CONTACT_IM_GOOGLE;
+    static const char* CONTACT_IM_WLM;
+    static const char* CONTACT_IM_YAHOO;
+    static const char* CONTACT_IM_FACEBOOK;
+    static const char* CONTACT_IM_ICQ;
+    static const char* CONTACT_IM_AIM;
+    static const char* CONTACT_IM_QQ;
+    static const char* CONTACT_IM_JABBER;
+    static const char* CONTACT_IM_SKYPE;
+    static const char* CONTACT_IM_IRC;
+    static const char* CONTACT_IM_CUSTOM;
+};
+
+template <class JSType, class NativeTypePtr>
+JSObjectRef ptrVectorToJSObjectArray(const std::vector<NativeTypePtr> &objs,
+        JSContextRef context) {
+
+    unsigned int size = objs.size();
+
+    JSObjectRef objArray[size];
+    for(unsigned int i = 0 ; i < size; i++) {
+        objArray[i] = JSType::makeJSObject(context, objs[i]);
+    }
+
+    JSValueRef exception = NULL;
+    JSObjectRef jsResult = JSObjectMakeArray(context, size,
+            size > 0 ? objArray : NULL, &exception);
+    if (exception != NULL) {
+        throw Common::UnknownException(context, exception);
+    }
+
+    return jsResult;
+}
+
+} // Contact
+} // DeviceAPI
+
+#endif
diff --git a/src/Contact/ContactWebSite.cpp b/src/Contact/ContactWebSite.cpp
new file mode 100644 (file)
index 0000000..3d46982
--- /dev/null
@@ -0,0 +1,131 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <PlatformException.h>
+#include <Logger.h>
+#include "ContactUtil.h"
+#include "ContactWebSite.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+ContactWebSite::ContactWebSite()
+{
+    m_url = "";
+    m_type = ContactWebSiteType::CONTACT_WEB_SITE_TYPE_HOMEPAGE;
+}
+
+ContactWebSite::~ContactWebSite()
+{
+
+}
+
+std::string ContactWebSite::getUrl() const
+{
+    return m_url;
+}
+
+void ContactWebSite::setUrl(const std::string &url)
+{
+    m_url = url;
+}
+
+ContactWebSiteType ContactWebSite::getType() const
+{
+    return m_type;
+}
+
+void ContactWebSite::setType(ContactWebSiteType type)
+{
+    m_type = type;
+}
+
+void ContactWebSite::importFromContactsRecord(contacts_record_h contacts_record,
+        unsigned int index)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h child_record = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    err = contacts_record_get_child_record_at_p(contacts_record, _contacts_contact.url, index, &child_record);
+    if (CONTACTS_ERROR_NONE != err && CONTACTS_ERROR_NO_DATA != err) {
+        LOGW("Failed contacts_record_get_child_record_at_p(): %s, %d",
+                ContactUtil::getContactErrorMessage(err).c_str(), err);
+        return;
+    }
+
+    char* char_value = NULL;
+    ContactUtil::getStrFromRecord(child_record,
+            _contacts_url.url, &char_value);
+    if(!char_value){
+        return;
+    }
+    setUrl(std::string(char_value));
+
+    int type = 0;
+    ContactUtil::getIntFromRecord(child_record, _contacts_url.type,
+            &type);
+
+    m_type = (CONTACTS_URL_TYPE_HOME == type) ?
+                    CONTACT_WEB_SITE_TYPE_HOMEPAGE : CONTACT_WEB_SITE_TYPE_BLOG;
+}
+
+void ContactWebSite::exportToContactsRecord(contacts_record_h contacts_record)
+{
+    int err = CONTACTS_ERROR_NONE;
+    contacts_record_h website_record_h = NULL;
+    //contacts_record is protected by unique_ptr and its ownership is not passed here
+    if (!contacts_record) {
+        LOGE("Contacts record is null");
+        throw Common::UnknownException("Contacts record is null");
+    }
+
+    if (getUrl().empty()) {
+        LOGD("WebSite urls are not set");
+        return;
+    }
+
+    err = contacts_record_create(_contacts_url._uri, &website_record_h);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_create()");
+    }
+    contacts_record_h_ptr record(&website_record_h, contactsDeleter);
+
+    ContactUtil::setStrInRecord(website_record_h, _contacts_url.url,
+            getUrl().c_str());
+
+    int type_to_set = (getType() == CONTACT_WEB_SITE_TYPE_HOMEPAGE)
+            ? CONTACTS_URL_TYPE_HOME : CONTACTS_URL_TYPE_WORK ;
+
+    ContactUtil::setIntInRecord(website_record_h, _contacts_url.type,
+            type_to_set);
+
+    err = contacts_record_add_child_record(contacts_record,
+            _contacts_contact.url, website_record_h);
+    if(CONTACTS_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        ContactUtil::throwContactException(err, "contacts_record_add_child_record()");
+    }
+    record.release();
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/ContactWebSite.h b/src/Contact/ContactWebSite.h
new file mode 100644 (file)
index 0000000..fdc64aa
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_CONTACT_WEB_SITE_H__
+#define __TIZEN_CONTACT_CONTACT_WEB_SITE_H__
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <contacts.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class ContactWebSite;
+typedef std::shared_ptr<ContactWebSite> ContactWebSitePtr;
+typedef std::vector<ContactWebSitePtr> ContactWebSitePtrVector;
+
+enum ContactWebSiteType {
+    CONTACT_WEB_SITE_TYPE_HOMEPAGE,
+    CONTACT_WEB_SITE_TYPE_BLOG
+};
+
+class ContactWebSite {
+public:
+    ContactWebSite();
+    virtual ~ContactWebSite();
+
+    std::string getUrl() const;
+    void setUrl(const std::string &url);
+    ContactWebSiteType getType() const;
+    void setType(ContactWebSiteType type);
+    void importFromContactsRecord(contacts_record_h contacts_record,
+            unsigned int index);
+    void exportToContactsRecord(contacts_record_h contacts_record);
+
+private:
+    std::string m_url;
+    ContactWebSiteType m_type;
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif
diff --git a/src/Contact/JSAddressBook.cpp b/src/Contact/JSAddressBook.cpp
new file mode 100644 (file)
index 0000000..b56e25d
--- /dev/null
@@ -0,0 +1,910 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSAddressBook.h"
+#include "JSContact.h"
+#include "JSContactGroup.h"
+#include "JSSortMode.h"
+#include "ContactManager.h"
+
+#include "AddressBookCallbackData.h"
+#include "AddressBookChangeCallback.h"
+#include <Any.h>
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include "plugin_config.h"
+#include <SecurityExceptions.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+struct AddressBookHolder {
+    AddressBookPtr ptr;
+};
+
+namespace {
+const char* CONTACT_ADDRESS_BOOK = "AddressBook";
+
+const char* CONTACT_ADDRESS_BOOK_ID = "id";
+const char* CONTACT_ADDRESS_BOOK_NAME = "name";
+const char* CONTACT_ADDRESS_BOOK_READ_ONLY = "readOnly";
+const char* CONTACT_ADDRESS_BOOK_ACCOUNT_ID = "accountId";
+}
+
+JSClassDefinition JSAddressBook::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_ADDRESS_BOOK,
+        0,
+        m_property, //m_property,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL,
+        NULL,
+        NULL, //deleteProperty,
+        NULL,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSAddressBook::m_property[] = {
+    { CONTACT_ADDRESS_BOOK_ID, getId, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CONTACT_ADDRESS_BOOK_NAME, getName, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CONTACT_ADDRESS_BOOK_READ_ONLY, getReadOnly, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CONTACT_ADDRESS_BOOK_ACCOUNT_ID, getAccountId, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSAddressBook::m_function[] = {
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_GET, get, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD, add, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_BATCH, addBatch, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE, update, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_BATCH, updateBatch, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE, remove, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_BATCH, removeBatch, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_FIND, find, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_CHANGE_LISTENER, addChangeListener, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_CHANGE_LISTENER, removeChangeListener, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUP, getGroup, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_GROUP, addGroup, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_GROUP, updateGroup, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_GROUP, removeGroup, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUPS, getGroups, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSAddressBook::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSAddressBook::m_jsClassRef = JSClassCreate(JSAddressBook::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSAddressBook::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+AddressBookPtr JSAddressBook::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    AddressBookHolder* priv = static_cast<AddressBookHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSAddressBook::setPrivateObject(JSObjectRef object, AddressBookPtr native)
+{
+    AddressBookHolder* priv = static_cast<AddressBookHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSAddressBook::makeJSObject(JSContextRef context,
+        AddressBookPtr native)
+{
+    LOGD("Entered");
+    if (!native) {
+        LOGW("Native is null");
+        throw UnknownException("Native is null");
+    }
+    if (!native->isInitialized()) {
+        LOGD("Not initialized");
+        native->copyAceCheckAccessFunction(ContactManager::getInstance());
+    }
+
+    AddressBookHolder* priv = new(std::nothrow) AddressBookHolder();
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSAddressBook::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSAddressBook::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    AddressBookHolder* priv = static_cast<AddressBookHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSAddressBook::constructor(JSContextRef context,
+         JSObjectRef constructor,
+         size_t argumentCount,
+         const JSValueRef arguments[],
+         JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObj = JSObjectMake(context, getClassRef(), NULL);
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObj, ctorName, constructor, kJSPropertyAttributeReadOnly
+        | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        // accountId
+        unsigned long accountId = validator.toULong(0);
+        if (validator.isOmitted(0)) {
+            throw TypeMismatchException("account_id parameter is missed");
+        }
+        if (!AddressBook::isValidAccount(accountId)) {
+            throw InvalidValuesException("account_id is invalid");
+        }
+
+        // name
+        std::string name = validator.toString(1);
+        if (validator.isOmitted(1)) {
+            throw TypeMismatchException("addressbook name parameter is missed");
+        }
+
+        AddressBookPtr priv = AddressBookPtr(new(std::nothrow) AddressBook());
+        priv->setName(name);
+        priv->setAccountId(accountId);
+
+        AddressBookHolder* holder = new(std::nothrow) AddressBookHolder();
+        if(!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        holder->ptr->copyAceCheckAccessFunction(ContactManager::getInstance());
+        JSObjectSetPrivate(jsObj, static_cast<void *>(holder));
+    } catch (const BasePlatformException& err) {
+        LOGE("%s, %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return jsObj;
+}
+
+JSValueRef JSAddressBook::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, object);
+        if (!priv->isAddressBookIdSet()) {
+            return JSValueMakeNull(context);
+        }
+        std::string string_value = std::to_string(priv->getAddressBookId());
+        return JSUtil::toJSValueRef(context, string_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::getName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getName());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::getReadOnly(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getReadOnly());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::getAccountId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exeption)
+{
+    LOGD("Entered");
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getAccountId());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::get(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_GET);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        long contact_id = ContactUtil::toIntId(validator.toString(0));
+
+        ContactPtr contact = priv->get(contact_id);
+        return JSContact::makeJSObject(context, contact);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Get failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Get failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+JSValueRef JSAddressBook::add(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    SET_TIME_TRACER_ITEM(0);
+
+    try{
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        ContactPtr contact = JSContact::getPrivateObject(context, validator.toObject(0));
+
+        priv->add(contact);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Add failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Add failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::addBatch(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ContactArrayCallbackData *callback = NULL;
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_BATCH);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::vector<JSValueRef> js_contacts = validator.toJSValueRefVector(0, false);
+        std::shared_ptr<ContactPtrVector> contacts(new ContactPtrVector());
+
+        for_each(js_contacts.begin(), js_contacts.end(),
+                [&context, &contacts] (JSValueRef js_contact) {
+            contacts->push_back(JSContact::getPrivateObject(context, js_contact));
+        });
+
+        callback = new ContactArrayCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setContacts(contacts);
+
+        priv->addBatch(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("addBatch BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("addBatch fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "addBatch fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::update(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try{
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        ContactPtr contact = JSContact::getPrivateObject(context, validator.toObject(0));
+
+        priv->update(contact);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Update failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Update failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::updateBatch(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ContactArrayCallbackData *callback = NULL;
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_BATCH);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::vector<JSValueRef> js_contacts = validator.toJSValueRefVector(0, false);
+        std::shared_ptr<ContactPtrVector> contacts(new ContactPtrVector());
+
+        for_each(js_contacts.begin(), js_contacts.end(),
+                [&context, &contacts] (JSValueRef js_contact) {
+            contacts->push_back(JSContact::getPrivateObject(context, js_contact));
+        });
+
+        callback = new ContactArrayCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setContacts(contacts);
+
+        priv->updateBatch(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("updateBatch BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("updateBatch fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "updateBatch fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::remove(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try{
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        long contact_id = ContactUtil::toIntId(validator.toString(0));
+
+        priv->remove(contact_id);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Remove failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Remove failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::removeBatch(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    IdArrayCallbackData *callback = NULL;
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_BATCH);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::shared_ptr<LongVector> contact_ids(new LongVector(
+                validator.toLongVector(0, false)));
+
+        callback = new IdArrayCallbackData(
+             GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setIds(contact_ids);
+
+        priv->removeBatch(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("removeBatch BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("removeBatch fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "removeBatch fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::find(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    AddressBookFindCallbackData *callback = NULL;
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_FIND);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new AddressBookFindCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(0, false));
+        callback->setErrorCallback(validator.toFunction(1, true));
+
+        JSObjectRef filter = validator.toObject(2, true);
+        JSObjectRef sort_mode = validator.toObject(3, true);
+
+        if (filter) {
+            callback->setFilter(Tizen::AbstractFilter::getPrivateObject(
+                    context, filter));
+        }
+
+        if (sort_mode) {
+            callback->setSortMode(Tizen::JSSortMode::getPrivateObject(
+                    context, sort_mode));
+        }
+
+        priv->find(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("find BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("find fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "find fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::addChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_CHANGE_LISTENER);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef contactCallbackObj = validator.toCallbackObject(0,
+                false,
+                AddressBookChangeCallback::CALLBACK_CONTACTS_ADDED,
+                AddressBookChangeCallback::CALLBACK_CONTACTS_UPDATED,
+                AddressBookChangeCallback::CALLBACK_CONTACTS_REMOVED,
+                NULL);
+
+        AddressBookChangeCallbackPtr callback_ptr = AddressBookChangeCallbackPtr(
+                new(std::nothrow) AddressBookChangeCallback(
+                        GlobalContextManager::getInstance()->getGlobalContext(context),
+                        contactCallbackObj));
+
+        validator.toFunction(1, true);
+
+        if(!callback_ptr) {
+            LOGE("Memory allocation error");
+            throw UnknownException("Memory allocation error");
+        }
+
+        long callback_id = priv->addChangeListener(callback_ptr);
+
+        return JSUtil::toJSValueRef(context, callback_id);
+    } catch (const BasePlatformException &err) {
+        LOGE("addChangeListener BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("addChangeListener fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "addChangeListener fails");
+    }
+}
+
+JSValueRef JSAddressBook::removeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_CHANGE_LISTENER);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        long listener_id = validator.toLong(0);
+        if (listener_id <= 0) {
+            LOGE("invalid watchId");
+            throw InvalidValuesException("watchId is invalid");
+        }
+
+        priv->removeChangeListener(context, listener_id);
+    } catch (const BasePlatformException &err) {
+        LOGE("removeChangeListener BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("removeChangeListener fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "removeChangeListener fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::getGroup(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUP);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        long group_id = ContactUtil::toIntId(validator.toString(0));
+
+        ContactGroupPtr contact_group = priv->getGroup(group_id);
+        return JSContactGroup::makeJSObject(context, contact_group);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Get group failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Get group failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+JSValueRef JSAddressBook::addGroup(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_GROUP);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        ContactGroupPtr contact_group =
+                JSContactGroup::getPrivateObject(context,
+                        validator.toObject(0, JSContactGroup::getClassRef()));
+
+        priv->addGroup(contact_group);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Add group failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Add group failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::updateGroup(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_GROUP);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        ContactGroupPtr contact_group =
+                JSContactGroup::getPrivateObject(context,
+                        validator.toObject(0, JSContactGroup::getClassRef()));
+
+        priv->updateGroup(contact_group);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Update group failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Update group failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::removeGroup(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try{
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_GROUP);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        long group_id = ContactUtil::toIntId(validator.toString(0));
+
+        priv->removeGroup(group_id);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Remove group failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Remove group failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAddressBook::getGroups(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        AddressBookPtr priv = JSAddressBook::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUPS);
+
+        ContactGroupPtrVector to_return = priv->getGroups();
+        return ptrVectorToJSObjectArray<JSContactGroup, ContactGroupPtr>(to_return, context);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Get groups failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Get groups failed");
+        return JSWebAPIErrorFactory::postException(context,
+                exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSAddressBook.h b/src/Contact/JSAddressBook.h
new file mode 100755 (executable)
index 0000000..9e6888b
--- /dev/null
@@ -0,0 +1,204 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_ADDRESS_BOOK_H__
+#define __TIZEN_CONTACT_JS_ADDRESS_BOOK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "AddressBook.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSAddressBook {
+public:
+    static const JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static AddressBookPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, AddressBookPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, AddressBookPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef get(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getReadOnly(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAccountId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef add(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef update(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef updateBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef remove(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef find(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getGroup(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addGroup(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef updateGroup(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeGroup(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getGroups(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_ADDRESS_BOOK_H__
diff --git a/src/Contact/JSContact.cpp b/src/Contact/JSContact.cpp
new file mode 100644 (file)
index 0000000..c456fcb
--- /dev/null
@@ -0,0 +1,1490 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContact.h"
+#include "JSContactAddress.h"
+#include "JSContactName.h"
+#include "JSContactPhoneNumber.h"
+#include "JSContactEmailAddress.h"
+#include "JSContactAnniversary.h"
+#include "JSContactOrganization.h"
+#include "JSContactWebSite.h"
+#include "JSContactInstantMessenger.h"
+#include "JSContactRelationship.h"
+#include <CommonsJavaScript/Converter.h>
+
+#include <TimeTracer.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <SecurityExceptions.h>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactHolder {
+    ContactPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT = "Contact";
+
+const char* CONTACT_CONTACT_ID = "id";
+const char* CONTACT_CONTACT_PERSON_ID = "personId";
+const char* CONTACT_CONTACT_ADDRESS_BOOK_ID = "addressBookId";
+const char* CONTACT_CONTACT_LAST_UPDATED = "lastUpdated";
+const char* CONTACT_CONTACT_IS_FAVORITE = "isFavorite";
+const char* CONTACT_CONTACT_NAME = "name";
+const char* CONTACT_CONTACT_ADDRESSES = "addresses";
+const char* CONTACT_CONTACT_PHOTO_URI = "photoURI";
+const char* CONTACT_CONTACT_PHONE_NUMBERS = "phoneNumbers";
+const char* CONTACT_CONTACT_EMAILS = "emails";
+const char* CONTACT_CONTACT_MESSENGERS = "messengers";
+const char* CONTACT_CONTACT_RELATIONSHIPS = "relationships";
+const char* CONTACT_CONTACT_BIRTHDAY = "birthday";
+const char* CONTACT_CONTACT_ANNIVERSARIES = "anniversaries";
+const char* CONTACT_CONTACT_ORGANIZATIONS = "organizations";
+const char* CONTACT_CONTACT_NOTES = "notes";
+const char* CONTACT_CONTACT_URLS = "urls";
+const char* CONTACT_CONTACT_RINGTONE_URI = "ringtoneURI";
+const char* CONTACT_CONTACT_MESSAGE_ALERT_URI = "messageAlertURI";
+const char* CONTACT_CONTACT_VIBRATION_URI = "vibrationURI";
+const char* CONTACT_CONTACT_GROUP_IDS = "groupIds";
+const char* CONTACT_CONTACT_CONVERT_TO_STRING = "convertToString";
+const char* CONTACT_CONTACT_CLONE = "clone";
+
+const char* CONTACT_V_CARD_30 = "VCARD_30";
+}
+
+JSClassDefinition JSContact::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT,
+        0,
+        m_property, //m_property,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL,
+        NULL,
+        NULL, //deleteProperty,
+        NULL,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContact::m_property[] = {
+    { CONTACT_CONTACT_ID, getId, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CONTACT_CONTACT_PERSON_ID, getPersonId, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CONTACT_CONTACT_ADDRESS_BOOK_ID, getAddressBookId, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CONTACT_CONTACT_LAST_UPDATED, getLastUpdated, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CONTACT_CONTACT_IS_FAVORITE, getIsFavorite, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { CONTACT_CONTACT_NAME, getName, setName, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_ADDRESSES, getAddresses, setAddresses, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_PHOTO_URI, getPhotoUri, setPhotoUri, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_PHONE_NUMBERS, getPhoneNumbers, setPhoneNumbers, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_EMAILS, getEmails, setEmails, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_MESSENGERS, getMessengers, setMessengers, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_RELATIONSHIPS, getRelationships, setRelationships, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_BIRTHDAY, getBirthday, setBirthday, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_ANNIVERSARIES, getAnniversaries, setAnniversaries, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_ORGANIZATIONS, getOrganizations, setOrganizations, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NOTES, getNotes, setNotes, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_URLS, getUrls, setUrls, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_RINGTONE_URI, getRingtoneUri, setRingtoneUri, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_MESSAGE_ALERT_URI, getMessageAlertUri, setMessageAlertUri, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_VIBRATION_URI, getVibrationUri, setVibrationUri, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_GROUP_IDS, getGroupIds, setGroupIds, kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSContact::m_function[] =
+{
+        { CONTACT_CONTACT_CONVERT_TO_STRING, convertToString, kJSPropertyAttributeNone },
+        { CONTACT_CONTACT_CLONE, clone, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContact::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContact::m_jsClassRef = JSClassCreate(JSContact::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContact::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactPtr JSContact::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactHolder* priv = static_cast<ContactHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContact::setPrivateObject(JSObjectRef object, ContactPtr native)
+{
+    ContactHolder* priv = static_cast<ContactHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContact::makeJSObject(JSContextRef context,
+        ContactPtr native)
+{
+    if (!native) {
+        LOGW("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactHolder* priv = new(std::nothrow) ContactHolder();
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContact::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContact::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContactHolder* priv = static_cast<ContactHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContact::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    enum JSContactConstructorType {
+        CONTACT_CONSTRUCTOR_TYPE_NO_PARAMS,
+        CONTACT_CONSTRUCTOR_TYPE_OBJECT,
+        CONTACT_CONSTRUCTOR_TYPE_STRING
+    };
+
+    JSContactConstructorType constructor_type = CONTACT_CONSTRUCTOR_TYPE_NO_PARAMS;
+    try {
+        if (validator.isOmitted(0) || validator.isNull(0)) {
+            constructor_type = CONTACT_CONSTRUCTOR_TYPE_NO_PARAMS;
+        }
+        else if (JSValueIsObject(context, arguments[0])) {
+            constructor_type = CONTACT_CONSTRUCTOR_TYPE_OBJECT;
+        }
+        else {
+            constructor_type = CONTACT_CONSTRUCTOR_TYPE_STRING;
+        }
+
+        ContactPtr priv = ContactPtr(new(std::nothrow) Contact());
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        switch (constructor_type) {
+            case CONTACT_CONSTRUCTOR_TYPE_NO_PARAMS:
+                // nothing to be done
+                break;
+
+            case CONTACT_CONSTRUCTOR_TYPE_OBJECT:
+            {
+                JSObjectRef dictionary = NULL;
+                dictionary = validator.toObject(0, true);
+
+                if (dictionary) {
+                    JSValueRef name = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_NAME);
+                    JSValueRef addresses = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_ADDRESSES);
+                    JSValueRef photo_uri = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_PHOTO_URI);
+                    JSValueRef phone_numbers = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_PHONE_NUMBERS);
+                    JSValueRef emails = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_EMAILS);
+                    JSValueRef messengers = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_MESSENGERS);
+                    JSValueRef relationships = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_RELATIONSHIPS);
+                    JSValueRef birthday = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_BIRTHDAY);
+                    JSValueRef anniversaries = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_ANNIVERSARIES);
+                    JSValueRef organizations = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_ORGANIZATIONS);
+                    JSValueRef notes = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_NOTES);
+                    JSValueRef urls = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_URLS);
+                    JSValueRef ringtone_uri = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_RINGTONE_URI);
+                    JSValueRef message_alert_uri = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_MESSAGE_ALERT_URI);
+                    JSValueRef vibration_uri = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_VIBRATION_URI);
+                    JSValueRef group_ids = JSUtil::getProperty(context,
+                            dictionary, CONTACT_CONTACT_GROUP_IDS);
+
+                    if (!JSValueIsUndefined(context, name)
+                            && !JSValueIsNull(context, name)) {
+                        ContactNamePtr ptr_name = JSContactName::getPrivateObject(context, name);
+                        priv->setName(ptr_name);
+                    }
+                    if (!JSValueIsUndefined(context, addresses)
+                            && !JSValueIsNull(context, addresses)) {
+                        ContactAddressPtrVector ptr_addresses =
+                                JSUtil::JSArrayToType_(context, addresses, JSContactAddress::getPrivateObject);
+                        priv->setAddresses(ptr_addresses);
+                    }
+                    if (!JSValueIsUndefined(context, photo_uri)
+                            && !JSValueIsNull(context, photo_uri)) {
+                        priv->setPhotoUri(JSUtil::JSValueToString(context, photo_uri));
+                    }
+                    if (!JSValueIsUndefined(context, phone_numbers)
+                            && !JSValueIsNull(context, phone_numbers)) {
+                        ContactPhoneNumberPtrVector ptr_phone_numbers =
+                                JSUtil::JSArrayToType_(context, phone_numbers, JSContactPhoneNumber::getPrivateObject);
+                        priv->setPhoneNumbers(ptr_phone_numbers);
+                    }
+                    if (!JSValueIsUndefined(context, emails)
+                            && !JSValueIsNull(context, emails)) {
+                        ContactEmailAddressPtrVector ptr_emails =
+                                JSUtil::JSArrayToType_(context, emails, JSContactEmailAddress::getPrivateObject);
+                        priv->setEmails(ptr_emails);
+                    }
+                    if (!JSValueIsUndefined(context, messengers)
+                            && !JSValueIsNull(context, messengers)) {
+                        ContactInstantMessengerPtrVector ptr_messengers =
+                                JSUtil::JSArrayToType_(context, messengers, JSContactInstantMessenger::getPrivateObject);
+                        priv->setMessengers(ptr_messengers);
+                    }
+                    if (!JSValueIsUndefined(context, relationships)
+                            && !JSValueIsNull(context, relationships)) {
+                        ContactRelationshipPtrVector ptr_relationships =
+                                JSUtil::JSArrayToType_(context, relationships, JSContactRelationship::getPrivateObject);
+                        priv->setRelationships(ptr_relationships);
+                    }
+                    if (!JSValueIsUndefined(context, birthday)
+                            && !JSValueIsNull(context, birthday)) {
+                        tm tms = WrtDeviceApis::CommonsJavaScript::Converter(context).toDateTm(birthday);
+                        priv->setBirthday(tms);
+                    }
+                    if (!JSValueIsUndefined(context, anniversaries)
+                            && !JSValueIsNull(context, anniversaries)) {
+                        ContactAnniversaryPtrVector ptr_anniversaries =
+                                JSUtil::JSArrayToType_(context, anniversaries, JSContactAnniversary::getPrivateObject);
+                        priv->setAnniversaries(ptr_anniversaries);
+                    }
+                    if (!JSValueIsUndefined(context, organizations)
+                            && !JSValueIsNull(context, organizations)) {
+                        ContactOrganizationPtrVector ptr_organizations =
+                                JSUtil::JSArrayToType_(context, organizations, JSContactOrganization::getPrivateObject);
+                        priv->setOrganizations(ptr_organizations);
+                    }
+                    if (!JSValueIsUndefined(context, notes)
+                            && !JSValueIsNull(context, notes)) {
+                        priv->setNotes(JSUtil::JSArrayToStringVector(context, notes));
+                    }
+                    if (!JSValueIsUndefined(context, urls)
+                            && !JSValueIsNull(context, urls)) {
+                        ContactWebSitePtrVector ptr_urls =
+                                JSUtil::JSArrayToType_(context, urls, JSContactWebSite::getPrivateObject);
+                        priv->setUrls(ptr_urls);
+                    }
+                    if (!JSValueIsUndefined(context, ringtone_uri)
+                            && !JSValueIsNull(context, ringtone_uri)) {
+                        priv->setRingtoneUri(JSUtil::JSValueToString(context, ringtone_uri));
+                    }
+                    if (!JSValueIsUndefined(context, message_alert_uri)
+                                && !JSValueIsNull(context, message_alert_uri)) {
+                            priv->setMessageAlertUri(JSUtil::JSValueToString(context, message_alert_uri));
+                    }
+                    if (!JSValueIsUndefined(context, vibration_uri)
+                            && !JSValueIsNull(context, vibration_uri)) {
+                        priv->setVibrationUri(JSUtil::JSValueToString(context, vibration_uri));
+                    }
+                    if (!JSValueIsUndefined(context, group_ids)
+                            && !JSValueIsNull(context, group_ids)) {
+                        priv->setGroupIds(JSUtil::JSArrayToLongVector(context, group_ids));
+                    }
+                }
+            }
+                break;
+
+            case CONTACT_CONSTRUCTOR_TYPE_STRING:
+                std::string vcard = validator.toString(0, false);
+                priv->importFromVCard(vcard);
+                break;
+        }
+
+        ContactHolder* holder = new(std::nothrow) ContactHolder();
+        if (!holder) {
+            LOGW("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Contact creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Contact creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContact::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_ID)) {
+            return JSValueMakeNull(context);
+        }
+        std::string string_value = std::to_string(priv->getId());
+        return JSUtil::toJSValueRef(context, string_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getPersonId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_PERSON_ID)) {
+            return JSValueMakeNull(context);
+        }
+        std::string string_value = std::to_string(priv->getPersonId());
+        return JSUtil::toJSValueRef(context, string_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getAddressBookId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_ADDRESS_BOOK_ID)) {
+            return JSValueMakeNull(context);
+        }
+        std::string string_value = std::to_string(priv->getAddressBookId());
+        return JSUtil::toJSValueRef(context, string_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getLastUpdated(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_LAST_UPDATED)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::makeDateObject(context, priv->getLastUpdated());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getIsFavorite(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getIsFavorite());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_NAME)) {
+            return JSValueMakeNull(context);
+        }
+        return JSContactName::makeJSObject(context, priv->getName());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getAddresses(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return toJSObjectArray<ContactAddressPtr, JSContactAddress>(context,
+                priv->getAddresses());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getPhotoUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_PHOTO_URI)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getPhotoUri());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getPhoneNumbers(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return toJSObjectArray<ContactPhoneNumberPtr, JSContactPhoneNumber>(context,
+                priv->getPhoneNumbers());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getEmails(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return toJSObjectArray<ContactEmailAddressPtr, JSContactEmailAddress>(context,
+                priv->getEmails());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getMessengers(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return toJSObjectArray<ContactInstantMessengerPtr, JSContactInstantMessenger>(context,
+                priv->getMessengers());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getRelationships(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return toJSObjectArray<ContactRelationshipPtr, JSContactRelationship>(context,
+                priv->getRelationships());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getBirthday(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_BIRTHDAY)) {
+            return JSValueMakeNull(context);
+        }
+        return WrtDeviceApis::
+                CommonsJavaScript::Converter(context).toJSValueRef(priv->getBirthday());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getAnniversaries(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        return priv->getJSAnniversaries(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getOrganizations(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return toJSObjectArray<ContactOrganizationPtr, JSContactOrganization>(context,
+                priv->getOrganizations());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getNotes(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getNotes());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getUrls(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return toJSObjectArray<ContactWebSitePtr, JSContactWebSite>(context,
+                priv->getUrls());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getRingtoneUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_RINGTONE_URI)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getRingtoneUri());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getMessageAlertUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_MESSAGE_ALERT_URI)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getMessageAlertUri());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getVibrationUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAttribute::CONTACT_ATTRIBUTE_VIBRATION_URI)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getVibrationUri());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContact::getGroupIds(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        LongVector group_ids = priv->getGroupIds();
+        StringVector str_group_ids;
+        size_t size = group_ids.size();
+        for(size_t i = 0; i < size; i++){
+            str_group_ids.push_back(std::to_string(group_ids[i]));
+        }
+        return JSUtil::toJSValueRef(context, str_group_ids);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContact::setName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_NAME, false);
+            return true;
+        }
+        ContactNamePtr ptr_name = JSContactName::getPrivateObject(context, value);
+        priv->setName(ptr_name);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setAddresses(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+           ContactAddressPtrVector empty_vector;
+           priv->setAddresses(empty_vector);
+           return true;
+       }
+       ContactAddressPtrVector ptr_addresses =
+               JSUtil::JSArrayToType_(context, value, JSContactAddress::getPrivateObject);
+       priv->setAddresses(ptr_addresses);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setPhotoUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setPhotoUri("");
+            priv->setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_PHOTO_URI, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setPhotoUri(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setPhoneNumbers(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            ContactPhoneNumberPtrVector empty_vector;
+            priv->setPhoneNumbers(empty_vector);
+            return true;
+        }
+        ContactPhoneNumberPtrVector ptr_phone_numbers =
+                JSUtil::JSArrayToType_(context, value, JSContactPhoneNumber::getPrivateObject);
+        priv->setPhoneNumbers(ptr_phone_numbers);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setEmails(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            ContactEmailAddressPtrVector empty_vector;
+            priv->setEmails(empty_vector);
+            return true;
+        }
+        ContactEmailAddressPtrVector ptr_emails =
+                JSUtil::JSArrayToType_(context, value, JSContactEmailAddress::getPrivateObject);
+        priv->setEmails(ptr_emails);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setMessengers(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            ContactInstantMessengerPtrVector empty_vector;
+            priv->setMessengers(empty_vector);
+            return true;
+        }
+        ContactInstantMessengerPtrVector ptr_messengers =
+                JSUtil::JSArrayToType_(context, value, JSContactInstantMessenger::getPrivateObject);
+        priv->setMessengers(ptr_messengers);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setRelationships(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            ContactRelationshipPtrVector empty_vector;
+            priv->setRelationships(empty_vector);
+            return true;
+        }
+        ContactRelationshipPtrVector ptr_relationships =
+                JSUtil::JSArrayToType_(context, value, JSContactRelationship::getPrivateObject);
+        priv->setRelationships(ptr_relationships);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setBirthday(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            tm tm_ = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+            priv->setBirthday(tm_);
+            priv->setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_BIRTHDAY, false);
+            return true;
+        }
+        tm tm_ = WrtDeviceApis::CommonsJavaScript::Converter(context).toDateTm(value);
+        priv->setBirthday(tm_);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setAnniversaries(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            ContactAnniversaryPtrVector empty_vector;
+            priv->setAnniversaries(empty_vector);
+            return true;
+        }
+        ContactAnniversaryPtrVector ptr_anniversaries =
+                JSUtil::JSArrayToType_(context, value, JSContactAnniversary::getPrivateObject);
+        priv->setAnniversaries(ptr_anniversaries);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setOrganizations(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            ContactOrganizationPtrVector empty_vector;
+            priv->setOrganizations(empty_vector);
+            return true;
+        }
+        ContactOrganizationPtrVector ptr_organizations =
+                JSUtil::JSArrayToType_(context, value, JSContactOrganization::getPrivateObject);
+        priv->setOrganizations(ptr_organizations);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setNotes(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        StringVector _value = JSUtil::JSArrayToStringVector(context, value);
+        priv->setNotes(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setUrls(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            ContactWebSitePtrVector empty_vector;
+            priv->setUrls(empty_vector);
+            return true;
+        }
+        ContactWebSitePtrVector ptr_urls =
+                JSUtil::JSArrayToType_(context, value, JSContactWebSite::getPrivateObject);
+        priv->setUrls(ptr_urls);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setRingtoneUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setRingtoneUri("");
+            priv->setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_RINGTONE_URI, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setRingtoneUri(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setMessageAlertUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setMessageAlertUri("");
+            priv->setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_MESSAGE_ALERT_URI, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setMessageAlertUri(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setVibrationUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setVibrationUri("");
+            priv->setIsSet(ContactAttribute::CONTACT_ATTRIBUTE_VIBRATION_URI, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setVibrationUri(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+bool JSContact::setGroupIds(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+
+        ContactPtr priv = JSContact::getPrivateObject(context, object);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        LongVector _value = JSUtil::JSArrayToLongVector(context, value);
+        priv->setGroupIds(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSContact::convertToString(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    SET_TIME_TRACER_ITEM(0);
+
+    std::string str_format, str_vcard;
+    ContactTextFormat format;
+    ArgumentValidator validator(context, argumentCount, arguments);
+    try {
+        ContactPtr priv = JSContact::getPrivateObject(context, thisObject);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw Common::UnknownException("Priv is null");
+        }
+
+        str_format = validator.toString(0, true, CONTACT_V_CARD_30);
+        if (CONTACT_V_CARD_30 != str_format) {
+            throw TypeMismatchException("Unsupported format");
+        }
+        format = CONTACT_TEXT_FORMAT_VCARD_30;
+        str_vcard = priv->convertToString(format);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("convertToString failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("convertToString failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    JSValueRef result = JSValueMakeString(
+            context,
+            JSStringCreateWithUTF8CString(str_vcard.c_str()));
+    return result;
+
+}
+
+JSValueRef JSContact::clone(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    SET_TIME_TRACER_ITEM(0);
+
+    try{
+        ContactPtr priv = JSContact::getPrivateObject(context, thisObject);
+        if (!priv) {
+            LOGW("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        ContactPtr cloned = priv->clone();
+        JSObjectRef result = JSContact::makeJSObject(context, cloned);
+        return result;
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Clone failed: %s", error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    }
+    catch (...) {
+        LOGE("Clone failed");
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContact.h b/src/Contact/JSContact.h
new file mode 100755 (executable)
index 0000000..f00e5ec
--- /dev/null
@@ -0,0 +1,321 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_H__
+#define __TIZEN_CONTACT_JS_CONTACT_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include "Contact.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContact {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPersonId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAddressBookId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLastUpdated(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsFavorite(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAddresses(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPhotoUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPhoneNumbers(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getEmails(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMessengers(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getRelationships(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getBirthday(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAnniversaries(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getOrganizations(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getNotes(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getUrls(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getRingtoneUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMessageAlertUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getVibrationUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getGroupIds(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setAddresses(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setPhotoUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setPhoneNumbers(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setEmails(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setMessengers(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setRelationships(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setBirthday(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setAnniversaries(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setOrganizations(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setNotes(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setUrls(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setRingtoneUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setMessageAlertUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setVibrationUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setGroupIds(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef convertToString(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef clone(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    template<class T, class U>
+    static JSObjectRef toJSObjectArray(JSContextRef context,
+            const std::vector<T> & vec)
+    {
+        size_t vec_size = vec.size();
+        if(0 == vec_size){
+            JSObjectRef empty = JSObjectMakeArray(context, 0, NULL, NULL);
+            if (!empty) {
+                LOGW("Empty array is null");
+                throw Common::UnknownException("Empty array is null");
+            }
+            return empty;
+        }
+        JSObjectRef array[vec_size];
+        for (size_t i = 0; i < vec_size; i++) {
+            array[i] = U::makeJSObject(context, vec[i]);
+        }
+        JSObjectRef result = JSObjectMakeArray(context, vec_size, array, NULL);
+        if (!result) {
+            LOGW("Array is null");
+            throw Common::UnknownException("Array is null");
+        }
+        return result;
+    }
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_H__
diff --git a/src/Contact/JSContactAddress.cpp b/src/Contact/JSContactAddress.cpp
new file mode 100755 (executable)
index 0000000..8e67c9c
--- /dev/null
@@ -0,0 +1,756 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactAddress.h"
+#include "ContactAddress.h"
+#include "ContactUtil.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include <algorithm>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactAddressHolder {
+    ContactAddressPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_ADDRESS = "ContactAddress";
+
+const char* CONTACT_CONTACT_ADDRESS_COUNTRY = "country";
+const char* CONTACT_CONTACT_ADDRESS_REGION = "region";
+const char* CONTACT_CONTACT_ADDRESS_CITY = "city";
+const char* CONTACT_CONTACT_ADDRESS_STREET_ADDRESS = "streetAddress";
+const char* CONTACT_CONTACT_ADDRESS_ADDITIONAL_INFORMATION = "additionalInformation";
+const char* CONTACT_CONTACT_ADDRESS_POSTAL_CODE = "postalCode";
+const char* CONTACT_CONTACT_ADDRESS_IS_DEFAULT = "isDefault";
+const char* CONTACT_CONTACT_ADDRESS_TYPES = "types";
+const char* CONTACT_CONTACT_ADDRESS_LABEL = "label";
+}
+
+JSClassDefinition JSContactAddress::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_ADDRESS,
+        NULL,
+        JSContactAddress::m_property,
+        NULL, //m_function,
+        JSContactAddress::initialize,
+        JSContactAddress::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactAddress::m_property[] = {
+        { CONTACT_CONTACT_ADDRESS_COUNTRY, getCountry, setCountry, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ADDRESS_REGION, getRegion, setRegion, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ADDRESS_CITY, getCity, setCity, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ADDRESS_STREET_ADDRESS, getStreetAddress, setStreetAddress, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ADDRESS_ADDITIONAL_INFORMATION, getAdditionalInformation, setAdditionalInformation, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ADDRESS_POSTAL_CODE, getPostalCode, setPostalCode, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ADDRESS_IS_DEFAULT, getIsDefault, setIsDefault, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ADDRESS_TYPES, getTypes, setTypes, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ADDRESS_LABEL, getLabel, setLabel, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactAddress::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactAddress::m_jsClassRef = JSClassCreate(JSContactAddress::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactAddress::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactAddressPtr JSContactAddress::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactAddressHolder* priv = static_cast<ContactAddressHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactAddress::setPrivateObject(JSObjectRef object, ContactAddressPtr native)
+{
+    ContactAddressHolder* priv = static_cast<ContactAddressHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactAddress::makeJSObject(JSContextRef context,
+        ContactAddressPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactAddressHolder* priv = new(std::nothrow) ContactAddressHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactAddress::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContactAddress::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContactAddressHolder* priv = static_cast<ContactAddressHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactAddress::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        JSObjectRef dictionary = NULL;
+        dictionary = validator.toObject(0, true);
+
+        ContactAddressPtr priv = ContactAddressPtr(new(std::nothrow) ContactAddress());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        if (dictionary) {
+            JSValueRef country = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ADDRESS_COUNTRY);
+            JSValueRef region = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ADDRESS_REGION);
+            JSValueRef city = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ADDRESS_CITY);
+            JSValueRef street_address = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ADDRESS_STREET_ADDRESS);
+            JSValueRef additional_information = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ADDRESS_ADDITIONAL_INFORMATION);
+            JSValueRef postal_code = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ADDRESS_POSTAL_CODE);
+            JSValueRef is_default = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ADDRESS_IS_DEFAULT);
+            JSValueRef address_types = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ADDRESS_TYPES);
+            JSValueRef label = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ADDRESS_LABEL);
+
+            if (!JSValueIsUndefined(context, country)
+                    && !JSValueIsNull(context, country)) {
+                priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_COUNTRY, JSUtil::JSValueToString(context, country));
+            }
+            if (!JSValueIsUndefined(context, region)
+                    && !JSValueIsNull(context, region)) {
+                priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_REGION, JSUtil::JSValueToString(context, region));
+            }
+            if (!JSValueIsUndefined(context, city)
+                    && !JSValueIsNull(context, city)) {
+                priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_CITY, JSUtil::JSValueToString(context, city));
+            }
+            if (!JSValueIsUndefined(context, street_address)
+                    && !JSValueIsNull(context, street_address)) {
+                priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_STREETADDR, JSUtil::JSValueToString(context, street_address));
+            }
+            if (!JSValueIsUndefined(context, additional_information)
+                    && !JSValueIsNull(context, additional_information)) {
+                priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO, JSUtil::JSValueToString(context, additional_information));
+            }
+            if (!JSValueIsUndefined(context, postal_code)
+                    && !JSValueIsNull(context, postal_code)) {
+                priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE, JSUtil::JSValueToString(context, postal_code));
+            }
+            if (!JSValueIsUndefined(context, is_default)) {
+                priv->setIsDefault(JSUtil::JSValueToBoolean(context, is_default));
+            }
+            if (!JSValueIsUndefined(context, address_types)) {
+                std::vector<std::string> str_types = JSUtil::JSArrayToStringVector(context, address_types);
+                size_t size = str_types.size();
+                if (size > 0) {
+                    for (size_t i = 0; i < size; i++) {
+                        // Verification if string is actual from ContactEmailAddressType
+                        ContactUtil::stringToContactAddressType(str_types[i]);
+                    }
+                    priv->setTypes(str_types);
+                }
+            }
+            if (!JSValueIsUndefined(context, label)
+                    && !JSValueIsNull(context, label)) {
+                priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_LABEL, JSUtil::JSValueToString(context, label));
+            }
+        }
+
+        ContactAddressHolder* holder = new(std::nothrow) ContactAddressHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactAddress creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactAddress creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactAddress::getCountry(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_COUNTRY)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_COUNTRY));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact address country. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact address country.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactAddress::getRegion(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_REGION)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_REGION));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact address region. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact address region.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactAddress::getCity(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_CITY)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_CITY));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact address city. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact address city.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactAddress::getStreetAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_STREETADDR)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_STREETADDR));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact address street address. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact address street address.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactAddress::getAdditionalInformation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact address additional information. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact address additional information.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactAddress::getPostalCode(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact address postal code. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact address postal code.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactAddress::getIsDefault(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getIsDefault());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact address is default flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact address is default flag.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactAddress::getTypes(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return priv->getJSTypes(GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact address types. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact address types.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactAddress::getLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if(!priv->isSet(CONTACT_ADDRESS_ATTRIBUTE_LABEL)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(CONTACT_ADDRESS_ATTRIBUTE_LABEL));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact address label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact address label.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactAddress::setCountry(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_COUNTRY, "");
+            priv->setIsSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_COUNTRY, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_COUNTRY, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact address country. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact address country.");
+    }
+    return true;
+}
+
+bool JSContactAddress::setRegion(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_REGION, "");
+            priv->setIsSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_REGION, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_REGION, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact address region. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact address region.");
+    }
+    return true;
+}
+
+bool JSContactAddress::setCity(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_CITY, "");
+            priv->setIsSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_CITY, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_CITY, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact address city. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact address city.");
+    }
+    return true;
+}
+
+bool JSContactAddress::setStreetAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_STREETADDR, "");
+            priv->setIsSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_STREETADDR, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_STREETADDR, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact address street address. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact address street address.");
+    }
+    return true;
+}
+
+bool JSContactAddress::setAdditionalInformation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO, "");
+            priv->setIsSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_ADDITIONALINFO, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact address additional information. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact address additional information.");
+    }
+    return true;
+}
+
+bool JSContactAddress::setPostalCode(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE, "");
+            priv->setIsSet(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactAddressAttribute::CONTACT_ADDRESS_ATTRIBUTE_POSTALCODE, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact address postal code. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact address postal code.");
+    }
+    return true;
+}
+
+bool JSContactAddress::setIsDefault(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        bool is_default = JSUtil::JSValueToBoolean(context, value);
+        priv->setIsDefault(is_default);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact address is default flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact address is default flag.");
+    }
+    return true;
+}
+
+bool JSContactAddress::setTypes(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::vector<std::string> str_types = JSUtil::JSArrayToStringVector(context, value);
+        size_t size = str_types.size();
+        if (size > 0) {
+            for (size_t i = 0; i < size; i++) {
+                // Verification if string is actual from ContactEmailAddressType
+                ContactUtil::stringToContactAddressType(str_types[i]);
+            }
+            priv->setTypes(str_types);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact address types. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact address types.");
+    }
+    return true;
+}
+
+bool JSContactAddress::setLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAddressPtr priv = JSContactAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setIsSet(CONTACT_ADDRESS_ATTRIBUTE_LABEL, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(CONTACT_ADDRESS_ATTRIBUTE_LABEL, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact address label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact address label.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactAddress.h b/src/Contact/JSContactAddress.h
new file mode 100755 (executable)
index 0000000..45beba3
--- /dev/null
@@ -0,0 +1,173 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_ADDRESS_H__
+#define __TIZEN_CONTACT_JS_CONTACT_ADDRESS_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactAddress.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactAddress {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactAddressPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactAddressPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactAddressPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getCountry(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getRegion(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCity(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getStreetAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAdditionalInformation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPostalCode(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsDefault(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTypes(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setCountry(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setRegion(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCity(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setStreetAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setAdditionalInformation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setPostalCode(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setIsDefault(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setTypes(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_ADDRESS_H__
diff --git a/src/Contact/JSContactAnniversary.cpp b/src/Contact/JSContactAnniversary.cpp
new file mode 100644 (file)
index 0000000..d2746f6
--- /dev/null
@@ -0,0 +1,301 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactAnniversary.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <CommonsJavaScript/Converter.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactAnniversaryHolder {
+    ContactAnniversaryPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_ANNIVERSARY = "ContactAnniversary";
+
+const char* CONTACT_CONTACT_ANNIVERSARY_DATE = "date";
+const char* CONTACT_CONTACT_ANNIVERSARY_LABEL = "label";
+}
+
+JSClassDefinition JSContactAnniversary::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_ANNIVERSARY,
+        NULL,
+        JSContactAnniversary::m_property,
+        NULL, //m_function,
+        JSContactAnniversary::initialize,
+        JSContactAnniversary::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactAnniversary::m_property[] = {
+        { CONTACT_CONTACT_ANNIVERSARY_DATE, getDate, setDate, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ANNIVERSARY_LABEL, getLabel, setLabel, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactAnniversary::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactAnniversary::m_jsClassRef = JSClassCreate(JSContactAnniversary::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactAnniversary::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactAnniversaryPtr JSContactAnniversary::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactAnniversaryHolder* priv = static_cast<ContactAnniversaryHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactAnniversary::setPrivateObject(JSObjectRef object, ContactAnniversaryPtr native)
+{
+    ContactAnniversaryHolder* priv = static_cast<ContactAnniversaryHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactAnniversary::makeJSObject(JSContextRef context,
+        ContactAnniversaryPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactAnniversaryHolder* priv = new(std::nothrow) ContactAnniversaryHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactAnniversary::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContactAnniversary::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+
+    ContactAnniversaryHolder* priv = static_cast<ContactAnniversaryHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactAnniversary::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        std::string label;
+
+        label = validator.toString(1, true, "");
+        ContactAnniversaryPtr priv = ContactAnniversaryPtr(new(std::nothrow) ContactAnniversary());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        tm tm_ = WrtDeviceApis::CommonsJavaScript::Converter(context).toDateTm(arguments[0]);
+        priv->setDate(tm_);
+
+        if (!validator.isNull(1) && !validator.isOmitted(1)) {
+            priv->setLabel(label);
+        }
+
+        ContactAnniversaryHolder* holder = new(std::nothrow) ContactAnniversaryHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactAnniversary creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactAnniversary creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactAnniversary::getDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAnniversaryPtr priv = JSContactAnniversary::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return WrtDeviceApis::CommonsJavaScript::Converter(context).toJSValueRef(priv->getDate());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact anniversary date. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact anniversary date.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactAnniversary::getLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAnniversaryPtr priv = JSContactAnniversary::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isLabelSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getLabel());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact anniversary label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact anniversary label.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactAnniversary::setDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAnniversaryPtr priv = JSContactAnniversary::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        tm tm_ = WrtDeviceApis::CommonsJavaScript::Converter(context).toDateTm(value);
+        priv->setDate(tm_);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact anniversary date. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact anniversary date.");
+    }
+    return true;
+}
+
+bool JSContactAnniversary::setLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactAnniversaryPtr priv = JSContactAnniversary::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetLabel();
+        }
+        else {
+            std::string label = JSUtil::JSValueToString(context, value);
+            priv->setLabel(label);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact anniversary label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact anniversary label.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactAnniversary.h b/src/Contact/JSContactAnniversary.h
new file mode 100755 (executable)
index 0000000..93da2bd
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_ANNIVERSARY_H__
+#define __TIZEN_CONTACT_JS_CONTACT_ANNIVERSARY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactAnniversary.h"
+#include <JSArray.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactAnniversary;
+typedef Common::JSObjectArray
+        <ContactAnniversaryPtr, JSContactAnniversary> JSContactAnniversaryArray;
+
+class JSContactAnniversary {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactAnniversaryPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactAnniversaryPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactAnniversaryPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_ANNIVERSARY_H__
diff --git a/src/Contact/JSContactEmailAddress.cpp b/src/Contact/JSContactEmailAddress.cpp
new file mode 100755 (executable)
index 0000000..f258146
--- /dev/null
@@ -0,0 +1,423 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactEmailAddress.h"
+#include "ContactUtil.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactEmailAddressHolder {
+    ContactEmailAddressPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_EMAIL_ADDRESS = "ContactEmailAddress";
+
+const char* CONTACT_CONTACT_EMAIL_ADDRESS_EMAIL = "email";
+const char* CONTACT_CONTACT_EMAIL_ADDRESS_IS_DEFAULT = "isDefault";
+const char* CONTACT_CONTACT_EMAIL_ADDRESS_TYPES = "types";
+const char* CONTACT_CONTACT_EMAIL_ADDRESS_LABEL = "label";
+}
+
+JSClassDefinition JSContactEmailAddress::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_EMAIL_ADDRESS,
+        NULL,
+        JSContactEmailAddress::m_property,
+        NULL, //m_function,
+        JSContactEmailAddress::initialize,
+        JSContactEmailAddress::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactEmailAddress::m_property[] = {
+        { CONTACT_CONTACT_EMAIL_ADDRESS_EMAIL, getEmail, setEmail, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_EMAIL_ADDRESS_IS_DEFAULT, getIsDefault, setIsDefault, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_EMAIL_ADDRESS_TYPES, getTypes, setTypes, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_EMAIL_ADDRESS_LABEL, getLabel, setLabel, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactEmailAddress::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactEmailAddress::m_jsClassRef = JSClassCreate(JSContactEmailAddress::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactEmailAddress::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactEmailAddressPtr JSContactEmailAddress::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactEmailAddressHolder* priv =
+            static_cast<ContactEmailAddressHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactEmailAddress::setPrivateObject(JSObjectRef object, ContactEmailAddressPtr native)
+{
+    ContactEmailAddressHolder* priv =
+            static_cast<ContactEmailAddressHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactEmailAddress::makeJSObject(JSContextRef context,
+        ContactEmailAddressPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactEmailAddressHolder* priv = new(std::nothrow) ContactEmailAddressHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactEmailAddress::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContactEmailAddress::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContactEmailAddressHolder* priv =
+            static_cast<ContactEmailAddressHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactEmailAddress::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        std::string email;
+        bool is_default = false;
+        std::vector<std::string> str_types;
+
+        email = validator.toString(0);
+        is_default = validator.toBool(2, true, false);
+        str_types = validator.toStringVector(1, true);
+
+        ContactEmailAddressPtr priv =
+                ContactEmailAddressPtr(new(std::nothrow) ContactEmailAddress());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        priv->setEmail(email);
+        priv->setIsDefault(is_default);
+
+        size_t size = str_types.size();
+        if (size > 0) {
+            for (size_t i = 0; i < size; i++) {
+                // Verification if string is actual from ContactEmailAddressType
+                ContactUtil::stringToContactEmailAddressType(str_types[i]);
+            }
+            priv->setTypes(str_types);
+        }
+
+        ContactEmailAddressHolder* holder = new(std::nothrow) ContactEmailAddressHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactEmailAddress creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactEmailAddress creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactEmailAddress::getEmail(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactEmailAddressPtr priv = JSContactEmailAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getEmail());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact email address. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact email address.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactEmailAddress::getIsDefault(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactEmailAddressPtr priv = JSContactEmailAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getIsDefault());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact email address is default flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact email address is default flag.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactEmailAddress::getTypes(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactEmailAddressPtr priv = JSContactEmailAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        return priv->getJSTypes(GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact email address types. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact email address types.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactEmailAddress::getLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactEmailAddressPtr priv = JSContactEmailAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if(!priv->isLabelSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getLabel());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact email address label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact email address label.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactEmailAddress::setEmail(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactEmailAddressPtr priv = JSContactEmailAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string email = JSUtil::JSValueToString(context, value);
+        priv->setEmail(email);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact email address. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact email address.");
+    }
+    return true;
+}
+
+bool JSContactEmailAddress::setIsDefault(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactEmailAddressPtr priv = JSContactEmailAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        bool is_default = JSUtil::JSValueToBoolean(context, value);
+        priv->setIsDefault(is_default);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact email address is default flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact email address is default flag.");
+    }
+    return true;
+}
+
+bool JSContactEmailAddress::setTypes(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactEmailAddressPtr priv = JSContactEmailAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::vector<std::string> str_types = JSUtil::JSArrayToStringVector(context, value);
+        size_t size = str_types.size();
+        if (size > 0) {
+            for (size_t i = 0; i < size; i++) {
+                // Verification if string is actual from ContactEmailAddressType
+                ContactUtil::stringToContactEmailAddressType(str_types[i]);
+            }
+            priv->setTypes(str_types);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact email address types. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact email address types.");
+    }
+    return true;
+}
+
+bool JSContactEmailAddress::setLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactEmailAddressPtr priv = JSContactEmailAddress::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetLabel();
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setLabel(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact email address label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact email address label.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactEmailAddress.h b/src/Contact/JSContactEmailAddress.h
new file mode 100755 (executable)
index 0000000..6e830b0
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_EMAIL_ADDRESS_H__
+#define __TIZEN_CONTACT_JS_CONTACT_EMAIL_ADDRESS_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactEmailAddress.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactEmailAddress {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactEmailAddressPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactEmailAddressPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactEmailAddressPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getEmail(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsDefault(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTypes(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setEmail(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setIsDefault(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setTypes(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_EMAIL_ADDRESS_H__
diff --git a/src/Contact/JSContactGroup.cpp b/src/Contact/JSContactGroup.cpp
new file mode 100644 (file)
index 0000000..1961bc0
--- /dev/null
@@ -0,0 +1,444 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactGroup.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactGroupHolder {
+    ContactGroupPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_GROUP = "ContactGroup";
+
+const char* CONTACT_CONTACT_GROUP_ID = "id";
+const char* CONTACT_CONTACT_GROUP_ADDRESS_BOOK_ID = "addressBookId";
+const char* CONTACT_CONTACT_GROUP_NAME = "name";
+const char* CONTACT_CONTACT_GROUP_RINGTONE_URI = "ringtoneURI";
+const char* CONTACT_CONTACT_GROUP_PHOTO_URI = "photoURI";
+const char* CONTACT_CONTACT_GROUP_READ_ONLY = "readOnly";
+}
+
+JSClassDefinition JSContactGroup::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_GROUP,
+        NULL,
+        JSContactGroup::m_property,
+        NULL, //m_function,
+        JSContactGroup::initialize,
+        JSContactGroup::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactGroup::m_property[] = {
+    { CONTACT_CONTACT_GROUP_ID, getId, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_GROUP_ADDRESS_BOOK_ID, getAddressBookId, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_GROUP_NAME, getName, setName, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_GROUP_RINGTONE_URI, getRingtoneURI, setRingtoneURI, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_GROUP_PHOTO_URI, getPhotoURI, setPhotoURI, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_GROUP_READ_ONLY, getReadOnly, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactGroup::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactGroup::m_jsClassRef = JSClassCreate(JSContactGroup::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactGroup::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactGroupPtr JSContactGroup::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactGroupHolder* priv = static_cast<ContactGroupHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactGroup::setPrivateObject(JSObjectRef object, ContactGroupPtr native)
+{
+    ContactGroupHolder* priv = static_cast<ContactGroupHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactGroup::makeJSObject(JSContextRef context,
+        ContactGroupPtr native)
+{
+    if (!native) {
+        LOGW("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactGroupHolder* priv = new(std::nothrow) ContactGroupHolder();
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactGroup::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("ContactGroup initialize entered");
+}
+
+void JSContactGroup::finalize(JSObjectRef object)
+{
+    LOGD("ContactGroup finalize entered");
+    ContactGroupHolder* priv = static_cast<ContactGroupHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactGroup::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("ContactGroup constructor entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        std::string name;
+        std::string ringtoneURI;
+        std::string photoURI;
+
+        name = validator.toString(0);
+        ringtoneURI = validator.toString(1, true, "");
+        photoURI = validator.toString(2, true, "");
+
+        ContactGroupPtr priv = ContactGroupPtr(new(std::nothrow) ContactGroup());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        priv->setName(name);
+        if (!validator.isNull(1) && !validator.isOmitted(1)) {
+            priv->setRingtoneURI(ringtoneURI);
+        }
+        if (!validator.isNull(2) && !validator.isOmitted(2)) {
+            priv->setPhotoURI(photoURI);
+        }
+
+        ContactGroupHolder* holder = new(std::nothrow) ContactGroupHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactGroup creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactGroup creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactGroup::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactGroupPtr priv = JSContactGroup::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->getIdIsSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getId());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact group id. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact group id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactGroup::getAddressBookId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactGroupPtr priv = JSContactGroup::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->getAddressBookIdIsSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAddressBookId());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact group address book id. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact group address book id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactGroup::getName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactGroupPtr priv = JSContactGroup::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getName());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact group name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact group name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactGroup::getRingtoneURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactGroupPtr priv = JSContactGroup::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->getRingtoneURIIsSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getRingtoneURI());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact group ringtone URI. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact group ringtone uri.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactGroup::getPhotoURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactGroupPtr priv = JSContactGroup::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->getPhotoURIIsSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getPhotoURI());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact group photo URI. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact group photo URI.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactGroup::getReadOnly(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactGroupPtr priv = JSContactGroup::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getReadOnly());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact group read only. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact group read only.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactGroup::setName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactGroupPtr priv = JSContactGroup::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string groupName = JSUtil::JSValueToString(context, value);
+        priv->setName(groupName);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact group name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact group name.");
+    }
+    return true;
+}
+
+bool JSContactGroup::setRingtoneURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactGroupPtr priv = JSContactGroup::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetRingtoneURI();
+        }
+        else {
+            std::string ringtoneURI = JSUtil::JSValueToString(context, value);
+            priv->setRingtoneURI(ringtoneURI);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact group ringtone URI. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact group ringtone URI.");
+    }
+    return true;
+}
+
+bool JSContactGroup::setPhotoURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactGroupPtr priv = JSContactGroup::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetPhotoURI();
+        }
+        else {
+            std::string photoURI = JSUtil::JSValueToString(context, value);
+            priv->setPhotoURI(photoURI);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact group photo URI. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact group photo URI.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactGroup.h b/src/Contact/JSContactGroup.h
new file mode 100755 (executable)
index 0000000..cf90768
--- /dev/null
@@ -0,0 +1,123 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_GROUP_H__
+#define __TIZEN_CONTACT_JS_CONTACT_GROUP_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactGroup.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactGroup {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static ContactGroupPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactGroupPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactGroupPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAddressBookId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getRingtoneURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPhotoURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getReadOnly(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setRingtoneURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setPhotoURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_GROUP_H__
diff --git a/src/Contact/JSContactInstantMessenger.cpp b/src/Contact/JSContactInstantMessenger.cpp
new file mode 100644 (file)
index 0000000..2df130e
--- /dev/null
@@ -0,0 +1,356 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactInstantMessenger.h"
+#include "ContactInstantMessenger.h"
+#include "ContactUtil.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include <algorithm>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactInstantMessengerHolder {
+    ContactInstantMessengerPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_INSTANT_MESSENGER = "ContactInstantMessenger";
+
+const char* CONTACT_CONTACT_INSTANT_MESSENGER_IM_ADDRESS = "imAddress";
+const char* CONTACT_CONTACT_INSTANT_MESSENGER_TYPE = "type";
+const char* CONTACT_CONTACT_INSTANT_MESSENGER_LABEL = "label";
+}
+
+JSClassDefinition JSContactInstantMessenger::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_INSTANT_MESSENGER,
+        NULL,
+        JSContactInstantMessenger::m_property,
+        NULL, //m_function,
+        JSContactInstantMessenger::initialize,
+        JSContactInstantMessenger::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactInstantMessenger::m_property[] = {
+        { CONTACT_CONTACT_INSTANT_MESSENGER_IM_ADDRESS, getImAddress, setImAddress, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_INSTANT_MESSENGER_TYPE, getType, setType, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_INSTANT_MESSENGER_LABEL, getLabel, setLabel, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactInstantMessenger::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactInstantMessenger::m_jsClassRef = JSClassCreate(JSContactInstantMessenger::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactInstantMessenger::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactInstantMessengerPtr JSContactInstantMessenger::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactInstantMessengerHolder* priv = static_cast<ContactInstantMessengerHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactInstantMessenger::setPrivateObject(JSObjectRef object, ContactInstantMessengerPtr native)
+{
+    ContactInstantMessengerHolder* priv = static_cast<ContactInstantMessengerHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactInstantMessenger::makeJSObject(JSContextRef context,
+        ContactInstantMessengerPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactInstantMessengerHolder* priv = new(std::nothrow) ContactInstantMessengerHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactInstantMessenger::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContactInstantMessenger::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContactInstantMessengerHolder* priv = static_cast<ContactInstantMessengerHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactInstantMessenger::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        std::string imAddress = validator.toString(0);
+        std::string type = validator.toString(1, true);
+
+        ContactInstantMessengerPtr priv = ContactInstantMessengerPtr(new(std::nothrow) ContactInstantMessenger());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        priv->setImAddress(imAddress);
+        try {
+            priv->setType(ContactUtil::stringToInstantMessengerType(type));
+        }
+        catch (const BasePlatformException &error) {
+            LOGD("Setting type to default");
+            priv->setType(CONTACT_IM_TYPE_OTHER);
+        }
+
+        ContactInstantMessengerHolder* holder = new(std::nothrow) ContactInstantMessengerHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactAddress creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactAddress creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactInstantMessenger::getImAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactInstantMessengerPtr priv = JSContactInstantMessenger::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getImAddress());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get IM address. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting IM address.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactInstantMessenger::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactInstantMessengerPtr priv = JSContactInstantMessenger::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string  str_type = ContactUtil::contactInstantMessengerTypeToString(priv->getType());
+        return JSUtil::toJSValueRef(context, str_type);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get type. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting type.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactInstantMessenger::getLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactInstantMessengerPtr priv = JSContactInstantMessenger::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if(!priv->isLabelSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getLabel());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting label.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactInstantMessenger::setImAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactInstantMessengerPtr priv = JSContactInstantMessenger::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setImAddress(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set IM address. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting IM address.");
+    }
+    return true;
+}
+
+bool JSContactInstantMessenger::setType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactInstantMessengerPtr priv = JSContactInstantMessenger::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setType(ContactUtil::stringToInstantMessengerType(_value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set type. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting type.");
+    }
+    return true;
+}
+
+bool JSContactInstantMessenger::setLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactInstantMessengerPtr priv = JSContactInstantMessenger::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetLabel();
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setLabel(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting label.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactInstantMessenger.h b/src/Contact/JSContactInstantMessenger.h
new file mode 100644 (file)
index 0000000..8c80f6b
--- /dev/null
@@ -0,0 +1,107 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_INSTANT_MESSENGER_H__
+#define __TIZEN_CONTACT_JS_CONTACT_INSTANT_MESSENGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactInstantMessenger.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactInstantMessenger {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactInstantMessengerPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactInstantMessengerPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactInstantMessengerPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getImAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setImAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif /* __TIZEN_CONTACT_JS_CONTACT_INSTANT_MESSENGER_H__ */
diff --git a/src/Contact/JSContactManager.cpp b/src/Contact/JSContactManager.cpp
new file mode 100644 (file)
index 0000000..8f39e52
--- /dev/null
@@ -0,0 +1,645 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactManager.h"
+#include "ContactManager.h"
+
+#include "JSAddressBook.h"
+#include "JSPerson.h"
+#include "ContactManagerCallbackData.h"
+#include <AbstractFilter.h>
+#include <JSSortMode.h>
+#include <Any.h>
+#include <Logger.h>
+#include <memory>
+#include <TimeTracer.h>
+#include <Export.h>
+#include "plugin_config.h"
+#include <SecurityExceptions.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include <GlobalContextManager.h>
+#include <CallbackUserData.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+namespace {
+const char* CONTACT_CONTACT_MANAGER = "ContactManager";
+}
+
+JSClassDefinition JSContactManager::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_MANAGER,
+        0,
+        NULL, //m_property,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticFunction JSContactManager::m_function[] = {
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOKS, getAddressBooks, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_UNIFIED_ADDRESS_BOOK, getUnifiedAddressBook, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_DEFAULT_ADDRESS_BOOK, getDefaultAddressBook, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOK, getAddressBook, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_ADDRESS_BOOK, addAddressBook, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_ADDRESS_BOOK, removeAddressBook, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_GET, get, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE, update, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE_BATCH, updateBatch, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE, remove, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_BATCH, removeBatch, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_FIND, find, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_CHANGE_LISTENER, addChangeListener, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_CHANGE_LISTENER, removeChangeListener, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactManager::m_jsClassRef = JSClassCreate(JSContactManager::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSContactManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered ContactManager initialize");
+    JSObjectSetPrivate(object, static_cast<void*>(&ContactManager::getInstance()));
+}
+
+void JSContactManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered ContactManager finalize");
+}
+
+JSValueRef JSContactManager::getAddressBooks(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    GetAddressBooksCallbackData *callback = NULL;
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOKS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new GetAddressBooksCallbackData(
+             GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(0, false));
+        callback->setErrorCallback(validator.toFunction(1, true));
+
+        ContactManager::getInstance().getAddressBooks(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getAddressBooks BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("getAddressBooks fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getUnifiedAddressBook fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactManager::getUnifiedAddressBook(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_UNIFIED_ADDRESS_BOOK);
+
+        return JSAddressBook::makeJSObject(context,
+                ContactManager::getInstance().getUnifiedAddressBook());
+    } catch (const BasePlatformException &err) {
+        LOGE("getUnifiedAddressBook BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getUnifiedAddressBook fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getUnifiedAddressBook fails");
+    }
+}
+
+JSValueRef JSContactManager::getDefaultAddressBook(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_DEFAULT_ADDRESS_BOOK);
+
+        return JSAddressBook::makeJSObject(context,
+                ContactManager::getInstance().getDefaultAddressBook());
+    } catch (const BasePlatformException &err) {
+        LOGE("getDefaultAddressBook BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getDefaultAddressBook fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getDefaultAddressBook fails");
+    }
+}
+
+JSValueRef JSContactManager::getAddressBook(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOK);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        long address_book_id = 0;
+
+        try {
+            address_book_id = ContactUtil::toIntId(validator.toString(0,false));
+        }
+        catch (const BasePlatformException &err) {
+            throw NotFoundException("AddressBook cannot be found");
+        }
+        return JSAddressBook::makeJSObject(context,
+                ContactManager::getInstance().getAddressBook(address_book_id));
+    } catch (const BasePlatformException &err) {
+        LOGE("getAddressBook BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getAddressBook fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getAddressBook fails");
+    }
+}
+
+JSValueRef JSContactManager::addAddressBook(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_ADDRESS_BOOK);
+
+        auto &priv = ContactManager::getInstance();
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // address book
+        JSObjectRef addressbookObj = validator.toObject(0, JSAddressBook::getClassRef());
+        AddressBookPtr addressbook = JSAddressBook::getPrivateObject(context, addressbookObj);
+        if (!addressbook) {
+            throw TypeMismatchException("AddressBook's private object is NULL");
+        }
+
+        priv.addAddressBook(addressbook);
+    } catch (const BasePlatformException &err) {
+        LOGE("addAddressBook BasePlatformException caught: name: %s, msg: %s",
+            err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("addAddressBook fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "addAddressBook fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactManager::removeAddressBook(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_ADDRESS_BOOK);
+
+        auto &priv = ContactManager::getInstance();
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        long address_book_id =
+            static_cast<long>(ContactUtil::toIntId(validator.toString(0)));
+
+        priv.removeAddressBook(address_book_id);
+    } catch (const BasePlatformException &err) {
+        LOGE("removeAddressBook BasePlatformException caught: name: %s, msg: %s",
+            err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("removeAddressBook fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "removeAddressBook fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactManager::get(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_GET);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        long person_id = ContactUtil::toIntId(validator.toString(0));
+        return JSPerson::makeJSObject(context,
+                ContactManager::getInstance().get(person_id));
+    } catch (const BasePlatformException &err) {
+        LOGE("get BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("get fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "get fails");
+    }
+}
+
+JSValueRef JSContactManager::update(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef person = validator.toObject(0, JSPerson::getClassRef(), false);
+
+        ContactManager::getInstance().update(JSPerson::getPrivateObject(context, person));
+    } catch (const BasePlatformException &err) {
+        LOGE("get BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("get fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "get fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactManager::updateBatch(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    UpdateBatchCallbackData *callback = NULL;
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE_BATCH);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::vector<JSValueRef> js_persons = validator.toJSValueRefVector(0, false);
+        std::shared_ptr<PersonPtrVector> persons(new PersonPtrVector());
+
+        for_each(js_persons.begin(), js_persons.end(),
+                [context, &persons] (JSValueRef js_person) {
+            persons->push_back(JSPerson::getPrivateObject(context, js_person));
+        });
+
+        callback = new UpdateBatchCallbackData(
+             GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setPersons(persons);
+
+        ContactManager::getInstance().updateBatch(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("updateBatch BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("updateBatch fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "updateBatch fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactManager::remove(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        ContactManager::getInstance().remove(
+                ContactUtil::toIntId(validator.toString(0)));
+    } catch (const BasePlatformException &err) {
+        LOGE("get BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("get fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "get fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactManager::removeBatch(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    RemoveBatchCallbackData *callback = NULL;
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_BATCH);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::shared_ptr<LongVector> person_ids(new LongVector(
+                validator.toLongVector(0, false)));
+
+        callback = new RemoveBatchCallbackData(
+             GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setPersonIds(person_ids);
+
+        ContactManager::getInstance().removeBatch(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("removeBatch BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("removeBatch fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "removeBatch fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactManager::find(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM( 0);
+    LOGD("Entered");
+
+    FindCallbackData *callback = NULL;
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_FIND);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        callback = new FindCallbackData(
+             GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(0, false));
+        callback->setErrorCallback(validator.toFunction(1, true));
+
+        JSObjectRef filter = validator.toObject(2, true);
+        JSObjectRef sort_mode = validator.toObject(3, true);
+
+        if (filter) {
+            callback->setFilter(Tizen::AbstractFilter::getPrivateObject(
+                    context, filter));
+        }
+
+        if (sort_mode) {
+            callback->setSortMode(Tizen::JSSortMode::getPrivateObject(
+                    context, sort_mode));
+        }
+
+        ContactManager::getInstance().find(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("find BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("find fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "find fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactManager::addChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_CHANGE_LISTENER);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef contactCallbackObj = validator.toCallbackObject(0,
+                false,
+                PersonChangeCallback::CALLBACK_PERSONS_ADDED,
+                PersonChangeCallback::CALLBACK_PERSONS_UPDATED,
+                PersonChangeCallback::CALLBACK_PERSONS_REMOVED,
+                NULL);
+
+        PersonChangeCallbackPtr callback_ptr = PersonChangeCallbackPtr(
+                new(std::nothrow) PersonChangeCallback(
+                        GlobalContextManager::getInstance()->getGlobalContext(context),
+                        contactCallbackObj));
+
+        if(!callback_ptr) {
+            LOGE("Memory allocation error");
+            throw UnknownException("Memory allocation error");
+        }
+
+        long callback_id = ContactManager::getInstance().addChangeListener(callback_ptr);
+
+        return JSUtil::toJSValueRef(context, callback_id);
+    } catch (const BasePlatformException &err) {
+        LOGE("addChangeListener BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("addChangeListener fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "addChangeListener fails");
+    }
+}
+
+JSValueRef JSContactManager::removeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContactManager::getInstance(),
+                CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_CHANGE_LISTENER);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        long listener_id = validator.toLong(0);
+        if (listener_id <= 0) {
+            LOGE("invalid watchId");
+            throw InvalidValuesException("watchId is invalid");
+        }
+
+        ContactManager::getInstance().removeChangeListener(context, listener_id);
+    } catch (const BasePlatformException &err) {
+        LOGE("removeChangeListener BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("removeChangeListener fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "removeChangeListener fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactManager.h b/src/Contact/JSContactManager.h
new file mode 100755 (executable)
index 0000000..b93716f
--- /dev/null
@@ -0,0 +1,194 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_MANAGER_H__
+#define __TIZEN_CONTACT_JS_CONTACT_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactManager {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * The callback invoked when getting a property's value.
+     */
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * The callback invoked when setting a property's value.
+     */
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * The callback invoked when collecting the names of an object's properties.
+     */
+    static void getPropertyNames(JSContextRef context,
+            JSObjectRef object,
+            JSPropertyNameAccumulatorRef propertyNames);
+
+    /**
+     * Get Address Books.
+     */
+    static JSValueRef getAddressBooks(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Get Unified Address Book.
+     */
+    static JSValueRef getUnifiedAddressBook(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Get Default Address Book.
+     */
+    static JSValueRef getDefaultAddressBook(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Get Address Book.
+     */
+    static JSValueRef getAddressBook(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addAddressBook(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeAddressBook(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef get(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef update(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef updateBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef remove(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef find(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif //__TIZEN_CONTACT_JS_CONTACT_MANAGER_H__
diff --git a/src/Contact/JSContactName.cpp b/src/Contact/JSContactName.cpp
new file mode 100644 (file)
index 0000000..c02f66f
--- /dev/null
@@ -0,0 +1,778 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactName.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactNameHolder {
+    ContactNamePtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_NAME = "ContactName";
+
+const char* CONTACT_CONTACT_NAME_PREFIX = "prefix";
+const char* CONTACT_CONTACT_NAME_SUFFIX = "suffix";
+const char* CONTACT_CONTACT_NAME_FIRST_NAME = "firstName";
+const char* CONTACT_CONTACT_NAME_MIDDLE_NAME = "middleName";
+const char* CONTACT_CONTACT_NAME_LAST_NAME = "lastName";
+const char* CONTACT_CONTACT_NAME_NICKNAMES = "nicknames";
+const char* CONTACT_CONTACT_NAME_PHONETIC_FIRST_NAME = "phoneticFirstName";
+const char* CONTACT_CONTACT_NAME_PHONETIC_MIDDLE_NAME = "phoneticMiddleName";
+const char* CONTACT_CONTACT_NAME_PHONETIC_LAST_NAME = "phoneticLastName";
+const char* CONTACT_CONTACT_NAME_DISPLAY_NAME = "displayName";
+}
+
+JSClassDefinition JSContactName::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_NAME,
+        NULL,
+        JSContactName::m_property,
+        NULL, //m_function,
+        JSContactName::initialize,
+        JSContactName::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactName::m_property[] = {
+    { CONTACT_CONTACT_NAME_PREFIX, getPrefix, setPrefix, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NAME_SUFFIX, getSuffix, setSuffix, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NAME_FIRST_NAME, getFirstName, setFirstName, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NAME_MIDDLE_NAME, getMiddleName, setMiddleName, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NAME_LAST_NAME, getLastName, setLastName, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NAME_NICKNAMES, getNicknames, setNicknames, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NAME_PHONETIC_FIRST_NAME, getPhoneticFirstName, setPhoneticFirstName, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NAME_PHONETIC_MIDDLE_NAME, getPhoneticMiddleName, setPhoneticMiddleName, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NAME_PHONETIC_LAST_NAME, getPhoneticLastName, setPhoneticLastName, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_NAME_DISPLAY_NAME, getDisplayName, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactName::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactName::m_jsClassRef = JSClassCreate(JSContactName::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactName::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactNamePtr JSContactName::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactNameHolder* priv = static_cast<ContactNameHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactName::setPrivateObject(JSObjectRef object, ContactNamePtr native)
+{
+    ContactNameHolder* priv = static_cast<ContactNameHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactName::makeJSObject(JSContextRef context,
+        ContactNamePtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactNameHolder* priv = new(std::nothrow) ContactNameHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactName::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContactName::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContactNameHolder* priv = static_cast<ContactNameHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactName::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        JSObjectRef dictionary = NULL;
+        dictionary = validator.toObject(0, true);
+
+        ContactNamePtr priv = ContactNamePtr(new(std::nothrow) ContactName());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        if (dictionary) {
+            JSValueRef prefix = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_NAME_PREFIX);
+            JSValueRef suffix = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_NAME_SUFFIX);
+            JSValueRef first_name = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_NAME_FIRST_NAME);
+            JSValueRef middle_name = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_NAME_MIDDLE_NAME);
+            JSValueRef last_name = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_NAME_LAST_NAME);
+            JSValueRef nicknames = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_NAME_NICKNAMES);
+            JSValueRef phonetic_first_name = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_NAME_PHONETIC_FIRST_NAME);
+            JSValueRef phonetic_middle_name = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_NAME_PHONETIC_MIDDLE_NAME);
+            JSValueRef phonetic_last_name = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_NAME_PHONETIC_LAST_NAME);
+
+            if (!JSValueIsUndefined(context, prefix)
+                    && !JSValueIsNull(context, prefix)) {
+                priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PREFIX, JSUtil::JSValueToString(context, prefix));
+            }
+            if (!JSValueIsUndefined(context, suffix)
+                    && !JSValueIsNull(context, suffix)) {
+                priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_SUFFIX, JSUtil::JSValueToString(context, suffix));
+            }
+            if (!JSValueIsUndefined(context, first_name)
+                    && !JSValueIsNull(context, first_name)) {
+                priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_FIRST_NAME, JSUtil::JSValueToString(context, first_name));
+            }
+            if (!JSValueIsUndefined(context, middle_name)
+                    && !JSValueIsNull(context, middle_name)) {
+                priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME, JSUtil::JSValueToString(context, middle_name));
+            }
+            if (!JSValueIsUndefined(context, last_name)
+                    && !JSValueIsNull(context, last_name)) {
+                priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_LAST_NAME, JSUtil::JSValueToString(context, last_name));
+            }
+            if (!JSValueIsUndefined(context, nicknames)
+                    && !JSValueIsNull(context, nicknames)) {
+                priv->setNicknames(JSUtil::JSArrayToStringVector(context, nicknames));
+            }
+            if (!JSValueIsUndefined(context, phonetic_first_name)
+                    && !JSValueIsNull(context, phonetic_first_name)) {
+                priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME, JSUtil::JSValueToString(context, phonetic_first_name));
+            }
+            if (!JSValueIsUndefined(context, phonetic_middle_name)
+                    && !JSValueIsNull(context, phonetic_middle_name)) {
+                priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME, JSUtil::JSValueToString(context, phonetic_middle_name));
+            }
+            if (!JSValueIsUndefined(context, phonetic_last_name)
+                    && !JSValueIsNull(context, phonetic_last_name)) {
+                priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME, JSUtil::JSValueToString(context, phonetic_last_name));
+            }
+        }
+
+        ContactNameHolder* holder = new(std::nothrow) ContactNameHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactName creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactName creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactName::getPrefix(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PREFIX)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PREFIX));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact name prefix. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact name prefix.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactName::getSuffix(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_SUFFIX)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_SUFFIX));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact name suffix. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact name suffix.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactName::getFirstName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_FIRST_NAME)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_FIRST_NAME));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact first name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact first name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactName::getMiddleName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact middle name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact middle name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactName::getLastName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_LAST_NAME)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_LAST_NAME));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact last name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact last name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactName::getNicknames(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return priv->getJSNicknames(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact nicknames. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact nicknames.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactName::getPhoneticFirstName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact phonetic first name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact phonetic first name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactName::getPhoneticMiddleName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact phonetic middle name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact phonetic middle name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactName::getPhoneticLastName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact phonetic last name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact phonetic last name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactName::getDisplayName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (!priv->isSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_DISPLAY_NAME)) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_DISPLAY_NAME));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact display name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact display name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactName::setPrefix(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PREFIX, "");
+            priv->setIsSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PREFIX, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PREFIX, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact name prefix. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact name prefix.");
+    }
+    return true;
+}
+
+bool JSContactName::setSuffix(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_SUFFIX, "");
+            priv->setIsSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_SUFFIX, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_SUFFIX, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact name suffix. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact name suffix.");
+    }
+    return true;
+}
+
+bool JSContactName::setFirstName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_FIRST_NAME, "");
+            priv->setIsSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_FIRST_NAME, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_FIRST_NAME, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact first name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact first name.");
+    }
+    return true;
+}
+
+bool JSContactName::setMiddleName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME, "");
+            priv->setIsSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_MIDDLE_NAME, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact middle name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact middle name.");
+    }
+    return true;
+}
+
+bool JSContactName::setLastName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_LAST_NAME, "");
+            priv->setIsSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_LAST_NAME, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_LAST_NAME, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact last name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact last name.");
+    }
+    return true;
+}
+
+bool JSContactName::setNicknames(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::vector<std::string> _value = JSUtil::JSArrayToStringVector(context, value);
+        priv->setNicknames(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact nicknames. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact nicknames.");
+    }
+    return true;
+}
+
+bool JSContactName::setPhoneticFirstName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME, "");
+            priv->setIsSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_FIRST_NAME, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact phonetic first name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact phonetic first name.");
+    }
+    return true;
+}
+
+bool JSContactName::setPhoneticMiddleName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME, "");
+            priv->setIsSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_MIDDLE_NAME, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact phonetic middle name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact phonetic middle name.");
+    }
+    return true;
+}
+
+bool JSContactName::setPhoneticLastName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactNamePtr priv = JSContactName::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME, "");
+            priv->setIsSet(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME, false);
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setAttribute(ContactNameAttribute::CONTACT_NAME_ATTRIBUTE_PHONETIC_LAST_NAME, _value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact phonetic last name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact phonetic last name.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactName.h b/src/Contact/JSContactName.h
new file mode 100755 (executable)
index 0000000..21f4308
--- /dev/null
@@ -0,0 +1,179 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_NAME_H__
+#define __TIZEN_CONTACT_JS_CONTACT_NAME_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactName.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactName {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactNamePtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactNamePtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactNamePtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getPrefix(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getSuffix(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getFirstName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMiddleName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLastName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getNicknames(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPhoneticFirstName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPhoneticMiddleName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPhoneticLastName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDisplayName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setPrefix(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setSuffix(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setFirstName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setMiddleName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setLastName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setNicknames(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setPhoneticFirstName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setPhoneticMiddleName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setPhoneticLastName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_NAME_H__
diff --git a/src/Contact/JSContactOrganization.cpp b/src/Contact/JSContactOrganization.cpp
new file mode 100644 (file)
index 0000000..999f8a2
--- /dev/null
@@ -0,0 +1,508 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactOrganization.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactOrganizationHolder {
+    ContactOrganizationPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_ORGANIZATION = "ContactOrganization";
+
+const char* CONTACT_CONTACT_ORGANIZATION_NAME = "name";
+const char* CONTACT_CONTACT_ORGANIZATION_DEPARTMENT = "department";
+const char* CONTACT_CONTACT_ORGANIZATION_TITLE = "title";
+const char* CONTACT_CONTACT_ORGANIZATION_ROLE = "role";
+const char* CONTACT_CONTACT_ORGANIZATION_LOGO_URI = "logoURI";
+}
+
+JSClassDefinition JSContactOrganization::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_ORGANIZATION,
+        NULL,
+        JSContactOrganization::m_property,
+        NULL, //m_function,
+        JSContactOrganization::initialize,
+        JSContactOrganization::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactOrganization::m_property[] = {
+        { CONTACT_CONTACT_ORGANIZATION_NAME, getName, setName, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ORGANIZATION_DEPARTMENT, getDepartment, setDepartment, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ORGANIZATION_TITLE, getTitle, setTitle, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ORGANIZATION_ROLE, getRole, setRole, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_ORGANIZATION_LOGO_URI, getLogoURI, setLogoURI, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactOrganization::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactOrganization::m_jsClassRef = JSClassCreate(JSContactOrganization::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactOrganization::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactOrganizationPtr JSContactOrganization::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactOrganizationHolder* priv =
+            static_cast<ContactOrganizationHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactOrganization::setPrivateObject(JSObjectRef object, ContactOrganizationPtr native)
+{
+    ContactOrganizationHolder* priv =
+            static_cast<ContactOrganizationHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactOrganization::makeJSObject(JSContextRef context,
+        ContactOrganizationPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactOrganizationHolder* priv = new(std::nothrow) ContactOrganizationHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactOrganization::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContactOrganization::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+
+    ContactOrganizationHolder* priv =
+            static_cast<ContactOrganizationHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactOrganization::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        JSObjectRef dictionary = NULL;
+        dictionary = validator.toObject(0, true);
+
+        ContactOrganizationPtr priv =
+                ContactOrganizationPtr(new(std::nothrow) ContactOrganization());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        if (dictionary) {
+            JSValueRef name = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ORGANIZATION_NAME);
+            JSValueRef department = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ORGANIZATION_DEPARTMENT);
+            JSValueRef title = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ORGANIZATION_TITLE);
+            JSValueRef role = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ORGANIZATION_ROLE);
+            JSValueRef logoURI = JSUtil::getProperty(context, dictionary, CONTACT_CONTACT_ORGANIZATION_LOGO_URI);
+
+            if (!JSValueIsUndefined(context, name)
+                    && !JSValueIsNull(context, name)) {
+                priv->setName(JSUtil::JSValueToString(context, name));
+            }
+            if (!JSValueIsUndefined(context, department)
+                    && !JSValueIsNull(context, department)) {
+                priv->setDepartment(JSUtil::JSValueToString(context, department));
+            }
+            if (!JSValueIsUndefined(context, title)
+                    && !JSValueIsNull(context, title)) {
+                priv->setTitle(JSUtil::JSValueToString(context, title));
+            }
+            if (!JSValueIsUndefined(context, role)
+                    && !JSValueIsNull(context, role)) {
+                priv->setRole(JSUtil::JSValueToString(context, role));
+            }
+            if (!JSValueIsUndefined(context, logoURI)
+                    && !JSValueIsNull(context, logoURI)) {
+                priv->setLogoURI(JSUtil::JSValueToString(context, logoURI));
+            }
+        }
+
+        ContactOrganizationHolder* holder = new(std::nothrow) ContactOrganizationHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactOrganization creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactOrganization creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactOrganization::getName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (priv->isNameSet()) {
+            return JSUtil::toJSValueRef(context, priv->getName());
+        }
+        return JSValueMakeNull(context);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact organization name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact organization name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactOrganization::getDepartment(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (priv->isDepartmentSet()) {
+            return JSUtil::toJSValueRef(context, priv->getDepartment());
+        }
+        return JSValueMakeNull(context);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact organization department. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact organization department.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactOrganization::getTitle(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (priv->isTitleSet()) {
+            return JSUtil::toJSValueRef(context, priv->getTitle());
+        }
+        return JSValueMakeNull(context);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact organization title. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact organization title.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactOrganization::getRole(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (priv->isRoleSet()) {
+            return JSUtil::toJSValueRef(context, priv->getRole());
+        }
+        return JSValueMakeNull(context);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact organization role. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact organization role.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactOrganization::getLogoURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (priv->isLogoURISet()) {
+            return JSUtil::toJSValueRef(context, priv->getLogoURI());
+        }
+        return JSValueMakeNull(context);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact organization logo URI. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact organization logo URI.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactOrganization::setName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetName();
+        }
+        else {
+            std::string name = JSUtil::JSValueToString(context, value);
+            priv->setName(name);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact organization name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact organization name.");
+    }
+    return true;
+}
+
+bool JSContactOrganization::setDepartment(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetDepartment();
+        }
+        else {
+            std::string dept = JSUtil::JSValueToString(context, value);
+            priv->setDepartment(dept);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact organization department. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact organization department.");
+    }
+    return true;
+}
+
+bool JSContactOrganization::setTitle(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetTitle();
+        }
+        else {
+            std::string title = JSUtil::JSValueToString(context, value);
+            priv->setTitle(title);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact organization title. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact organization title.");
+    }
+    return true;
+}
+
+bool JSContactOrganization::setRole(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetRole();
+        }
+        else {
+            std::string role = JSUtil::JSValueToString(context, value);
+            priv->setRole(role);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact organization role. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact organization role.");
+    }
+    return true;
+}
+
+bool JSContactOrganization::setLogoURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactOrganizationPtr priv = JSContactOrganization::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetLogoURI();
+        }
+        else {
+            std::string logo_uri = JSUtil::JSValueToString(context, value);
+            priv->setLogoURI(logo_uri);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact organization logo URI. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact organization logo URI.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactOrganization.h b/src/Contact/JSContactOrganization.h
new file mode 100755 (executable)
index 0000000..f894765
--- /dev/null
@@ -0,0 +1,134 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_ORGANIZATION_H__
+#define __TIZEN_CONTACT_JS_CONTACT_ORGANIZATION_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactOrganization.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactOrganization {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactOrganizationPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactOrganizationPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactOrganizationPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    //static JSStaticFunction m_function[];
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDepartment(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTitle(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getRole(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLogoURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setDepartment(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setTitle(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setRole(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setLogoURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_ORGANIZATION_H__
diff --git a/src/Contact/JSContactPhoneNumber.cpp b/src/Contact/JSContactPhoneNumber.cpp
new file mode 100755 (executable)
index 0000000..3c07936
--- /dev/null
@@ -0,0 +1,424 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactPhoneNumber.h"
+#include "ContactPhoneNumber.h"
+#include "ContactUtil.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactPhoneNumberHolder {
+    ContactPhoneNumberPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_PHONE_NUMBER = "ContactPhoneNumber";
+
+const char* CONTACT_CONTACT_PHONE_NUMBER_NUMBER = "number";
+const char* CONTACT_CONTACT_PHONE_NUMBER_IS_DEFAULT = "isDefault";
+const char* CONTACT_CONTACT_PHONE_NUMBER_TYPES = "types";
+const char* CONTACT_CONTACT_PHONE_NUMBER_LABEL = "label";
+}
+
+JSClassDefinition JSContactPhoneNumber::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_PHONE_NUMBER,
+        NULL,
+        JSContactPhoneNumber::m_property,
+        NULL, //m_function,
+        JSContactPhoneNumber::initialize,
+        JSContactPhoneNumber::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactPhoneNumber::m_property[] = {
+        { CONTACT_CONTACT_PHONE_NUMBER_NUMBER, getNumber, setNumber, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_PHONE_NUMBER_IS_DEFAULT, getIsDefault, setIsDefault, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_PHONE_NUMBER_TYPES, getTypes, setTypes, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_PHONE_NUMBER_LABEL, getLabel, setLabel, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactPhoneNumber::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactPhoneNumber::m_jsClassRef = JSClassCreate(JSContactPhoneNumber::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactPhoneNumber::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactPhoneNumberPtr JSContactPhoneNumber::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactPhoneNumberHolder* priv =
+            static_cast<ContactPhoneNumberHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactPhoneNumber::setPrivateObject(JSObjectRef object,
+        ContactPhoneNumberPtr native)
+{
+    ContactPhoneNumberHolder* priv =
+            static_cast<ContactPhoneNumberHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactPhoneNumber::makeJSObject(JSContextRef context,
+        ContactPhoneNumberPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactPhoneNumberHolder* priv = new (std::nothrow) ContactPhoneNumberHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactPhoneNumber::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContactPhoneNumber::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContactPhoneNumberHolder* priv =
+            static_cast<ContactPhoneNumberHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactPhoneNumber::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        std::string phone_number;
+        bool is_default = false;
+        std::vector<std::string> str_types;
+
+        phone_number = validator.toString(0);
+        is_default = validator.toBool(2, true, false);
+        str_types = validator.toStringVector(1, true);
+
+        ContactPhoneNumberPtr priv =
+                ContactPhoneNumberPtr(new(std::nothrow) ContactPhoneNumber());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        priv->setPhoneNumber(phone_number);
+        priv->setIsDefault(is_default);
+
+        size_t size = str_types.size();
+        if (size > 0) {
+            for (size_t i = 0; i < size; i++) {
+                // Verification if string is actual from ContactEmailAddressType
+                ContactUtil::stringToContactPhoneNumberType(str_types[i]);
+            }
+            priv->setTypes(str_types);
+        }
+
+        ContactPhoneNumberHolder* holder = new(std::nothrow) ContactPhoneNumberHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactPhoneNumber creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactPhoneNumber creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactPhoneNumber::getNumber(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPhoneNumberPtr priv = JSContactPhoneNumber::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getPhoneNumber());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact phone number. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact phone number.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactPhoneNumber::getIsDefault(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPhoneNumberPtr priv = JSContactPhoneNumber::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getIsDefault());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact phone number is default flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact phone number is default flag.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactPhoneNumber::getTypes(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPhoneNumberPtr priv = JSContactPhoneNumber::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return priv->getJSTypes(GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact phone number types. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact phone number types.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactPhoneNumber::getLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPhoneNumberPtr priv = JSContactPhoneNumber::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if(!priv->isLabelSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getLabel());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact phone number label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact phone number label.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactPhoneNumber::setNumber(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPhoneNumberPtr priv = JSContactPhoneNumber::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string phoneNumber = JSUtil::JSValueToString(context, value);
+        priv->setPhoneNumber(phoneNumber);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact phone number. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact phone number.");
+    }
+    return true;
+}
+
+bool JSContactPhoneNumber::setIsDefault(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPhoneNumberPtr priv = JSContactPhoneNumber::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        bool is_default = JSUtil::JSValueToBoolean(context, value);
+        priv->setIsDefault(is_default);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact phone number is default flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact phone number is default flag.");
+    }
+    return true;
+}
+
+bool JSContactPhoneNumber::setTypes(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPhoneNumberPtr priv = JSContactPhoneNumber::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::vector<std::string> str_types = JSUtil::JSArrayToStringVector(context, value);
+        size_t size = str_types.size();
+        if (size > 0) {
+            for (size_t i = 0; i < size; i++) {
+                // Verification if string is actual from ContactEmailAddressType
+                ContactUtil::stringToContactPhoneNumberType(str_types[i]);
+            }
+            priv->setTypes(str_types);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact phone number types. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact phone number types.");
+    }
+    return true;
+}
+
+bool JSContactPhoneNumber::setLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactPhoneNumberPtr priv = JSContactPhoneNumber::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetLabel();
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setLabel(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact phone number label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact phone number label.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactPhoneNumber.h b/src/Contact/JSContactPhoneNumber.h
new file mode 100755 (executable)
index 0000000..9345667
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_PHONE_NUMBER_H__
+#define __TIZEN_CONTACT_JS_CONTACT_PHONE_NUMBER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactPhoneNumber.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactPhoneNumber {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactPhoneNumberPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactPhoneNumberPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            ContactPhoneNumberPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getNumber(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsDefault(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTypes(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setNumber(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setIsDefault(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setTypes(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_PHONE_NUMBER_H__
diff --git a/src/Contact/JSContactRef.cpp b/src/Contact/JSContactRef.cpp
new file mode 100644 (file)
index 0000000..9f85eb9
--- /dev/null
@@ -0,0 +1,293 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactRef.h"
+#include "ContactRef.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include <string>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactRefHolder {
+    ContactRefPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_REF = "ContactRef";
+
+const char* CONTACT_CONTACT_REF_ADDRESS_BOOK_ID = "addressBookId";
+const char* CONTACT_CONTACT_REF_CONTACT_ID = "contactId";
+}
+
+JSClassDefinition JSContactRef::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_REF,
+        NULL,
+        JSContactRef::m_property,
+        NULL, //m_function,
+        JSContactRef::initialize,
+        JSContactRef::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactRef::m_property[] = {
+    { CONTACT_CONTACT_REF_ADDRESS_BOOK_ID, getAddressBookId, setAddressBookId, kJSPropertyAttributeDontDelete },
+    { CONTACT_CONTACT_REF_CONTACT_ID, getContactId, setContactId, kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactRef::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactRef::m_jsClassRef = JSClassCreate(JSContactRef::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactRef::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactRefPtr DLL_EXPORT JSContactRef::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Not JSContactRef Entry");
+        throw TypeMismatchException("Not JSContactRef Entry");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactRefHolder* priv = static_cast<ContactRefHolder*>(JSObjectGetPrivate(object));
+    if(!priv) {
+        LOGE("priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSContactRef::setPrivateObject(JSObjectRef object, ContactRefPtr native)
+{
+    ContactRefHolder* priv = static_cast<ContactRefHolder*>(JSObjectGetPrivate(object));
+    if(!priv) {
+        LOGE("priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    priv->ptr = native;
+}
+
+JSObjectRef DLL_EXPORT JSContactRef::makeJSObject(JSContextRef context, ContactRefPtr native)
+{
+    if (!native) {
+        LOGE("native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactRefHolder* priv = new (std::nothrow) ContactRefHolder();
+    if (!priv) {
+        LOGE("Memory allocation failure");
+        throw UnknownException("Memory allocation failure");
+    }
+
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactRef::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("ContactRef initialize entered");
+}
+
+void JSContactRef::finalize(JSObjectRef object)
+{
+    LOGD("ContactRef finalize entered");
+
+    ContactRefHolder* priv = static_cast<ContactRefHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactRef::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("ContactRef constructor entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        int addressBookId = validator.toLong(0);
+        int contactId = validator.toLong(1);
+
+        ContactRefPtr priv = ContactRefPtr(new(std::nothrow) ContactRef());
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Memory allocation failure");
+        }
+
+        priv->setAddressBookId(addressBookId);
+        priv->setContactId(contactId);
+
+        ContactRefHolder* holder = new(std::nothrow) ContactRefHolder();
+        if (!holder) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Memory allocation failure");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactRef creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactRef creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactRef::getAddressBookId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRefPtr priv = JSContactRef::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getAddressBookIdString());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact ref address book id. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact ref address book id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactRef::getContactId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRefPtr priv = JSContactRef::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getContactIdString());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact ref contact id. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact ref contact id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactRef::setAddressBookId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRefPtr priv = JSContactRef::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string address_book_id = JSUtil::JSValueToString(context, value);
+        priv->setAddressBookIdString(address_book_id);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact ref address book id. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact ref address book id.");
+    }
+    return true;
+}
+
+bool JSContactRef::setContactId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRefPtr priv = JSContactRef::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string contact_id = JSUtil::JSValueToString(context, value);
+        priv->setContactIdString(contact_id);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact ref contact id. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact ref contact id.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactRef.h b/src/Contact/JSContactRef.h
new file mode 100755 (executable)
index 0000000..edf4465
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_REF_H__
+#define __TIZEN_CONTACT_JS_CONTACT_REF_H__
+
+#include "ContactRef.h"
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactRef {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static ContactRefPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactRefPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactRefPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getAddressBookId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getContactId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setAddressBookId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setContactId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_REF_H__
diff --git a/src/Contact/JSContactRelationship.cpp b/src/Contact/JSContactRelationship.cpp
new file mode 100644 (file)
index 0000000..7d815bd
--- /dev/null
@@ -0,0 +1,356 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactRelationship.h"
+#include "ContactRelationship.h"
+#include "ContactUtil.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include <algorithm>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactRelationshipHolder {
+    ContactRelationshipPtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_RELATIONSHIP = "ContactRelationship";
+
+const char* CONTACT_CONTACT_RELATIONSHIP_RELATIVE_NAME = "relativeName";
+const char* CONTACT_CONTACT_RELATIONSHIP_TYPE = "type";
+const char* CONTACT_CONTACT_RELATIONSHIP_LABEL = "label";
+}
+
+JSClassDefinition JSContactRelationship::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_RELATIONSHIP,
+        NULL,
+        JSContactRelationship::m_property,
+        NULL, //m_function,
+        JSContactRelationship::initialize,
+        JSContactRelationship::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactRelationship::m_property[] = {
+        { CONTACT_CONTACT_RELATIONSHIP_RELATIVE_NAME, getRelativeName, setRelativeName, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_RELATIONSHIP_TYPE, getType, setType, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_RELATIONSHIP_LABEL, getLabel, setLabel, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactRelationship::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactRelationship::m_jsClassRef = JSClassCreate(JSContactRelationship::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactRelationship::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactRelationshipPtr JSContactRelationship::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactRelationshipHolder* priv = static_cast<ContactRelationshipHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactRelationship::setPrivateObject(JSObjectRef object, ContactRelationshipPtr native)
+{
+    ContactRelationshipHolder* priv = static_cast<ContactRelationshipHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactRelationship::makeJSObject(JSContextRef context,
+        ContactRelationshipPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactRelationshipHolder* priv = new(std::nothrow) ContactRelationshipHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactRelationship::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContactRelationship::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContactRelationshipHolder* priv = static_cast<ContactRelationshipHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactRelationship::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        std::string relative_name = validator.toString(0);
+        std::string type = validator.toString(1, true);
+
+        ContactRelationshipPtr priv = ContactRelationshipPtr(new(std::nothrow) ContactRelationship());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        priv->setRelativeName(relative_name);
+        try {
+            priv->setType(ContactUtil::stringToRelationshipType(type));
+        }
+        catch (const BasePlatformException &error) {
+            LOGD("Setting type to default");
+            priv->setType(CONTACT_RELATIONSHIP_TYPE_OTHER);
+        }
+
+        ContactRelationshipHolder* holder = new(std::nothrow) ContactRelationshipHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactRelationship creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactRelationship creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSContactRelationship::getRelativeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRelationshipPtr priv = JSContactRelationship::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getRelativeName());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get relative name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting relative name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactRelationship::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRelationshipPtr priv = JSContactRelationship::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        std::string str_type = ContactUtil::contactRelationshipTypeToString(priv->getType());
+        return JSUtil::toJSValueRef(context, str_type);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get type. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting type.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactRelationship::getLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRelationshipPtr priv = JSContactRelationship::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if(!priv->isLabelSet()) {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, priv->getLabel());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting label.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactRelationship::setRelativeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRelationshipPtr priv = JSContactRelationship::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setRelativeName(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set relative name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting relative name.");
+    }
+    return true;
+}
+
+bool JSContactRelationship::setType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRelationshipPtr priv = JSContactRelationship::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setType(ContactUtil::stringToRelationshipType(_value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set type. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting type.");
+    }
+    return true;
+}
+
+bool JSContactRelationship::setLabel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactRelationshipPtr priv = JSContactRelationship::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        if (JSValueIsNull(context, value)) {
+            priv->unsetLabel();
+            return true;
+        }
+        std::string _value = JSUtil::JSValueToString(context, value);
+        priv->setLabel(_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set label. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting label.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactRelationship.h b/src/Contact/JSContactRelationship.h
new file mode 100644 (file)
index 0000000..a3a9e0a
--- /dev/null
@@ -0,0 +1,107 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_RELATIONSHIP_H__
+#define __TIZEN_CONTACT_JS_CONTACT_RELATIONSHIP_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactRelationship.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactRelationship {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactRelationshipPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactRelationshipPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactRelationshipPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getRelativeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setRelativeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setLabel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif /* __TIZEN_CONTACT_JS_CONTACT_RELATIONSHIP_H__ */
diff --git a/src/Contact/JSContactWebSite.cpp b/src/Contact/JSContactWebSite.cpp
new file mode 100644 (file)
index 0000000..6524872
--- /dev/null
@@ -0,0 +1,293 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSContactWebSite.h"
+#include "ContactUtil.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+struct ContactWebSiteHolder {
+    ContactWebSitePtr ptr;
+};
+
+namespace {
+const char* CONTACT_CONTACT_WEB_SITE = "ContactWebSite";
+
+const char* CONTACT_CONTACT_WEB_SITE_URL = "url";
+const char* CONTACT_CONTACT_WEB_SITE_TYPE = "type";
+}
+
+JSClassDefinition JSContactWebSite::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_CONTACT_WEB_SITE,
+        NULL,
+        JSContactWebSite::m_property,
+        NULL, //m_function,
+        JSContactWebSite::initialize,
+        JSContactWebSite::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSContactWebSite::m_property[] = {
+        { CONTACT_CONTACT_WEB_SITE_URL, getURL, setURL, kJSPropertyAttributeDontDelete },
+        { CONTACT_CONTACT_WEB_SITE_TYPE, getType, setType, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSContactWebSite::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSContactWebSite::m_jsClassRef = JSClassCreate(JSContactWebSite::getClassInfo());
+
+JSClassRef DLL_EXPORT JSContactWebSite::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+ContactWebSitePtr JSContactWebSite::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ContactWebSiteHolder* priv = static_cast<ContactWebSiteHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSContactWebSite::setPrivateObject(JSObjectRef object, ContactWebSitePtr native)
+{
+    ContactWebSiteHolder* priv = static_cast<ContactWebSiteHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSContactWebSite::makeJSObject(JSContextRef context,
+        ContactWebSitePtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    ContactWebSiteHolder* priv = new(std::nothrow) ContactWebSiteHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSContactWebSite::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContactWebSite::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContactWebSiteHolder* priv = static_cast<ContactWebSiteHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSContactWebSite::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        std::string url;
+        std::string str_type;
+
+        url = validator.toString(0);
+        str_type = validator.toString(1, true, ContactUtil::CONTACT_TYPE_HOMEPAGE);
+
+        ContactWebSitePtr priv = ContactWebSitePtr(new(std::nothrow) ContactWebSite());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        priv->setUrl(url);
+        priv->setType(ContactUtil::stringToContactWebSiteType(str_type));
+
+        ContactWebSiteHolder* holder = new(std::nothrow) ContactWebSiteHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ContactWebSite creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ContactWebSite creation failed");
+    }
+
+    return jsObjRef;
+
+}
+
+JSValueRef JSContactWebSite::getURL(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactWebSitePtr priv = JSContactWebSite::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, priv->getUrl());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact website url. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact website url.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContactWebSite::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactWebSitePtr priv = JSContactWebSite::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        return JSUtil::toJSValueRef(context, ContactUtil::contactWebSiteTypeToString(priv->getType()));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact website type. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact website type.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContactWebSite::setURL(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactWebSitePtr priv = JSContactWebSite::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string url = JSUtil::JSValueToString(context, value);
+        priv->setUrl(url);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact website url. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact website url.");
+    }
+    return true;
+}
+
+bool JSContactWebSite::setType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContactWebSitePtr priv = JSContactWebSite::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+        std::string str_type = JSUtil::JSValueToString(context, value);
+        priv->setType(ContactUtil::stringToContactWebSiteType(str_type));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact website type. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting contact website type.");
+    }
+    return true;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSContactWebSite.h b/src/Contact/JSContactWebSite.h
new file mode 100755 (executable)
index 0000000..a927d00
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_CONTACT_WEB_SITE_H__
+#define __TIZEN_CONTACT_JS_CONTACT_WEB_SITE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ContactWebSite.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSContactWebSite {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static ContactWebSitePtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, ContactWebSitePtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ContactWebSitePtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getURL(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setURL(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_CONTACT_WEB_SITE_H__
diff --git a/src/Contact/JSPerson.cpp b/src/Contact/JSPerson.cpp
new file mode 100644 (file)
index 0000000..7ac5e2f
--- /dev/null
@@ -0,0 +1,532 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSPerson.h"
+#include "Person.h"
+#include "ContactUtil.h"
+#include "ContactManager.h"
+
+#include <sstream>
+#include <Logger.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <TimeTracer.h>
+#include "plugin_config.h"
+#include <SecurityExceptions.h>
+#include <JSWebAPIErrorFactory.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+struct PersonHolder {
+    PersonPtr ptr;
+};
+
+namespace {
+const char* CONTACT_PERSON = "Person";
+
+const char* CONTACT_PERSON_ID = "id";
+const char* CONTACT_PERSON_DISPLAY_NAME = "displayName";
+const char* CONTACT_PERSON_CONTACT_COUNT = "contactCount";
+const char* CONTACT_PERSON_HAS_PHONE_NUMBER = "hasPhoneNumber";
+const char* CONTACT_PERSON_HAS_EMAIL = "hasEmail";
+const char* CONTACT_PERSON_IS_FAVORITE = "isFavorite";
+const char* CONTACT_PERSON_PHOTO_URI = "photoURI";
+const char* CONTACT_PERSON_RINGTONE_URI = "ringtoneURI";
+const char* CONTACT_PERSON_DISPLAY_CONTACT_ID = "displayContactId";
+}
+
+JSClassDefinition JSPerson::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CONTACT_PERSON,
+        NULL,
+        JSPerson::m_property,
+        JSPerson::m_function,
+        JSPerson::initialize,
+        JSPerson::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSPerson::m_property[] = {
+    { CONTACT_PERSON_ID, getId, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { CONTACT_PERSON_DISPLAY_NAME, getDisplayName, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { CONTACT_PERSON_CONTACT_COUNT, getContactCount, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { CONTACT_PERSON_HAS_PHONE_NUMBER, getHasPhoneNumber, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { CONTACT_PERSON_HAS_EMAIL, getHasEmail, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { CONTACT_PERSON_IS_FAVORITE, getIsFavorite, setIsFavorite, kJSPropertyAttributeDontDelete },
+    { CONTACT_PERSON_PHOTO_URI, getPhotoURI, setPhotoURI, kJSPropertyAttributeDontDelete },
+    { CONTACT_PERSON_RINGTONE_URI, getRingtoneURI, setRingtoneURI, kJSPropertyAttributeDontDelete },
+    { CONTACT_PERSON_DISPLAY_CONTACT_ID, getDisplayContactId, setDisplayContactId, kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSPerson::m_function[] = {
+        { CONTACT_FUNCTION_API_PERSON_LINK, link, kJSPropertyAttributeNone },
+        { CONTACT_FUNCTION_API_PERSON_UNLINK, unlink, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSPerson::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSPerson::m_jsClassRef = JSClassCreate(JSPerson::getClassInfo());
+
+const JSClassRef JSPerson::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+PersonPtr JSPerson::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Not JSPerson Entry");
+        throw TypeMismatchException("Not JSPerson Entry");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    PersonHolder* priv = static_cast<PersonHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSPerson::setPrivateObject(JSObjectRef object, PersonPtr native)
+{
+    PersonHolder* priv = static_cast<PersonHolder*>(JSObjectGetPrivate(object));
+    if(!priv) {
+        LOGE("priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSPerson::makeJSObject(JSContextRef context, PersonPtr native)
+{
+    if (!native) {
+        LOGE("native is null");
+        throw UnknownException("Native is null");
+    }
+
+    PersonHolder* priv = new (std::nothrow) PersonHolder();
+    if (!priv) {
+        LOGE("priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (!native->isInitialized()) {
+        LOGD("Not initialized");
+        native->copyAceCheckAccessFunction(ContactManager::getInstance());
+    }
+
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+void JSPerson::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Person initialize entered");
+}
+
+void JSPerson::finalize(JSObjectRef object)
+{
+    LOGD("Person finalize entered");
+
+    PersonHolder* priv = static_cast<PersonHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSPerson::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        std::string id_str = std::to_string(priv->getId());
+        return JSUtil::toJSValueRef(context, id_str);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact person id. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPerson::getDisplayName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getDisplayName());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact person display name. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person display name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPerson::getContactCount(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getContactCount());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact person contact count. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person contact count.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPerson::getHasPhoneNumber(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getHasPhoneNumber());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact person has phone number flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person has phone number flag.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPerson::getHasEmail(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getHasEmail());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact person has email flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person has email flag.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPerson::getIsFavorite(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getIsFavorite());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact person is favorite flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person is favorite flag.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPerson::getPhotoURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        if (priv->isPhotoURISet()) {
+            return JSUtil::toJSValueRef(context, priv->getPhotoURI());
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact person photo URI. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person photo URI.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPerson::getRingtoneURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        if (priv->isRingtoneURISet()) {
+            return JSUtil::toJSValueRef(context, priv->getRingtoneURI());
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact person ringtone URI. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person ringtone URI.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPerson::getDisplayContactId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        std::string disp_id_str = std::to_string(priv->getDisplayContactId());
+        return JSUtil::toJSValueRef(context, disp_id_str);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to get contact person display contact id. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person display contact id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSPerson::setIsFavorite(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        bool isFavorite = JSUtil::JSValueToBoolean(context, value);
+        priv->setIsFavorite(isFavorite);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact person is favorite flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person is favorite flag.");
+    }
+    return true;
+}
+
+bool JSPerson::setPhotoURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unsetPhotoURI();
+        }
+        else {
+            std::string photoURI = JSUtil::JSValueToString(context, value);
+            priv->setPhotoURI(photoURI);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact person is favorite flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person is favorite flag.");
+    }
+    return true;
+}
+
+bool JSPerson::setRingtoneURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unsetRingtoneURI();
+        }
+        else {
+            std::string ringtoneURI = JSUtil::JSValueToString(context, value);
+            priv->setRingtoneURI(ringtoneURI);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact person is favorite flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person is favorite flag.");
+    }
+    return true;
+}
+
+bool JSPerson::setDisplayContactId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        PersonPtr priv = JSPerson::getPrivateObject(context, object);
+        int displayContactId = JSUtil::JSValueToLong(context, value);
+        priv->setDisplayContactId(displayContactId);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Failed to set contact person is favorite flag. %s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting contact person is favorite flag.");
+    }
+    return true;
+}
+
+JSValueRef JSPerson::link(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Person link entered");
+
+    int personId = -1;
+
+    try {
+        PersonPtr priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_PERSON_LINK);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        personId = ContactUtil::toIntId(validator.toString(0, false));
+
+        priv->link(personId);
+    }
+    catch (const NotFoundException &err) {
+        std::stringstream oss;
+        oss << "Person id (" << personId << ") is not exists.";
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::INVALID_VALUES_ERROR, oss.str());
+    }
+    catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPerson::unlink(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Person unlink entered");
+
+    JSObjectRef obj;
+    int contactId = -1;
+
+    try {
+        PersonPtr priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                CONTACT_FUNCTION_API_PERSON_UNLINK);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        contactId = ContactUtil::toIntId(validator.toString(0, false));
+
+        PersonPtr newPerson = priv->unlink(contactId);
+        obj = JSPerson::makeJSObject(context, newPerson);
+    }
+    catch (const NotFoundException &err) {
+        std::stringstream oss;
+        oss << "Contact id (" << contactId << ") is not exists.";
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::INVALID_VALUES_ERROR, oss.str());
+    }
+    catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return obj;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/JSPerson.h b/src/Contact/JSPerson.h
new file mode 100755 (executable)
index 0000000..a773cc0
--- /dev/null
@@ -0,0 +1,156 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTACT_JS_PERSON_H__
+#define __TIZEN_CONTACT_JS_PERSON_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "Person.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class JSPerson {
+public:
+    static const JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static PersonPtr getPrivateObject(JSContextRef context, JSValueRef object);
+
+    static void setPrivateObject(JSObjectRef object, PersonPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, PersonPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDisplayName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getContactCount(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getHasPhoneNumber(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getHasEmail(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsFavorite(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPhotoURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getRingtoneURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDisplayContactId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setIsFavorite(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setPhotoURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setRingtoneURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setDisplayContactId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef link(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unlink(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_CONTACT_JS_PERSON_H__
diff --git a/src/Contact/Person.cpp b/src/Contact/Person.cpp
new file mode 100644 (file)
index 0000000..4f1e014
--- /dev/null
@@ -0,0 +1,395 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Person.cpp
+ */
+
+#include "Person.h"
+#include <PlatformException.h>
+#include "Logger.h"
+#include "ContactUtil.h"
+#include "Contact.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace DeviceAPI::Common;
+
+Person::Person():
+        SecurityAccessor(),
+        m_id(0),
+        m_displayName(""),
+        m_contactCount(0),
+        m_hasPhoneNumber(false),
+        m_hasEmail(false),
+        m_isFavorite(false),
+        m_photoURI(""),
+        m_isPhotoURISet(false),
+        m_ringtoneURI(""),
+        m_isRingtoneURISet(false),
+        m_displayContactId(0)
+{
+}
+
+Person::~Person()
+{
+}
+
+int Person::getId() const
+{
+    return m_id;
+}
+
+void Person::setId(int value)
+{
+    m_id = value;
+}
+
+std::string Person::getDisplayName() const
+{
+    return m_displayName;
+}
+
+void Person::setDisplayName(const std::string &value)
+{
+    m_displayName = value;
+}
+
+long Person::getContactCount() const
+{
+    return m_contactCount;
+}
+
+void Person::setContactCount(long value)
+{
+    m_contactCount = value;
+}
+
+bool Person::getHasPhoneNumber() const
+{
+    return m_hasPhoneNumber;
+}
+
+void Person::setHasPhoneNumber(bool value)
+{
+    m_hasPhoneNumber = value;
+}
+
+bool Person::getHasEmail() const
+{
+    return m_hasEmail;
+}
+
+void Person::setHasEmail(bool value)
+{
+    m_hasEmail = value;
+}
+
+bool Person::getIsFavorite() const
+{
+    return m_isFavorite;
+}
+
+void Person::setIsFavorite(bool value)
+{
+    m_isFavorite = value;
+}
+
+std::string Person::getPhotoURI() const
+{
+    return m_photoURI;
+}
+
+void Person::setPhotoURI(const std::string &value)
+{
+    m_photoURI = value;
+    m_isPhotoURISet = true;
+}
+
+void Person::unsetPhotoURI()
+{
+    m_isPhotoURISet = false;
+}
+
+bool Person::isPhotoURISet() const
+{
+    return m_isPhotoURISet;
+}
+
+std::string Person::getRingtoneURI() const
+{
+    return m_ringtoneURI;
+}
+
+void Person::setRingtoneURI(const std::string &value)
+{
+    m_ringtoneURI = value;
+    m_isRingtoneURISet = true;
+}
+
+void Person::unsetRingtoneURI()
+{
+    m_isRingtoneURISet = false;
+}
+
+bool Person::isRingtoneURISet() const
+{
+    return m_isRingtoneURISet;
+}
+
+int Person::getDisplayContactId() const
+{
+    return m_displayContactId;
+}
+
+void Person::setDisplayContactId(int value)
+{
+    m_displayContactId = value;
+}
+
+void Person::link(int personId)
+{
+    contacts_record_h contacts_record = NULL;
+
+    int errorCode = contacts_db_get_record(_contacts_person._uri, personId,
+            &contacts_record);
+    int ret = contacts_record_destroy(contacts_record, true);
+    if (CONTACTS_ERROR_NONE != ret) {
+        LOGW("Failed contacts_record_destroy(): %s, %d",
+                ContactUtil::getContactErrorMessage(ret).c_str(), ret);
+    }
+    contacts_record = NULL;
+
+    if (CONTACTS_ERROR_NONE != errorCode) {
+        LOGE("ret: %d", errorCode);
+        ContactUtil::throwContactException<NotFoundException>(errorCode, "contacts_db_get_record()");
+    }
+
+    errorCode = contacts_person_link_person(m_id, personId);
+    if (CONTACTS_ERROR_NONE != errorCode) {
+        LOGE("ret: %d", errorCode);
+        ContactUtil::throwContactException(errorCode, "contacts_person_link_person()");
+    }
+
+    m_contactCount++;
+}
+
+PersonPtr Person::unlink(int contactId)
+{
+    contacts_record_h contacts_record = NULL;
+
+    int errorCode = contacts_db_get_record(_contacts_simple_contact._uri,
+            contactId, &contacts_record);
+
+    if (CONTACTS_ERROR_NONE != errorCode) {
+        int ret = contacts_record_destroy(contacts_record, true);
+        if (CONTACTS_ERROR_NONE != ret) {
+            LOGW("Failed contacts_record_destroy(): %s, %d",
+                    ContactUtil::getContactErrorMessage(ret).c_str(), ret);
+        }
+        contacts_record = NULL;
+        LOGE("ret: %d", errorCode);
+        ContactUtil::throwContactException<NotFoundException>(errorCode, "contacts_db_get_record()");
+    }
+
+    int contactsPersonId = 0;
+    errorCode = contacts_record_get_int(contacts_record,
+            _contacts_simple_contact.person_id, &contactsPersonId);
+    int ret = contacts_record_destroy(contacts_record, true);
+    if (CONTACTS_ERROR_NONE != ret) {
+        LOGW("Failed contacts_record_destroy(): %s, %d",
+                ContactUtil::getContactErrorMessage(ret).c_str(), ret);
+    }
+    contacts_record = NULL;
+
+    if (CONTACTS_ERROR_NONE != errorCode) {
+        LOGE("ret: %d", errorCode);
+        ContactUtil::throwContactException(errorCode, "contacts_record_get_int()");
+    }
+
+    if (contactsPersonId != m_id) {
+        LOGW("Contact is not a member of person (wrong id's)");
+        throw InvalidValuesException("Contact is not a member of person");
+    }
+
+    int newPersonId = 0;
+
+    errorCode = contacts_person_unlink_contact(m_id, contactId, &newPersonId);
+    if (CONTACTS_ERROR_NONE != errorCode) {
+        LOGE("ret: %d", errorCode);
+        ContactUtil::throwContactException(errorCode, "contacts_person_unlink_contact()");
+    }
+
+    m_contactCount--;
+
+    errorCode = contacts_db_get_record(_contacts_person._uri, newPersonId,
+            &contacts_record);
+    if (CONTACTS_ERROR_NONE != errorCode) {
+        int ret = contacts_record_destroy(contacts_record, true);
+        if (CONTACTS_ERROR_NONE != ret) {
+            LOGW("%s", ContactUtil::getContactErrorString(ret,
+                    "contacts_record_destroy()").c_str());
+        }
+        contacts_record = NULL;
+        LOGE("ret: %d", errorCode);
+        ContactUtil::throwContactException(errorCode, "contacts_db_get_record()");
+    }
+
+    PersonPtr person = PersonPtr(new Person());
+
+    person->importFromRecord(contacts_record);
+
+    errorCode = contacts_record_destroy(contacts_record, true);
+    if (CONTACTS_ERROR_NONE != errorCode) {
+        LOGW("%s", ContactUtil::getContactErrorString(errorCode,
+                "contacts_record_destroy()").c_str());
+    }
+    contacts_record = NULL;
+
+    return person;
+}
+
+void Person::importFromRecord(contacts_record_h record)
+{
+    if (NULL == record) {
+        LOGW("Platform person record did not set");
+        throw InvalidValuesException("Platform person record did not set");
+    }
+
+    char *char_value = NULL;
+    int int_value = 0;
+    bool bool_value = false;
+
+    // id
+    ContactUtil::getIntFromRecord(record, _contacts_person.id,
+            &int_value);
+    setId(int_value);
+
+    // displayName
+    ContactUtil::getStrFromRecord(record, _contacts_person.display_name,
+            &char_value);
+    if (char_value) {
+        setDisplayName(char_value);
+    }
+
+    // contactCount
+    ContactUtil::getIntFromRecord(record, _contacts_person.link_count,
+            &int_value);
+    setContactCount(int_value);
+
+    // hasPhoneNumber
+    ContactUtil::getBoolFromRecord(record, _contacts_person.has_phonenumber,
+            &bool_value);
+    setHasPhoneNumber(bool_value);
+
+    // hasEmail
+    ContactUtil::getBoolFromRecord(record, _contacts_person.has_email,
+            &bool_value);
+    setHasEmail(bool_value);
+
+    // isFavorite
+    ContactUtil::getBoolFromRecord(record, _contacts_person.is_favorite,
+            &bool_value);
+    setIsFavorite(bool_value);
+
+    // photoURI
+    ContactUtil::getStrFromRecord(record, _contacts_person.image_thumbnail_path,
+            &char_value);
+    if (char_value) {
+        setPhotoURI(ContactUtil::convertPathToUri(char_value));
+    }
+    else {
+        unsetPhotoURI();
+    }
+
+    // ringtoneURI
+    ContactUtil::getStrFromRecord(record, _contacts_person.ringtone_path,
+            &char_value);
+    if (char_value) {
+        setRingtoneURI(ContactUtil::convertPathToUri(char_value));
+    }
+    else {
+        unsetRingtoneURI();
+    }
+
+    // displayContactId
+    ContactUtil::getIntFromRecord(record, _contacts_person.display_contact_id,
+            &int_value);
+    setDisplayContactId(int_value);
+}
+
+void Person::exportToRecord(contacts_record_h record)
+{
+    if (NULL == record) {
+        LOGE("Platform person object did not set");
+        throw UnknownException("Platform person object did not set");
+    }
+
+    ContactUtil::setBoolInRecord(record, _contacts_person.is_favorite,
+            getIsFavorite());
+    if (isPhotoURISet() && !getPhotoURI().empty()) {
+        //TODO: updating photoURI
+        //ContactUtil::setStrInRecord(record,
+        //    _contacts_person.image_thumbnail_path, getPhotoURI().c_str());
+    }
+    else {
+        //TODO: updating photoURI
+        //ContactUtil::setStrInRecord(record,
+        //    _contacts_person.image_thumbnail_path, "");
+    }
+    if (isRingtoneURISet() && !getRingtoneURI().empty()) {
+        ContactUtil::setStrInRecord(record, _contacts_person.ringtone_path,
+                getRingtoneURI().c_str());
+    }
+    else {
+        ContactUtil::setStrInRecord(record, _contacts_person.ringtone_path,
+                NULL);
+    }
+    ContactUtil::setIntInRecord(record, _contacts_person.display_contact_id,
+            getDisplayContactId());
+}
+
+PersonPtr Person::getPersonById(int person_id)
+{
+    contacts_record_h person_record = NULL;
+
+    int error_code = contacts_db_get_record(_contacts_person._uri, person_id,
+            &person_record);
+    if(CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_db_get_record()");
+    }
+
+    contacts_record_h_ptr person_record_ptr(&person_record, contactsDeleter);
+
+    PersonPtr person;
+    try {
+         person = PersonPtr(new Person());
+    }
+    catch (const std::bad_alloc &err) {
+        LOGE("Memory allocation error: %s", err.what());
+        throw UnknownException("Memory allocation error");
+    }
+
+    person->importFromRecord(*person_record_ptr);
+
+    return person;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/Person.h b/src/Contact/Person.h
new file mode 100644 (file)
index 0000000..0f152fd
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Person.h
+ */
+
+#ifndef __TIZEN_CONTACT_PERSON_H__
+#define __TIZEN_CONTACT_PERSON_H__
+
+#include <string>
+#include <memory>
+#include <vector>
+#include "contacts.h"
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+class Person;
+typedef std::shared_ptr<Person> PersonPtr;
+typedef std::vector<PersonPtr> PersonPtrVector;
+
+class Person : public Common::SecurityAccessor
+{
+public:
+    Person();
+    virtual ~Person();
+
+    int getId() const;
+    void setId(int);
+
+    std::string getDisplayName() const;
+    void setDisplayName(const std::string&);
+
+    long getContactCount() const;
+    void setContactCount(long);
+
+    bool getHasPhoneNumber() const;
+    void setHasPhoneNumber(bool);
+
+    bool getHasEmail() const;
+    void setHasEmail(bool);
+
+    bool getIsFavorite() const;
+    void setIsFavorite(bool);
+
+    std::string getPhotoURI() const;
+    void setPhotoURI(const std::string&);
+    void unsetPhotoURI();
+    bool isPhotoURISet() const;
+
+    std::string getRingtoneURI() const;
+    void setRingtoneURI(const std::string&);
+    void unsetRingtoneURI();
+    bool isRingtoneURISet() const;
+
+    int getDisplayContactId() const;
+    void setDisplayContactId(int);
+
+    void link(int);
+    PersonPtr unlink(int);
+
+    /**
+     * @brief   Fills Person object with values from record
+     *
+     * @param[in]   contacts_record_h  Record which is used to fill Person
+     */
+    void importFromRecord(contacts_record_h record);
+
+    /**
+     * @brief   Updates contacts_record_h with values from Person object
+     *
+     * @param[out]   contacts_record_h  Record which is updated
+     */
+    void exportToRecord(contacts_record_h record);
+
+    /**
+     * @brief   Gets Person from contacts DB with given Id
+     *
+     * @param[in]   int  Person id
+     */
+    static PersonPtr getPersonById(int person_id);
+
+private:
+    int m_id;
+    std::string m_displayName;
+    long m_contactCount;
+    bool m_hasPhoneNumber;
+    bool m_hasEmail;
+    bool m_isFavorite;
+
+    std::string m_photoURI;
+    bool m_isPhotoURISet;
+
+    std::string m_ringtoneURI;
+    bool m_isRingtoneURISet;
+
+    int m_displayContactId;
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif //__TIZEN_CONTACT_PERSON_H__
diff --git a/src/Contact/PersonChangeCallback.cpp b/src/Contact/PersonChangeCallback.cpp
new file mode 100644 (file)
index 0000000..5e07e93
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        PersonChangeCallback.cpp
+ */
+
+#include "PersonChangeCallback.h"
+#include "JSPerson.h"
+#include "ContactUtil.h"
+#include <JSUtil.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace Common;
+
+const char* PersonChangeCallback::CALLBACK_PERSONS_ADDED = "onpersonsadded";
+const char* PersonChangeCallback::CALLBACK_PERSONS_UPDATED = "onpersonsupdated";
+const char* PersonChangeCallback::CALLBACK_PERSONS_REMOVED = "onpersonsremoved";
+
+PersonChangeCallback::PersonChangeCallback(JSContextRef globalCtx,
+        JSObjectRef object): m_is_active(true)
+{
+    m_callback = MultiCallbackPtr(new (std::nothrow) MultiCallbackUserData(globalCtx, object));
+
+    if (!m_callback) {
+        LOGW("Callback is null");
+        throw UnknownException("Cannot allocate memory");
+    }
+}
+
+PersonChangeCallback::~PersonChangeCallback()
+{
+}
+
+void PersonChangeCallback::onpersonsadded(const PersonPtrVector &persons)
+{
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+    JSObjectRef jsPersons = ptrVectorToJSObjectArray<JSPerson, PersonPtr>(
+            persons, context);
+
+    m_callback->invokeCallback(CALLBACK_PERSONS_ADDED, jsPersons);
+}
+
+void PersonChangeCallback::onpersonsupdated(const PersonPtrVector &persons)
+{
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+    JSObjectRef jsPersons = ptrVectorToJSObjectArray<JSPerson, PersonPtr>(
+            persons, context);
+
+    m_callback->invokeCallback(CALLBACK_PERSONS_UPDATED, jsPersons);
+}
+
+void PersonChangeCallback::onpersonsremoved(const StringVector &person_ids)
+{
+    if (!m_is_active) {
+        return;
+    }
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+    m_callback->invokeCallback(CALLBACK_PERSONS_REMOVED, JSUtil::toJSValueRef(context, person_ids));
+}
+
+void PersonChangeCallback::setActive(bool act) {
+    m_is_active = act;
+}
+
+bool PersonChangeCallback::isActive()
+{
+    return m_is_active;
+}
+
+JSContextRef PersonChangeCallback::getContext() const
+{
+    return m_callback->getContext();
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/PersonChangeCallback.h b/src/Contact/PersonChangeCallback.h
new file mode 100644 (file)
index 0000000..10697c3
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        PersonChangeCallback.h
+ */
+
+#ifndef __TIZEN_PERSON_CHANGE_CALLBACK_H__
+#define __TIZEN_PERSON_CHANGE_CALLBACK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <vector>
+#include <memory>
+#include <string>
+#include "Person.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+class PersonChangeCallback;
+typedef std::shared_ptr<PersonChangeCallback> PersonChangeCallbackPtr;
+typedef std::shared_ptr<Common::MultiCallbackUserData> MultiCallbackPtr;
+
+typedef std::vector<std::string> StringVector;
+
+class PersonChangeCallback {
+public:
+    PersonChangeCallback(JSContextRef globalCtx, JSObjectRef object);
+    virtual ~PersonChangeCallback();
+
+    void onpersonsadded(const PersonPtrVector &persons);
+    void onpersonsupdated(const PersonPtrVector &persons);
+    void onpersonsremoved(const StringVector &person_ids);
+
+    static const char* CALLBACK_PERSONS_ADDED;
+    static const char* CALLBACK_PERSONS_UPDATED;
+    static const char* CALLBACK_PERSONS_REMOVED;
+
+    void setActive(bool act);
+    bool isActive();
+
+    JSContextRef getContext() const;
+
+private:
+    MultiCallbackPtr m_callback;
+    bool m_is_active;
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif //__TIZEN_PERSON_CHANGE_CALLBACK_H__
diff --git a/src/Contact/PersonSearchEngine.cpp b/src/Contact/PersonSearchEngine.cpp
new file mode 100755 (executable)
index 0000000..fe694a6
--- /dev/null
@@ -0,0 +1,629 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PersonSearchEngine.h"
+#include "ContactUtil.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <string>
+#include <map>
+#include <algorithm>
+#include <contacts.h>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace Tizen;
+
+PersonSearchEngine::PropertiesMap PersonSearchEngine::s_properties_map = {
+        {"id",                      { _contacts_person.id,                  PrimitiveType_Long } },
+        {"displayName",             { _contacts_person.display_name,        PrimitiveType_String } },
+        {"contactCount",            { _contacts_person.link_count,          PrimitiveType_Long } },
+        {"hasPhoneNumber",          { _contacts_person.has_phonenumber,     PrimitiveType_Boolean } },
+        {"hasEmail",                { _contacts_person.has_email,           PrimitiveType_Boolean } },
+        {"isFavorite",              { _contacts_person.is_favorite,         PrimitiveType_Boolean } },
+        {"photoURI",                { _contacts_person.image_thumbnail_path,PrimitiveType_String } },
+        {"ringtoneURI",             { _contacts_person.ringtone_path,       PrimitiveType_String } },
+        {"displayContactId",        { _contacts_person.display_contact_id,  PrimitiveType_Long } },
+};
+
+PersonSearchEngine::PersonSearchEngine():
+        m_query(NULL), m_filter(NULL)
+{
+    int ret = contacts_query_create(_contacts_person._uri, &m_query);
+    if (CONTACTS_ERROR_NONE != ret) {
+        LOGW("%s", ContactUtil::getContactErrorString(ret, "contacts_query_create()").c_str());
+    }
+}
+
+PersonSearchEngine::~PersonSearchEngine()
+{
+    int ret = 0;
+    if (m_filter) {
+        ret = contacts_filter_destroy(m_filter);
+        if (CONTACTS_ERROR_NONE != ret) {
+            LOGW("%s", ContactUtil::getContactErrorString(ret, "contacts_filter_destroy()").c_str());
+        }
+    }
+
+    if (m_query) {
+        ret = contacts_query_destroy(m_query);
+        if (CONTACTS_ERROR_NONE != ret) {
+            LOGW("%s", ContactUtil::getContactErrorString(ret, "contacts_query_destroy()").c_str());
+        }
+    }
+}
+
+std::shared_ptr<PersonPtrVector> PersonSearchEngine::find()
+{
+    contacts_list_h person_list = NULL;
+
+    std::shared_ptr<PersonPtrVector> persons(new PersonPtrVector());
+
+    int error_code = contacts_db_get_records_with_query(m_query, 0, 0, &person_list);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_db_get_records_with_query()");
+    }
+    contacts_list_h_ptr person_list_ptr(&person_list, contactsListDeleter);
+
+    int record_count = 0;
+
+    error_code = contacts_list_get_count(*person_list_ptr, &record_count);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_list_get_count()");
+    }
+
+    error_code = contacts_list_first(*person_list_ptr);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                "contacts_list_first()").c_str());
+    }
+    contacts_record_h contacts_record;
+
+    for (int i = 0; i < record_count; ++i) {
+        error_code = contacts_list_get_current_record_p(*person_list_ptr,
+                &contacts_record);
+
+        if(CONTACTS_ERROR_NONE != error_code || !contacts_record) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code,
+                    "contacts_list_get_current_record_p()").c_str());
+            continue;
+        }
+
+        PersonPtr person = PersonPtr(new Person());
+        person->importFromRecord(contacts_record);
+        persons->push_back(person);
+        contacts_list_next(*person_list_ptr);
+    }
+
+    return persons;
+}
+
+void PersonSearchEngine::applySortMode(SortModePtr sort_mode)
+{
+    if (!sort_mode) {
+        return;
+    }
+
+    const std::string attr_name = sort_mode->getAttributeName();
+
+    PropertiesMap::iterator iter =
+            s_properties_map.find(attr_name);
+    if (s_properties_map.end() == iter) {
+        std::string msg = "SortMode don't support ";
+        msg += attr_name;
+        LOGE("%s", msg.c_str());
+        throw Common::UnknownException(msg.c_str());
+    }
+
+    FilterPropertyStruct property = iter->second;
+
+    bool is_ascending = true;
+    if (DESC == sort_mode->getOrder()) {
+        is_ascending = false;
+    }
+
+    int error_code = contacts_query_set_sort(m_query, property.propertyId,
+            is_ascending);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_set_sort()");
+    }
+}
+
+void PersonSearchEngine::applyFilter(AbstractFilterPtr filter)
+{
+    if (!filter) {
+        return;
+    }
+
+    contacts_filter_h returned_filter;
+
+    switch (filter->getFilterType()) {
+        case ATTRIBUTE_FILTER: {
+            AttributeFilterPtr attribute_filter =
+                    std::dynamic_pointer_cast<AttributeFilter>(filter);
+            if (!attribute_filter) {
+                LOGE("Could not cast AbstractFilterPtr to AttributeFilterPtr");
+                throw Common::UnknownException("Wrong filter type");
+            }
+            returned_filter = this->applyAttributeFilter(attribute_filter);
+            break;
+        }
+        case ATTRIBUTE_RANGE_FILTER: {
+            AttributeRangeFilterPtr attribute_range_filter =
+                    std::dynamic_pointer_cast<AttributeRangeFilter>(filter);
+            if (!attribute_range_filter) {
+                LOGE("Could not cast AbstractFilterPtr to AttributeRangeFilterPtr");
+                throw Common::UnknownException("Wrong filter type");
+            }
+            returned_filter = this->applyAttributeRangeFilter(
+                    attribute_range_filter);
+            break;
+        }
+        case COMPOSITE_FILTER: {
+            CompositeFilterPtr composite_filter =
+                    std::dynamic_pointer_cast<CompositeFilter>(filter);
+            if (!composite_filter) {
+                LOGE("Could not cast AbstractFilterPtr to CompositeFilterPtr");
+                throw Common::UnknownException("Wrong filter type");
+            }
+            AbstractFilterPtrVector filters = composite_filter->getFilters();
+            returned_filter = this->applyCompositeFilter(
+                    composite_filter);
+            break;
+        }
+        default:
+            LOGE("Wrong filter type");
+            throw Common::UnknownException("Wrong filter type");
+    }
+
+    m_filter = returned_filter;
+
+    int error_code = contacts_query_set_filter(m_query, m_filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        if (m_filter) {
+            int ret = contacts_filter_destroy(m_filter);
+            if (CONTACTS_ERROR_NONE != ret) {
+                LOGW("Failed contacts_filter_destroy(): %s, %d",
+                        ContactUtil::getContactErrorMessage(ret).c_str(), ret);
+            }
+            m_filter = NULL;
+        }
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_query_set_filter()");
+    }
+}
+
+contacts_filter_h PersonSearchEngine::applyAttributeFilter(
+        AttributeFilterPtr filter)
+{
+    contacts_filter_h contacts_filter = NULL;
+
+    int error_code = contacts_filter_create(_contacts_person._uri,
+            &contacts_filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+
+    contacts_filter_h_ptr contacts_filter_ptr(&contacts_filter,
+            contactsFilterDeleter);
+
+    std::string attr_name = filter->getAttributeName();
+    FilterMatchFlag match_flag = filter->getMatchFlag();
+    AnyPtr match_value = filter->getMatchValue();
+
+    PropertiesMap::iterator iter = s_properties_map.find(attr_name);
+    if (s_properties_map.end() == iter) {
+        LOGE("Invalid attribute name, s%", attr_name.c_str());
+        throw Common::InvalidValuesException("Invalid value of attributeName");
+    }
+
+    FilterPropertyStruct property = iter->second;
+
+    if (filter->getMatchValue()->isNullOrUndefined()) {
+        match_flag = EXISTS;
+    }
+
+    std::string func_name;
+    if (PrimitiveType_Long == property.type) {
+        int value = match_value->toLong();
+
+        contacts_match_int_flag_e flag;
+        if (EXISTS == match_flag) {
+            flag = CONTACTS_MATCH_GREATER_THAN_OR_EQUAL;
+            value = 0;
+        }
+        else if (STARTSWITH == match_flag || CONTAINS == match_flag) {
+            flag = CONTACTS_MATCH_GREATER_THAN_OR_EQUAL;
+        }
+        else if (ENDSWITH == match_flag){
+            flag = CONTACTS_MATCH_LESS_THAN_OR_EQUAL;
+        }
+        else {
+            flag = CONTACTS_MATCH_EQUAL;
+        }
+
+        error_code = contacts_filter_add_int(*contacts_filter_ptr,
+                property.propertyId, flag, value);
+        func_name = "contacts_filter_add_int";
+    }
+    else if (PrimitiveType_String == property.type) {
+        std::string value = match_value->toString();
+
+        contacts_match_str_flag_e flag = CONTACTS_MATCH_EXISTS;
+        if (EXACTLY == match_flag) {
+            flag = CONTACTS_MATCH_EXACTLY;
+        }
+        else if (FULLSTRING == match_flag) {
+            flag = CONTACTS_MATCH_FULLSTRING;
+        }
+        else if (CONTAINS == match_flag) {
+            flag = CONTACTS_MATCH_CONTAINS;
+        }
+        else if (STARTSWITH == match_flag) {
+            flag = CONTACTS_MATCH_STARTSWITH;
+        }
+        else if (ENDSWITH == match_flag) {
+            flag = CONTACTS_MATCH_ENDSWITH;
+        }
+        else if (EXISTS == match_flag) {
+            flag = CONTACTS_MATCH_EXISTS;
+            value = "";
+        }
+
+        error_code = contacts_filter_add_str(*contacts_filter_ptr,
+                property.propertyId, flag, value.c_str());
+        func_name = "contacts_filter_add_str";
+    }
+    else if (PrimitiveType_Boolean == property.type) {
+        bool value = true;
+        if (EXISTS != match_flag) {
+            value = match_value->toBool();
+        }
+
+        error_code = contacts_filter_add_bool(*contacts_filter_ptr,
+                property.propertyId, value);
+        func_name = "contacts_filter_add_bool";
+    }
+
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, func_name);
+    }
+
+    contacts_filter_ptr.release();
+
+    return contacts_filter;
+}
+
+contacts_filter_h PersonSearchEngine::applyAttributeRangeFilter(
+        AttributeRangeFilterPtr filter)
+{
+    contacts_filter_h contacts_filter = NULL;
+
+    int error_code = contacts_filter_create(_contacts_person._uri,
+            &contacts_filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+
+    contacts_filter_h_ptr contacts_filter_ptr(&contacts_filter,
+            contactsFilterDeleter);
+
+    std::string attr_name = filter->getAttributeName();
+    AnyPtr initial_value = filter->getInitialValue();
+    AnyPtr end_value = filter->getEndValue();
+
+    PropertiesMap::iterator iter = s_properties_map.find(attr_name);
+    if (s_properties_map.end() == iter) {
+        LOGE("Invalid attribute name, s%", attr_name.c_str());
+        throw Common::InvalidValuesException("Invalid value of attributeName");
+    }
+
+    FilterPropertyStruct property = iter->second;
+
+    bool initial_value_exists = false;
+    bool end_value_exists = false;
+
+    if (PrimitiveType_Long == property.type) {
+        int initial_value_int = 0;
+        int end_value_int = 0;
+
+        if (!filter->getInitialValue()->isNullOrUndefined()) {
+            initial_value_int = initial_value->toLong();
+            initial_value_exists = true;
+        }
+
+        if (!filter->getEndValue()->isNullOrUndefined()) {
+            end_value_int = end_value->toLong();
+            end_value_exists = true;
+        }
+
+        if(initial_value_exists && end_value_exists) {
+            contacts_filter_h sub_filter = NULL;
+
+            error_code = contacts_filter_create(_contacts_person._uri, &sub_filter);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+            }
+
+            contacts_filter_h_ptr sub_filter_ptr(&sub_filter,
+                    contactsFilterDeleter);
+
+            error_code = contacts_filter_add_int(*sub_filter_ptr, property.propertyId,
+                    CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value_int);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+            }
+
+            error_code = contacts_filter_add_operator(*sub_filter_ptr,
+                    CONTACTS_FILTER_OPERATOR_AND);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+            }
+
+            error_code = contacts_filter_add_int(*sub_filter_ptr, property.propertyId,
+                    CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value_int);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+            }
+
+            error_code = contacts_filter_add_filter(*contacts_filter_ptr,
+                    *sub_filter_ptr);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_filter()");
+            }
+        }
+        else if (initial_value_exists) {
+            error_code = contacts_filter_add_int(*contacts_filter_ptr, property.propertyId,
+                    CONTACTS_MATCH_GREATER_THAN_OR_EQUAL, initial_value_int);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+            }
+        }
+        else if (end_value_exists) {
+            error_code = contacts_filter_add_int(*contacts_filter_ptr, property.propertyId,
+                    CONTACTS_MATCH_LESS_THAN_OR_EQUAL, end_value_int);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_int()");
+            }
+        }
+    }
+    else if (PrimitiveType_String == property.type) {
+        std::string initial_value_str = 0;
+        std::string end_value_str = 0;
+
+        if (!filter->getInitialValue()->isNullOrUndefined()) {
+            initial_value_str = initial_value->toString();
+            initial_value_exists = true;
+        }
+
+        if (!filter->getEndValue()->isNullOrUndefined()) {
+            end_value_str = end_value->toString();
+            end_value_exists = true;
+        }
+
+        if (initial_value_exists && end_value_exists) {
+            contacts_filter_h sub_filter = NULL;
+
+            error_code = contacts_filter_create(_contacts_person._uri, &sub_filter);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+            }
+
+            contacts_filter_h_ptr sub_filter_ptr(&sub_filter,
+                    contactsFilterDeleter);
+
+            error_code = contacts_filter_add_str(*sub_filter_ptr, property.propertyId,
+                    CONTACTS_MATCH_STARTSWITH, initial_value_str.c_str());
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_str()");
+            }
+
+            error_code = contacts_filter_add_operator(*sub_filter_ptr,
+                    CONTACTS_FILTER_OPERATOR_AND);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+            }
+
+            error_code = contacts_filter_add_str(*sub_filter_ptr, property.propertyId,
+                    CONTACTS_MATCH_ENDSWITH, end_value_str.c_str());
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_str()");
+            }
+
+            error_code = contacts_filter_add_filter(*contacts_filter_ptr,
+                    *sub_filter_ptr);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_filter()");
+            }
+        }
+        else if (initial_value_exists) {
+            error_code = contacts_filter_add_str(*contacts_filter_ptr, property.propertyId,
+                    CONTACTS_MATCH_STARTSWITH, initial_value_str.c_str());
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_str()");
+            }
+        }
+        else if (end_value_exists) {
+            error_code = contacts_filter_add_str(*contacts_filter_ptr, property.propertyId,
+                    CONTACTS_MATCH_ENDSWITH, end_value_str.c_str());
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_str()");
+            }
+        }
+    }
+    else if (PrimitiveType_Boolean == property.type) {
+        bool initial_value_bool = false;
+        bool end_value_bool = false;
+
+        if (!filter->getInitialValue()->isNullOrUndefined()) {
+            initial_value_bool = initial_value->toBool();
+            initial_value_exists = true;
+        }
+
+        if (!filter->getEndValue()->isNullOrUndefined()) {
+            end_value_bool = end_value->toBool();
+            end_value_exists = true;
+        }
+
+        if (initial_value_exists && end_value_exists) {
+            if (initial_value_bool == end_value_bool) {
+                error_code = contacts_filter_add_bool(*contacts_filter_ptr,
+                        property.propertyId, initial_value_bool);
+                if (CONTACTS_ERROR_NONE != error_code) {
+                    LOGE("ret: %d", error_code);
+                    ContactUtil::throwContactException(error_code, "contacts_filter_add_bool()");
+                }
+            }
+        }
+        else if (initial_value_exists) {
+            if (initial_value_bool) {
+                error_code = contacts_filter_add_bool(*contacts_filter_ptr,
+                        property.propertyId, true);
+                if (CONTACTS_ERROR_NONE != error_code) {
+                    LOGE("ret: %d", error_code);
+                    ContactUtil::throwContactException(error_code, "contacts_filter_add_bool()");
+                }
+            }
+        }
+        else if (end_value_exists) {
+            if (!end_value_bool) {
+                error_code = contacts_filter_add_bool(*contacts_filter_ptr,
+                        property.propertyId, false);
+                if (CONTACTS_ERROR_NONE != error_code) {
+                    LOGE("ret: %d", error_code);
+                    ContactUtil::throwContactException(error_code, "contacts_filter_add_bool()");
+                }
+            }
+        }
+    }
+
+    contacts_filter_ptr.release();
+
+    return contacts_filter;
+}
+
+contacts_filter_h PersonSearchEngine::applyCompositeFilter(CompositeFilterPtr filter)
+{
+    AbstractFilterPtrVector filters = filter->getFilters();
+    CompositeFilterType type = filter->getType();
+
+    contacts_filter_h contacts_filter = NULL;
+
+    int error_code = contacts_filter_create(_contacts_person._uri,
+                    &contacts_filter);
+    if (CONTACTS_ERROR_NONE != error_code) {
+        LOGE("ret: %d", error_code);
+        ContactUtil::throwContactException(error_code, "contacts_filter_create()");
+    }
+
+    contacts_filter_h_ptr contacts_filter_ptr(&contacts_filter,
+            contactsFilterDeleter);
+
+    for_each(filters.begin(), filters.end(),
+            [this, &contacts_filter_ptr, type, &error_code] (AbstractFilterPtr filter_ptr) {
+        contacts_filter_h returned_filter = NULL;
+
+        switch (filter_ptr->getFilterType()) {
+            case ATTRIBUTE_FILTER: {
+                AttributeFilterPtr attribute_filter =
+                        std::dynamic_pointer_cast<AttributeFilter>(filter_ptr);
+                if (!attribute_filter) {
+                    LOGE("Could not cast AbstractFilterPtr to AttributeFilterPtr");
+                    throw Common::UnknownException("Wrong filter type");
+                }
+                returned_filter = this->applyAttributeFilter(attribute_filter);
+                break;
+            }
+            case ATTRIBUTE_RANGE_FILTER: {
+                AttributeRangeFilterPtr attribute_range_filter =
+                        std::dynamic_pointer_cast<AttributeRangeFilter>(filter_ptr);
+                if (!attribute_range_filter) {
+                    LOGE("Could not cast AbstractFilterPtr to AttributeRangeFilterPtr");
+                    throw Common::UnknownException("Wrong filter type");
+                }
+                returned_filter = this->applyAttributeRangeFilter(
+                        attribute_range_filter);
+                break;
+            }
+            case COMPOSITE_FILTER: {
+                CompositeFilterPtr composite_filter =
+                        std::dynamic_pointer_cast<CompositeFilter>(filter_ptr);
+                if (!composite_filter) {
+                    LOGE("Could not cast AbstractFilterPtr to CompositeFilterPtr");
+                    throw Common::UnknownException("Wrong filter type");
+                }
+                returned_filter = this->applyCompositeFilter(composite_filter);
+                break;
+            }
+            default:
+                LOGE("Wrong filter type");
+                throw Common::UnknownException("Wrong filter type");
+        }
+        contacts_filter_h_ptr returned_filter_ptr(&returned_filter,
+                contactsFilterDeleter);
+
+        error_code = contacts_filter_add_filter(*contacts_filter_ptr, *returned_filter_ptr);
+        if (CONTACTS_ERROR_NONE != error_code) {
+            LOGW("%s", ContactUtil::getContactErrorString(error_code, "contacts_filter_add_filter()").c_str());
+        }
+        if (INTERSECTION == type) {
+            error_code = contacts_filter_add_operator(*contacts_filter_ptr,
+                    CONTACTS_FILTER_OPERATOR_AND);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+            }
+        }
+        else if (UNION == type) {
+            error_code = contacts_filter_add_operator(*contacts_filter_ptr,
+                    CONTACTS_FILTER_OPERATOR_OR);
+            if (CONTACTS_ERROR_NONE != error_code) {
+                LOGE("ret: %d", error_code);
+                ContactUtil::throwContactException(error_code, "contacts_filter_add_operator()");
+            }
+        }
+    });
+
+    contacts_filter_ptr.release();
+
+    return contacts_filter;
+}
+
+} // Contact
+} // DeviceAPI
diff --git a/src/Contact/PersonSearchEngine.h b/src/Contact/PersonSearchEngine.h
new file mode 100644 (file)
index 0000000..46a69bf
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_PERSON_SEARCH_ENGINE__
+#define __TIZEN_PERSON_SEARCH_ENGINE__
+
+#include <AbstractFilter.h>
+#include <AttributeFilter.h>
+#include <AttributeRangeFilter.h>
+#include <CompositeFilter.h>
+#include <SortMode.h>
+#include <Any.h>
+#include "Person.h"
+#include <memory>
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace Tizen;
+
+class PersonSearchEngine {
+public:
+    PersonSearchEngine();
+    virtual ~PersonSearchEngine();
+
+    std::shared_ptr<PersonPtrVector> find();
+
+    void applySortMode(SortModePtr sort_mode);
+    void applyFilter(AbstractFilterPtr filter);
+
+private:
+    contacts_query_h m_query;
+    contacts_filter_h m_filter;
+
+    struct FilterPropertyStruct {
+        const unsigned int propertyId;
+        const PrimitiveType type;
+    };
+    typedef std::map<std::string, FilterPropertyStruct> PropertiesMap;
+    static PropertiesMap s_properties_map;
+
+    contacts_filter_h applyAttributeFilter(AttributeFilterPtr filter);
+    contacts_filter_h applyAttributeRangeFilter(AttributeRangeFilterPtr filter);
+    contacts_filter_h applyCompositeFilter(CompositeFilterPtr filter);
+
+};
+
+} // Contact
+} // DeviceAPI
+
+#endif // __TIZEN_PERSON_SEARCH_ENGINE__
diff --git a/src/Contact/config.xml b/src/Contact/config.xml
new file mode 100755 (executable)
index 0000000..8de81d4
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-contact.so</library-name>
+    <feature-install-uri>contact.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/contact.read</name>
+        <device-capability>contact.read</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/contact.write</name>
+        <device-capability>contact.write</device-capability>
+    </api-feature>
+</plugin-properties>
diff --git a/src/Contact/plugin_config.cpp b/src/Contact/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..5213f29
--- /dev/null
@@ -0,0 +1,424 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define CONTACT_FEATURE_API_READ  "http://tizen.org/privilege/contact.read"
+#define CONTACT_FEATURE_API_WRITE "http://tizen.org/privilege/contact.write"
+
+#define CONTACT_DEVICE_CAP_READ "contact.read"
+#define CONTACT_DEVICE_CAP_WRITE "contact.write"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Contact {
+
+static FunctionMapping createContactFunctions();
+
+static FunctionMapping ContactFunctions =
+    createContactFunctions();
+
+#pragma GCC visibility push(default)
+DEFINE_FUNCTION_GETTER(Contact, ContactFunctions);
+#pragma GCC visibility pop
+
+static FunctionMapping createContactFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_CONTACT_READ, CONTACT_DEVICE_CAP_READ);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_CONTACT_WRITE, CONTACT_DEVICE_CAP_WRITE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_CONTACT_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_CONTACT_READ, DEVICE_CAP_CONTACT_READ);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_CONTACT_WRITE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_CONTACT_WRITE, DEVICE_CAP_CONTACT_WRITE);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_CONTACT_READ, CONTACT_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_CONTACT_WRITE, CONTACT_FEATURE_API_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(CONTACT_FEATURES_CONTACT_READ);
+    ACE_ADD_API_FEATURE(CONTACT_FEATURES_CONTACT_READ, FEATURE_CONTACT_READ);
+
+    ACE_CREATE_FEATURE_LIST(CONTACT_FEATURES_CONTACT_WRITE);
+    ACE_ADD_API_FEATURE(CONTACT_FEATURES_CONTACT_WRITE, FEATURE_CONTACT_WRITE);
+
+    /**
+     * Functions
+     */
+
+    FunctionMapping contactMapping;
+
+    //ContactManager.getAddressBooks
+    AceFunction contactManagerGetAddressBooksFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_GET_ADDRESS_BOOKS,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOKS,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOKS,
+                               contactManagerGetAddressBooksFunc));
+
+    //ContactManager.getDefaultAddressBook
+    AceFunction contactManagerGetDefaultAddressBookFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_GET_DEFAULT_ADDRESS_BOOK,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_DEFAULT_ADDRESS_BOOK,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_DEFAULT_ADDRESS_BOOK,
+                               contactManagerGetDefaultAddressBookFunc));
+
+    //ContactManager.getUnifiedAddressBook
+    AceFunction contactManagerGetUnifiedAddressBookFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_GET_UNIFIED_ADDRESS_BOOK,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_UNIFIED_ADDRESS_BOOK,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_UNIFIED_ADDRESS_BOOK,
+                               contactManagerGetUnifiedAddressBookFunc));
+
+    //ContactManager.getAddressBook
+    AceFunction contactManagerGetAddressBookFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_GET_ADDRESS_BOOK,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOK,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOK,
+                               contactManagerGetAddressBookFunc));
+
+    //ContactManager.addAddressBook
+    AceFunction contactManagerAddAddressBookFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_ADD_ADDRESS_BOOK,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_ADDRESS_BOOK,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_ADDRESS_BOOK,
+                               contactManagerAddAddressBookFunc));
+
+    //ContactManager.removeAddressBook
+    AceFunction contactManagerRemoveAddressBookFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_REMOVE_ADDRESS_BOOK,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_ADDRESS_BOOK,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_ADDRESS_BOOK,
+                               contactManagerRemoveAddressBookFunc));
+
+    //ContactManager.get
+    AceFunction contactManagerGetFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_GET,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_GET,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_GET,
+                               contactManagerGetFunc));
+
+    //ContactManager.update
+    AceFunction contactManagerUpdateFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_UPDATE,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE,
+                               contactManagerUpdateFunc));
+
+    //ContactManager.updateBatch
+    AceFunction contactManagerUpdateBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_UPDATE_BATCH,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE_BATCH,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE_BATCH,
+                               contactManagerUpdateBatchFunc));
+
+    //ContactManager.remove
+    AceFunction contactManagerRemoveFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_REMOVE,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE,
+                               contactManagerRemoveFunc));
+
+    //ContactManager.removeBatch
+    AceFunction contactManagerRemoveBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_REMOVE_BATCH,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_BATCH,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_BATCH,
+                               contactManagerRemoveBatchFunc));
+
+    //ContactManager.find
+    AceFunction contactManagerFindFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_FIND,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_FIND,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_FIND,
+                               contactManagerFindFunc));
+
+    //ContactManager.addChangeListener
+    AceFunction contactManagerAddChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_ADD_CHANGE_LISTENER,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_CHANGE_LISTENER,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_CHANGE_LISTENER,
+                               contactManagerAddChangeListenerFunc));
+
+    //ContactManager.removeChangeListener
+    AceFunction contactManagerRemoveChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONTACT_MANAGER_REMOVE_CHANGE_LISTENER,
+            CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_CHANGE_LISTENER,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_CHANGE_LISTENER,
+                               contactManagerRemoveChangeListenerFunc));
+
+    //AddressBook.get
+    AceFunction addressBookGetFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_GET,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_GET,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_GET,
+                               addressBookGetFunc));
+
+    //AddressBook.add
+    AceFunction addressBookAddFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_ADD,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD,
+                               addressBookAddFunc));
+
+    //AddressBook.addBatch
+    AceFunction addressBookAddBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_ADD_BATCH,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_BATCH,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_BATCH,
+                               addressBookAddBatchFunc));
+
+    //AddressBook.update
+    AceFunction addressBookUpdateFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_UPDATE,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE,
+                               addressBookUpdateFunc));
+
+    //AddressBook.updateBatch
+    AceFunction addressBookUpdateBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_UPDATE_BATCH,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_BATCH,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_BATCH,
+                               addressBookUpdateBatchFunc));
+
+    //AddressBook.remove
+    AceFunction addressBookRemoveFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_REMOVE,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE,
+                               addressBookRemoveFunc));
+
+    //AddressBook.removeBatch
+    AceFunction addressBookRemoveBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_REMOVE_BATCH,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_BATCH,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_BATCH,
+                               addressBookRemoveBatchFunc));
+
+    //AddressBook.find
+    AceFunction addressBookFindFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_FIND,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_FIND,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_FIND,
+                               addressBookFindFunc));
+
+    //AddressBook.addChangeListener
+    AceFunction addressBookAddChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_ADD_CHANGE_LISTENER,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_CHANGE_LISTENER,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_CHANGE_LISTENER,
+                               addressBookAddChangeListenerFunc));
+
+    //AddressBook.removeChangeListener
+    AceFunction addressBookRemoveChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_REMOVE_CHANGE_LISTENER,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_CHANGE_LISTENER,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_CHANGE_LISTENER,
+                               addressBookRemoveChangeListenerFunc));
+    //AddressBook.getGroup
+    AceFunction addressBookGetGroupFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_GET_GROUP,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUP,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUP,
+                               addressBookGetGroupFunc));
+
+    //AddressBook.addGroup
+    AceFunction addressBookAddGroupFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_ADD_GROUP,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_GROUP,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_GROUP,
+                               addressBookAddGroupFunc));
+
+    //AddressBook.updateGroup
+    AceFunction addressBookUpdateGroupFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_UPDATE_GROUP,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_GROUP,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_GROUP,
+                               addressBookUpdateGroupFunc));
+
+    //AddressBook.removeGroup
+    AceFunction addressBookRemoveGroupFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_REMOVE_GROUP,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_GROUP,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_GROUP,
+                               addressBookRemoveGroupFunc));
+
+    //AddressBook.getGroups
+    AceFunction addressBookGetGroupsFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADDRESS_BOOK_GET_GROUPS,
+            CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUPS,
+            CONTACT_FEATURES_CONTACT_READ,
+            DEVICE_LIST_CONTACT_READ);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUPS,
+                               addressBookGetGroupsFunc));
+
+    //Person.link
+    AceFunction personLinkFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_PERSON_LINK,
+            CONTACT_FUNCTION_API_PERSON_LINK,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_PERSON_LINK,
+                               personLinkFunc));
+
+    //Person.unlink
+    AceFunction personUnlinkFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_PERSON_UNLINK,
+            CONTACT_FUNCTION_API_PERSON_UNLINK,
+            CONTACT_FEATURES_CONTACT_WRITE,
+            DEVICE_LIST_CONTACT_WRITE);
+
+    contactMapping.insert(std::make_pair(
+                               CONTACT_FUNCTION_API_PERSON_UNLINK,
+                               personUnlinkFunc));
+
+    return contactMapping;
+}
+
+}
+}
diff --git a/src/Contact/plugin_config.h b/src/Contact/plugin_config.h
new file mode 100755 (executable)
index 0000000..db741c0
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _CONTACT_PLUGIN_CONFIG_H_
+#define _CONTACT_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+DECLARE_FUNCTION_GETTER(Contact);
+
+#define CONTACT_CHECK_ACCESS(functionName)                     \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(                \
+        getContactFunctionData,           \
+        functionName)
+
+} // Contact
+} // DeviceAPI
+
+#endif // _CONTACT_PLUGIN_CONFIG_H_
diff --git a/src/Contact/plugin_config_impl.h b/src/Contact/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..d4f5ae9
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _CONTACT_PLUGIN_CONFIG_IMPL_H_
+#define _CONTACT_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_CONTACT_CONTACT_CLASS "contact"
+#define TIZEN_CONTACT_CONTACT_INTERFACE "Contact"
+#define TIZEN_CONTACT_CONTACT_GROUP_INTERFACE "ContactGroup"
+#define TIZEN_CONTACT_CONTACT_REF_INTERFACE "ContactRef"
+#define TIZEN_CONTACT_CONTACT_NAME_INTERFACE "ContactName"
+#define TIZEN_CONTACT_CONTACT_ORGANIZATION_INTERFACE "ContactOrganization"
+#define TIZEN_CONTACT_CONTACT_WEB_SITE_INTERFACE "ContactWebSite"
+#define TIZEN_CONTACT_CONTACT_ANNIVERSARY_INTERFACE "ContactAnniversary"
+#define TIZEN_CONTACT_CONTACT_ADDRESS_INTERFACE "ContactAddress"
+#define TIZEN_CONTACT_CONTACT_PHONE_NUMBER_INTERFACE "ContactPhoneNumber"
+#define TIZEN_CONTACT_CONTACT_EMAIL_ADDRESS_INTERFACE "ContactEmailAddress"
+#define TIZEN_CONTACT_CONTACT_RELATIONSHIP_INTERFACE "ContactRelationship"
+#define TIZEN_CONTACT_CONTACT_INSTANT_MESSENGER_INTERFACE "ContactInstantMessenger"
+#define TIZEN_CONTACT_ADDRESS_BOOK_INTERFACE "AddressBook"
+
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOKS          "getAddressBooks"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_DEFAULT_ADDRESS_BOOK   "getDefaultAddressBook"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_UNIFIED_ADDRESS_BOOK   "getUnifiedAddressBook"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_GET_ADDRESS_BOOK           "getAddressBook"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_ADDRESS_BOOK           "addAddressBook"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_ADDRESS_BOOK        "removeAddressBook"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_GET                        "get"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE                     "update"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_UPDATE_BATCH               "updateBatch"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE                     "remove"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_BATCH               "removeBatch"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_FIND                       "find"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_ADD_CHANGE_LISTENER        "addChangeListener"
+#define CONTACT_FUNCTION_API_CONTACT_MANAGER_REMOVE_CHANGE_LISTENER     "removeChangeListener"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_GET                           "get"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD                           "add"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_BATCH                     "addBatch"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE                        "update"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_BATCH                  "updateBatch"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE                        "remove"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_BATCH                  "removeBatch"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_FIND                          "find"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_CHANGE_LISTENER           "addChangeListener"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_CHANGE_LISTENER        "removeChangeListener"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUP                     "getGroup"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_ADD_GROUP                     "addGroup"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_UPDATE_GROUP                  "updateGroup"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_REMOVE_GROUP                  "removeGroup"
+#define CONTACT_FUNCTION_API_ADDRESS_BOOK_GET_GROUPS                    "getGroups"
+#define CONTACT_FUNCTION_API_PERSON_LINK                                "link"
+#define CONTACT_FUNCTION_API_PERSON_UNLINK                              "unlink"
+
+#endif // _CONTACT_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/Contact/plugin_initializer.cpp b/src/Contact/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..7ea14a3
--- /dev/null
@@ -0,0 +1,199 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+
+#include "JSAddressBook.h"
+#include "JSContactAddress.h"
+#include "JSContactAnniversary.h"
+#include "JSContactEmailAddress.h"
+#include "JSContactGroup.h"
+#include "JSContact.h"
+#include "JSContactManager.h"
+#include "JSContactName.h"
+#include "JSContactOrganization.h"
+#include "JSContactPhoneNumber.h"
+#include "JSContactRef.h"
+#include "JSContactWebSite.h"
+#include "JSContactRelationship.h"
+#include "JSContactInstantMessenger.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Contact {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+AceSecurityStatus contactAceCheckAccessFunction(const char* functionName)
+{
+    return CONTACT_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerContactSetter,
+        Common::SecurityAccessor,
+        gSecurityAccessor);
+
+class_definition_options_t ConstructorClassOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED,
+    NULL,
+    NULL,
+    NULL
+};
+
+class_definition_options_t ClassOptions =
+{
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerContactSetter,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\contact] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch(...) {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, contactAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\contact] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "Contact";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch(...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\contact] on_frame_load_callback (%p)", context);
+    Common::GlobalContextManager::getInstance()->addGlobalContext(
+            static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\contact] on_frame_unload_callback (%p)", context);
+    Common::GlobalContextManager::getInstance()->removeGlobalContext(
+            static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_ADDRESS_BOOK_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSAddressBook::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSAddressBook::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_CLASS,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactManager::getClassRef,
+        &ClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContact::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContact::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_GROUP_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactGroup::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactGroup::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_REF_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactRef::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactRef::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_NAME_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactName::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactName::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_ORGANIZATION_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactOrganization::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactOrganization::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_WEB_SITE_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactWebSite::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactWebSite::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_ANNIVERSARY_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactAnniversary::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactAnniversary::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_ADDRESS_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactAddress::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactAddress::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_PHONE_NUMBER_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactPhoneNumber::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactPhoneNumber::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_EMAIL_ADDRESS_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactEmailAddress::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactEmailAddress::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_RELATIONSHIP_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactRelationship::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactRelationship::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTACT_CONTACT_INSTANT_MESSENGER_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Contact::JSContactInstantMessenger::getClassRef,
+        (js_class_constructor_cb_t)(DeviceAPI::Contact::JSContactInstantMessenger::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_END
+
+} // Contact
+} // DeviceAPI
+
diff --git a/src/Content/AddBatchCallbackUserData.cpp b/src/Content/AddBatchCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..b2c6272
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AddBatchCallbackUserData.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+
+using namespace DeviceAPI::Common;
+
+namespace Content {
+
+AddBatchCallbackUserData::AddBatchCallbackUserData(JSContextRef global_ctx,
+        const std::vector<ContentPtr>& items,
+        PlaylistPtr playlist_ptr) :
+                BaseCallbackUserData(global_ctx),
+                m_playlist_ptr(playlist_ptr),
+                m_items(items)
+{
+    LOGD("Entered");
+}
+
+AddBatchCallbackUserData::~AddBatchCallbackUserData()
+{
+}
+
+const std::vector<ContentPtr>& AddBatchCallbackUserData::getItems() const
+{
+    LOGD("Entered");
+    return m_items;
+}
+
+PlaylistPtr AddBatchCallbackUserData::getPlaylist()
+{
+    LOGD("Entered");
+    return m_playlist_ptr;
+}
+
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/AddBatchCallbackUserData.h b/src/Content/AddBatchCallbackUserData.h
new file mode 100644 (file)
index 0000000..ff76b66
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CONTENT_ADD_BATCH_CALLBACK_USER_DATA_H_
+#define _TIZEN_CONTENT_ADD_BATCH_CALLBACK_USER_DATA_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <vector>
+#include <memory>
+#include <CallbackUserData.h>
+#include "Content.h"
+#include "BaseCallbackUserData.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class Playlist;
+typedef std::shared_ptr<Playlist> PlaylistPtr;
+
+class AddBatchCallbackUserData: public BaseCallbackUserData {
+
+public:
+    AddBatchCallbackUserData(JSContextRef global_ctx,
+            const std::vector<ContentPtr>& items,
+            PlaylistPtr playlist_ptr);
+    virtual ~AddBatchCallbackUserData();
+
+    const std::vector<ContentPtr>& getItems() const;
+    PlaylistPtr getPlaylist();
+
+private:
+    std::vector<ContentPtr> m_items;
+    PlaylistPtr m_playlist_ptr;
+};
+
+} // DeviceAPI
+} // Calendar
+
+#endif /* _TIZEN_CONTENT_ADD_BATCH_CALLBACK_USER_DATA_H_ */
diff --git a/src/Content/AudioContent.cpp b/src/Content/AudioContent.cpp
new file mode 100755 (executable)
index 0000000..00d6a62
--- /dev/null
@@ -0,0 +1,134 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "AudioContent.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+AudioContent::AudioContent():
+            m_album(""),
+            m_copyright(""),
+            m_bitrate(0),
+            m_duration(0)
+{
+    m_type = "AUDIO";
+}
+
+AudioContent::~AudioContent()
+{
+    m_genres.clear();
+    m_artists.clear();
+    m_composers.clear();
+}
+
+std::string AudioContent::getAlbum() const
+{
+    return m_album;
+}
+
+void AudioContent::setAlbum(std::string album)
+{
+    m_album = album;
+}
+
+std::vector<std::string> AudioContent::getGenres() const
+{
+    return m_genres;
+}
+
+void AudioContent::setGenres(std::vector<std::string> genres)
+{
+    m_genres = genres;
+}
+
+std::vector<std::string> AudioContent::getArtists() const
+{
+    return m_artists;
+}
+
+void AudioContent::setArtists(std::vector<std::string> artists)
+{
+    m_artists = artists;
+}
+
+std::vector<std::string> AudioContent::getComposers() const
+{
+    return m_composers;
+}
+
+void AudioContent::setComposers(std::vector<std::string> composers)
+{
+    m_composers = composers;
+}
+
+AudioContentLyricsPtr AudioContent::getLyrics() const
+{
+    return m_lyrics;
+}
+
+void AudioContent::setLyrics(AudioContentLyricsPtr lyrics)
+{
+    m_lyrics = lyrics;
+}
+
+std::string AudioContent::getCopyright() const
+{
+    return m_copyright;
+}
+
+void AudioContent::setCopyright(std::string copyright)
+{
+    m_copyright = copyright;
+}
+
+unsigned long AudioContent::getBitrate() const
+{
+    return m_bitrate;
+}
+
+void AudioContent::setBitrate(unsigned long bitrate)
+{
+    m_bitrate = bitrate;
+}
+
+unsigned short AudioContent::getTrackNumber() const
+{
+    return m_trackNumber;
+}
+
+void AudioContent::setTrackNumber(unsigned short trackNumber)
+{
+    m_trackNumber = trackNumber;
+}
+
+unsigned long AudioContent::getDuration() const
+{
+    return m_duration;
+}
+
+void AudioContent::setDuration(unsigned long duration)
+{
+    m_duration = duration;
+}
+
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/AudioContent.h b/src/Content/AudioContent.h
new file mode 100755 (executable)
index 0000000..559e706
--- /dev/null
@@ -0,0 +1,85 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_AUDIO_CONTENT_H__
+#define __TIZEN_AUDIO_CONTENT_H__
+
+#include <Export.h>
+#include <MultiCallbackUserData.h>
+
+#include "ContentTypes.h"
+#include "AudioContentLyrics.h"
+
+#include "Content.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+class AudioContent;
+typedef std::shared_ptr<AudioContent> AudioContentPtr;
+
+class DLL_EXPORT AudioContent : public Content
+{
+public:
+    AudioContent();
+    virtual ~AudioContent();
+
+    std::string getAlbum() const;
+    void setAlbum(std::string album);
+
+    std::vector<std::string> getGenres() const;
+    void setGenres(std::vector<std::string> genres);
+
+    std::vector<std::string> getArtists() const;
+    void setArtists(std::vector<std::string> artists);
+
+    std::vector<std::string> getComposers() const;
+    void setComposers(std::vector<std::string> composers);
+
+    AudioContentLyricsPtr getLyrics() const;
+    void setLyrics(AudioContentLyricsPtr lyrics);
+
+    std::string getCopyright() const;
+    void setCopyright(std::string copyright);
+
+    unsigned long getBitrate() const;
+    void setBitrate(unsigned long bitrate);
+
+    unsigned short getTrackNumber() const;
+    void setTrackNumber(unsigned short trackNumber);
+
+    unsigned long getDuration() const;
+    void setDuration(unsigned long duration);
+
+private:
+    std::string m_album;
+    std::vector<std::string> m_genres;
+    std::vector<std::string> m_artists;
+    std::vector<std::string> m_composers;
+    AudioContentLyricsPtr m_lyrics;
+    std::string m_copyright;
+    unsigned long m_bitrate;
+    unsigned short m_trackNumber;
+    unsigned long m_duration;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_AUDIO_CONTENT_H__
diff --git a/src/Content/AudioContentLyrics.cpp b/src/Content/AudioContentLyrics.cpp
new file mode 100644 (file)
index 0000000..109dd5d
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "AudioContentLyrics.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+AudioContentLyrics::AudioContentLyrics():
+            m_type("")
+{
+}
+
+AudioContentLyrics::~AudioContentLyrics()
+{
+}
+
+std::string AudioContentLyrics::getType() const
+{
+    return m_type;
+}
+
+void AudioContentLyrics::setType(std::string type)
+{
+    m_type = type;
+}
+
+std::vector<unsigned long> AudioContentLyrics::getTimestamps() const
+{
+    return m_timestamps;
+}
+
+void AudioContentLyrics::setTimestamps(std::vector<unsigned long> timestamps)
+{
+    m_timestamps = timestamps;
+}
+
+std::vector<std::string> AudioContentLyrics::getTexts() const
+{
+    return m_texts;
+}
+
+void AudioContentLyrics::setTexts(std::vector<std::string> texts)
+{
+    m_texts = texts;
+}
+
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/AudioContentLyrics.h b/src/Content/AudioContentLyrics.h
new file mode 100755 (executable)
index 0000000..479adde
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_AUDIO_CONTENT_LYRICS_H__
+#define __TIZEN_AUDIO_CONTENT_LYRICS_H__
+
+#include <MultiCallbackUserData.h>
+
+#include "ContentTypes.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+class AudioContentLyrics;
+typedef std::shared_ptr<AudioContentLyrics> AudioContentLyricsPtr;
+
+class AudioContentLyrics
+{
+public:
+    AudioContentLyrics();
+    virtual ~AudioContentLyrics();
+
+    std::string getType() const;
+    void setType(std::string type);
+
+    std::vector<unsigned long> getTimestamps() const;
+    void setTimestamps(std::vector<unsigned long> timestamps);
+
+    std::vector<std::string> getTexts() const;
+    void setTexts(std::vector<std::string> texts);
+
+private:
+    std::string m_type;
+    std::vector<unsigned long> m_timestamps;
+    std::vector<std::string> m_texts;
+};
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_AUDIO_CONTENT_LYRICS_H__
diff --git a/src/Content/AudioLyricsUtil.cpp b/src/Content/AudioLyricsUtil.cpp
new file mode 100755 (executable)
index 0000000..3040281
--- /dev/null
@@ -0,0 +1,151 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "ContentUtility.h"
+
+#include "AudioLyricsUtil.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+AudioLyricsUtil::AudioLyricsUtil() : m_extractor(NULL), m_lyrics(new AudioContentLyrics())
+{
+}
+
+AudioLyricsUtil::~AudioLyricsUtil()
+{
+}
+
+AudioContentLyricsPtr AudioLyricsUtil::getAudioLyrics()
+{
+    return m_lyrics;
+}
+
+
+bool AudioLyricsUtil::fetchLyrics(std::string URI)
+{
+    LOGD("Entered");
+    bool ret = true;
+    int err = metadata_extractor_create(&m_extractor);
+    if ( METADATA_EXTRACTOR_ERROR_NONE != err)
+    {
+        LOGE("ret: %d", err);
+        ContentUtility::throwMetadataException<UnknownException>(
+                err, "metadata_extractor_create()");
+    }
+
+    err = metadata_extractor_set_path(m_extractor, URI.c_str());
+    if(METADATA_EXTRACTOR_ERROR_NONE == err)
+    {
+        std::vector<unsigned long> timestamps;
+        std::vector<std::string> texts;
+        char* strSyncTextNum=NULL;
+        metadata_extractor_attr_e attr = METADATA_SYNCLYRICS_NUM;
+        err = metadata_extractor_get_metadata(m_extractor, attr, &strSyncTextNum);
+        if ( METADATA_EXTRACTOR_ERROR_NONE == err && strSyncTextNum )
+        {
+            int nSyncTextNum = atoi(strSyncTextNum);
+            //istringstream(strSyncTextNum) >> nSyncTextNum;
+            free(strSyncTextNum);
+            strSyncTextNum = NULL;
+
+            if ( nSyncTextNum > 0)
+            {
+                m_lyrics->setType("SYNCHRONIZED");
+                for(int i=0; i < nSyncTextNum; i++)
+                {
+                    unsigned long time_info = 0;
+                    char * lyrics = NULL;
+                    err = metadata_extractor_get_synclyrics(m_extractor, i, &time_info, &lyrics);
+                    if ( METADATA_EXTRACTOR_ERROR_NONE == err)
+                    {
+                        timestamps.push_back(time_info);
+                        texts.push_back(lyrics);
+                        free(lyrics);
+                    } else {
+                        LOGW("%s", ContentUtility::getMetadataErrorMessage(
+                                err, "metadata_extractor_get_synclyrics()").c_str());
+                    }
+                }
+                ret = true;
+            }
+            else
+            {
+                char* unSyncText = NULL;
+                attr = METADATA_UNSYNCLYRICS;
+
+                err = metadata_extractor_get_metadata(m_extractor, attr, &unSyncText);
+                if ( METADATA_EXTRACTOR_ERROR_NONE == err)
+                {
+                    if (unSyncText)
+                    {
+                        m_lyrics->setType("UNSYNCHRONIZED");
+                        texts.push_back(unSyncText);
+
+                        free(unSyncText);
+                        unSyncText = NULL;
+                        ret = true;
+                    }
+                    else
+                    {
+                        ret = false;
+                    }
+                } else {
+                    LOGW("%s", ContentUtility::getMetadataErrorMessage(
+                            err, "metadata_extractor_get_metadata()").c_str());
+                }
+
+            }
+
+            if(ret)
+            {
+                m_lyrics->setTimestamps(timestamps);
+                m_lyrics->setTexts(texts);
+            }
+        }
+        else
+        {
+            LOGE("%s", ContentUtility::getMetadataErrorMessage(
+                    err, "metadata_extractor_get_metadata()").c_str());
+            ret = false;
+        }
+
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMetadataErrorMessage(
+                err, "metadata_extractor_set_path()").c_str());
+        ret = false;
+    }
+
+    if(m_extractor != NULL)
+    {
+        err = metadata_extractor_destroy(m_extractor);
+        if(METADATA_EXTRACTOR_ERROR_NONE != err)
+        {
+            LOGW("%s", ContentUtility::getMetadataErrorMessage(
+                    err, "metadata_extractor_destroy()").c_str());
+        }
+    }
+    return ret;
+}
+
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/AudioLyricsUtil.h b/src/Content/AudioLyricsUtil.h
new file mode 100755 (executable)
index 0000000..cd6f5a1
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_AUDIO_LYRICS_UTIL_H__
+#define __TIZEN_AUDIO_LYRICS_UTIL_H__
+
+//#include <IFilter.h>
+//#include <SortMode.h>
+
+#include "AudioContentLyrics.h"
+
+#include <metadata_extractor.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+class AudioLyricsUtil
+{
+public:
+    AudioLyricsUtil();
+    virtual ~AudioLyricsUtil();
+
+    bool fetchLyrics(std::string);
+
+    AudioContentLyricsPtr getAudioLyrics();
+
+private:
+    metadata_extractor_h m_extractor;
+    AudioContentLyricsPtr m_lyrics;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_AUDIO_LYRICS_UTIL_H__
diff --git a/src/Content/BaseCallbackUserData.cpp b/src/Content/BaseCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..9372b95
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "BaseCallbackUserData.h"
+
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+BaseCallbackUserData::BaseCallbackUserData(
+        JSContextRef global_ctx) :
+                CallbackUserData(global_ctx),
+                m_is_error(false)
+{
+}
+
+BaseCallbackUserData::~BaseCallbackUserData()
+{
+}
+
+void BaseCallbackUserData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool BaseCallbackUserData::isError() const
+{
+    return m_is_error;
+}
+
+const std::string& BaseCallbackUserData::getErrorName() const
+{
+    return m_err_name;
+}
+
+const std::string& BaseCallbackUserData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/BaseCallbackUserData.h b/src/Content/BaseCallbackUserData.h
new file mode 100644 (file)
index 0000000..e2297f1
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_BASE_CALLBACK_USER_DATA_H__
+#define __TIZEN_CONTENT_BASE_CALLBACK_USER_DATA_H__
+
+#include <CallbackUserData.h>
+#include <string>
+
+namespace DeviceAPI {
+namespace Content {
+
+class BaseCallbackUserData : public Common::CallbackUserData
+{
+public:
+    BaseCallbackUserData(JSContextRef global_ctx);
+    virtual ~BaseCallbackUserData();
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+
+    const std::string& getErrorName() const;
+    const std::string& getErrorMessage() const;
+
+private:
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+};
+
+}//Content
+}//DeviceAPI
+
+#endif /* __TIZEN_CONTENT_BASE_CALLBACK_USER_DATA_H__ */
diff --git a/src/Content/CMakeLists.txt b/src/Content/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..549fde2
--- /dev/null
@@ -0,0 +1,109 @@
+
+SET(TARGET_NAME ${content_target})
+SET(DESTINATION_NAME ${content_dest})
+SET(TARGET_IMPL_NAME ${content_impl})
+SET(TARGET_CONFIG_NAME ${content_config})
+
+PKG_CHECK_MODULES(platform_pkgs_content REQUIRED capi-content-media-content capi-media-metadata-extractor)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+SET(INCLUDE_DIRS
+    ${filesystem_include}
+    ${tizen_include}
+    ${platform_pkgs_content_INCLUDE_DIRS}
+)
+
+INCLUDE_DIRECTORIES(${INCLUDE_COMMON} ${INCLUDE_DIRS})
+MESSAGE(STATUS "${TARGET_NAME} module includes: INCLUDE_COMMON ${INCLUDE_DIRS}")
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${filesystem_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSContentManager.cpp
+    JSContentDirectory.cpp
+    JSContent.cpp
+    JSVideoContent.cpp
+    JSAudioContentLyrics.cpp
+    JSAudioContent.cpp
+    JSImageContent.cpp
+    ContentManager.cpp
+    ContentChangeCallback.cpp
+    ContentDirectory.cpp
+    Content.cpp
+    VideoContent.cpp
+    AudioContentLyrics.cpp
+    AudioContent.cpp
+    ImageContent.cpp
+    ContentHelper.cpp
+    ContentUtility.cpp
+    AudioLyricsUtil.cpp
+    ContentFilterQueryGenerator.cpp
+    ContentCallback.cpp
+
+    AddBatchCallbackUserData.cpp
+    BaseCallbackUserData.cpp
+    CreatePlaylistCallbackUserData.cpp
+    GetPlaylistItemsRequest.cpp
+    GetPlaylistsRequest.cpp
+    JSPlaylist.cpp
+    JSPlaylistItem.cpp
+    MoveItemCallbackUserData.cpp
+    PlaylistArraySuccessCallbackUserData.cpp
+    PlaylistContentCallback.cpp
+    PlaylistCopyUtil.cpp
+    Playlist.cpp
+    PlaylistItem.cpp
+    PlaylistUtils.cpp
+    RemoveBatchCallbackUserData.cpp
+    RemovePlaylistCallbackUserData.cpp
+    SetItemsOrderCallbackUserData.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+
+SET(LINK_LIBS
+    ${tizen_impl}
+    ${filesystem_impl}
+    ${filesystem_config}
+    ${platform_pkgs_content_LIBRARIES}
+    ${TARGET_CONFIG_NAME}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME} ${LIBS_COMMON} ${LINK_LIBS})
+MESSAGE(STATUS "${TARGET_NAME} module links: LIBS_COMMON ${LINK_LIBS}")
+
+
+SET(SRCS_CONFIG
+    plugin_config.cpp
+)
+
+ADD_LIBRARY(${TARGET_CONFIG_NAME} SHARED ${SRCS_CONFIG})
+
+TARGET_LINK_LIBRARIES(${TARGET_CONFIG_NAME}
+    ${LIBS_COMMON}
+)
+
+SET(SRCS
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+    ${TARGET_CONFIG_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_CONFIG_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/content
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Content/Content.cpp b/src/Content/Content.cpp
new file mode 100755 (executable)
index 0000000..48fbdfe
--- /dev/null
@@ -0,0 +1,207 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "Content.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+Content::Content():
+            m_name(""),
+            m_type("OTHER"),
+            m_mimeType(""),
+            m_title(""),
+            m_contentURI(""),
+            m_size(0),
+            m_description(""),
+            m_rating(0),
+            m_is_favorite(false)
+{
+    m_editableAttributes.push_back("name");
+    m_editableAttributes.push_back("rating");
+    m_editableAttributes.push_back("description");
+    m_editableAttributes.push_back("isFavorite");
+    m_isReleseDate = false;
+    m_isModifiedDate = false;
+}
+
+Content::~Content()
+{
+    m_thumbnailURIs.clear();
+    m_editableAttributes.clear();
+}
+
+std::vector<std::string> Content::getEditableAttributes() const
+{
+    return m_editableAttributes;
+}
+
+void Content::setEditableAttributes(std::vector<std::string> editableAttributes)
+{
+    m_editableAttributes = editableAttributes;
+}
+
+std::string Content::getId() const
+{
+    return m_id;
+}
+
+void Content::setId(std::string id)
+{
+    m_id = id;
+}
+
+std::string Content::getName() const
+{
+    return m_name;
+}
+
+void Content::setName(std::string name)
+{
+    m_name = name;
+}
+
+std::string Content::getType() const
+{
+    return m_type;
+}
+
+void Content::setType(std::string type)
+{
+    m_type = type;
+}
+
+std::string Content::getMimeType() const
+{
+    return m_mimeType;
+}
+
+void Content::setMimeType(std::string mimeType)
+{
+    m_mimeType = mimeType;
+}
+
+std::string Content::getTitle() const
+{
+    return m_title;
+}
+
+void Content::setTitle(std::string title)
+{
+    m_title = title;
+}
+
+std::string Content::getContentURI() const
+{
+    return m_contentURI;
+}
+
+void Content::setContentURI(std::string contentURI)
+{
+    m_contentURI = contentURI;
+}
+
+std::vector<std::string> Content::getThumbnailURIs() const
+{
+    return m_thumbnailURIs;
+}
+
+void Content::setThumbnailURIs(std::vector<std::string> thumbnailURIs)
+{
+    m_thumbnailURIs = thumbnailURIs;
+}
+
+time_t Content::getReleaseDate() const
+{
+    return m_releaseDate;
+}
+
+void Content::setReleaseDate(time_t releaseDate)
+{
+    m_releaseDate = releaseDate;
+    m_isReleseDate = true;
+}
+
+time_t Content::getModifiedDate() const
+{
+    return m_modifiedDate;
+}
+
+void Content::setModifiedDate(time_t modifiedDate)
+{
+    m_modifiedDate = modifiedDate;
+    m_isModifiedDate = true;
+}
+
+unsigned long Content::getSize() const
+{
+    return m_size;
+}
+
+void Content::setSize(unsigned long size)
+{
+    m_size = size;
+}
+
+std::string Content::getDescription() const
+{
+    return m_description;
+}
+
+void Content::setDescription(std::string description)
+{
+    m_description = description;
+}
+
+unsigned long Content::getRating() const
+{
+    return m_rating;
+}
+
+void Content::setRating(unsigned long rating)
+{
+    if(10 >= rating){
+        m_rating = rating;
+    } else {
+        LOGW("Incorrect rating value");
+    }
+}
+
+bool Content::getIsFavorite() const
+{
+    return m_is_favorite;
+}
+
+void Content::setIsFavorite(bool favorite)
+{
+    m_is_favorite = favorite;
+}
+
+bool Content::isReleaseDate()
+{
+    return m_isReleseDate;
+}
+bool Content::isModefiedDate()
+{
+    return m_isModifiedDate;
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/Content.h b/src/Content/Content.h
new file mode 100755 (executable)
index 0000000..8ac967b
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_H__
+#define __TIZEN_CONTENT_H__
+
+#include <Export.h>
+#include <MultiCallbackUserData.h>
+
+#include "ContentTypes.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+class Content;
+typedef std::shared_ptr<Content> ContentPtr;
+
+struct ContentHolder{
+    ContentPtr ptr;
+};
+
+class DLL_EXPORT Content
+{
+public:
+    Content();
+    virtual ~Content();
+
+    std::vector<std::string> getEditableAttributes() const;
+    void setEditableAttributes(std::vector<std::string> editableAttributes);
+
+    std::string getId() const;
+    void setId(std::string id);
+
+    std::string getName() const;
+    void setName(std::string name);
+
+    std::string getType() const;
+    void setType(std::string type);
+
+    std::string getMimeType() const;
+    void setMimeType(std::string mimeType);
+
+    std::string getTitle() const;
+    void setTitle(std::string title);
+
+    std::string getContentURI() const;
+    void setContentURI(std::string contentURI);
+
+    std::vector<std::string> getThumbnailURIs() const;
+    void setThumbnailURIs(std::vector<std::string> thumbnailURIs);
+
+    time_t getReleaseDate() const;
+    void setReleaseDate(time_t releaseDate);
+
+    time_t getModifiedDate() const;
+    void setModifiedDate(time_t modifiedDate);
+
+    unsigned long getSize() const;
+    void setSize(unsigned long size);
+
+    std::string getDescription() const;
+    void setDescription(std::string description);
+
+    unsigned long getRating() const;
+    void setRating(unsigned long rating);
+
+    bool getIsFavorite() const;
+    void setIsFavorite(bool favorite);
+
+    bool isReleaseDate();
+    bool isModefiedDate();
+
+protected:
+    std::vector<std::string> m_editableAttributes;
+    std::string m_id;
+    std::string m_name;
+    std::string m_type;
+    std::string m_mimeType;
+    std::string m_title;
+    std::string m_contentURI;
+    std::vector<std::string> m_thumbnailURIs;
+    time_t m_releaseDate;
+    time_t m_modifiedDate;
+    unsigned long m_size;
+    std::string m_description;
+    unsigned long m_rating;
+    bool m_is_favorite;
+
+private:
+    bool m_isReleseDate;
+    bool m_isModifiedDate;
+};
+
+typedef std::vector<ContentPtr> ContentLst;
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_CONTENT_H__
diff --git a/src/Content/ContentCallback.cpp b/src/Content/ContentCallback.cpp
new file mode 100644 (file)
index 0000000..80d6e91
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ContentCallback.h"
+#include <TimeTracer.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+using namespace DeviceAPI::Common;
+
+ContentCallback::ContentCallback(JSContextRef globalCtx)
+{
+    m_callback = std::shared_ptr<MultiCallbackUserData>(new MultiCallbackUserData(globalCtx));
+}
+
+ContentCallback::~ContentCallback()
+{
+
+}
+
+void ContentCallback::setSuccessCallback(JSValueRef onSuccess_ref)
+{
+    if( onSuccess_ref && JSValueIsObject(m_callback->getContext(), onSuccess_ref) ) {
+        JSObjectRef success = JSValueToObject(m_callback->getContext(),
+                onSuccess_ref, NULL);
+        m_callback->setCallback("onsuccess", success);
+    }
+}
+
+void ContentCallback::setErrorCallback(JSValueRef onError_ref)
+{
+    if( onError_ref && JSValueIsObject(m_callback->getContext(), onError_ref) ) {
+        JSObjectRef error = JSValueToObject(m_callback->getContext(),
+                onError_ref, NULL);
+        m_callback->setCallback("onerror", error);
+    }
+}
+
+void ContentCallback::onSuccess(){
+    m_callback->invokeCallback("onsuccess");
+    TIME_TRACER_ITEM_END(CONTENT_TT_UPDATE_BATCH_TOTAL, CONTENT_TIME_TRACER_SHOW);
+}
+
+void ContentCallback::onError(JSObjectRef& err)
+{
+    m_callback->invokeCallback("onerror", err);
+}
+
+void ContentCallback::onError(std::string message)
+{
+    JSObjectRef jsResult = JSWebAPIErrorFactory::makeErrorObject(
+            m_callback->getContext(), JSWebAPIErrorFactory::UNKNOWN_ERROR,
+            message.c_str());
+    if(jsResult) {
+        m_callback->invokeCallback("onerror", jsResult);
+    }
+}
+
+void ContentCallback::onError()
+{
+    JSObjectRef jsResult = JSWebAPIErrorFactory::makeErrorObject(
+            m_callback->getContext(), JSWebAPIErrorFactory::UNKNOWN_ERROR,
+            m_err.c_str());
+    if(jsResult) {
+        m_callback->invokeCallback("onerror", jsResult);
+    }
+}
+
+void ContentCallback::setErrMsg(std::string msg) {
+    m_err = msg;
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/ContentCallback.h b/src/Content/ContentCallback.h
new file mode 100755 (executable)
index 0000000..bb174c5
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_CALLBACK_H__
+#define __TIZEN_CONTENT_CALLBACK_H__
+
+#include <string>
+#include <memory>
+
+#include <Logger.h>
+
+#include <JSWebAPIErrorFactory.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+
+#include <JSUtil.h>
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class ContentCallback
+{
+public:
+    ContentCallback(JSContextRef globalCtx);
+    virtual ~ContentCallback();
+
+    void setSuccessCallback(JSValueRef onSuccess_ref);
+    void setErrorCallback(JSValueRef onError_ref);
+
+    virtual void onSuccess();
+    void onError(JSObjectRef& err);
+    void onError(std::string message);
+    void onError();
+
+    void setErrMsg(std::string msg);
+
+protected:
+    Common::MultiCallbackUserDataPtr m_callback;
+
+private:
+    std::string m_err;
+};
+
+typedef std::shared_ptr<ContentCallback> ContentCallbackPtr;
+
+} //namespace Content
+} //namespace DeviceAPI
+
+#endif // __TIZEN_CONTENT_FIND_CALLBACK_H__
diff --git a/src/Content/ContentChangeCallback.cpp b/src/Content/ContentChangeCallback.cpp
new file mode 100755 (executable)
index 0000000..8c4ce3c
--- /dev/null
@@ -0,0 +1,150 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+#include "ContentChangeCallback.h"
+#include "JSContent.h"
+#include "JSImageContent.h"
+#include "JSVideoContent.h"
+#include "JSAudioContent.h"
+#include <GlobalContextManager.h>
+
+//using namespace WrtDeviceApis::Commons;
+//using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace DeviceAPI {
+namespace Content {
+
+ContentChangeCallback::ContentChangeCallback(JSContextRef globalCtx, JSObjectRef object)
+{
+    m_callback = new MultiCallbackUserData(globalCtx);
+
+    JSValueRef oncontentadded_ref = JSUtil::getProperty(globalCtx , object, "oncontentadded");
+    if(!JSValueIsUndefined(globalCtx,oncontentadded_ref)) {
+        m_callback->setCallback("oncontentadded", JSUtil::JSValueToObject(globalCtx, oncontentadded_ref));
+    }
+    JSValueRef oncontentupdated_ref = JSUtil::getProperty(globalCtx , object, "oncontentupdated");
+    if(!JSValueIsUndefined(globalCtx,oncontentupdated_ref)) {
+        m_callback->setCallback("oncontentupdated", JSUtil::JSValueToObject(globalCtx, oncontentupdated_ref));
+    }
+    JSValueRef oncontentremoved_ref = JSUtil::getProperty(globalCtx , object, "oncontentremoved");
+    if(!JSValueIsUndefined(globalCtx,oncontentremoved_ref)) {
+        m_callback->setCallback("oncontentremoved", JSUtil::JSValueToObject(globalCtx, oncontentremoved_ref));
+    }
+
+}
+
+ContentChangeCallback::~ContentChangeCallback()
+{
+    if(m_callback != NULL){
+        delete m_callback;
+        m_callback = NULL;
+    }
+}
+
+void ContentChangeCallback::oncontentadded(ImageContentPtr content)
+{
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef jsObject = JSImageContent::CreateJSObject(context,content);
+    m_callback->invokeCallback("oncontentadded", jsObject);
+}
+
+void ContentChangeCallback::oncontentadded(VideoContentPtr content)
+{
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef jsObject = JSVideoContent::CreateJSObject(context,content);
+    m_callback->invokeCallback("oncontentadded", jsObject);
+}
+
+void ContentChangeCallback::oncontentadded(AudioContentPtr content)
+{
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef jsObject = JSAudioContent::CreateJSObject(context,content);
+    m_callback->invokeCallback("oncontentadded", jsObject);
+}
+
+void ContentChangeCallback::oncontentadded(ContentPtr content)
+{
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef jsObject = JSContent::CreateJSObject(context, content);
+    m_callback->invokeCallback("oncontentadded", jsObject);
+}
+
+void ContentChangeCallback::oncontentupdated(ImageContentPtr content)
+{
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef jsObject = JSImageContent::CreateJSObject(context,content);
+    m_callback->invokeCallback("oncontentupdated", jsObject);
+}
+
+void ContentChangeCallback::oncontentupdated(VideoContentPtr content)
+{
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef jsObject = JSVideoContent::CreateJSObject(context,content);
+    m_callback->invokeCallback("oncontentupdated", jsObject);
+}
+
+void ContentChangeCallback::oncontentupdated(AudioContentPtr content)
+{
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef jsObject = JSAudioContent::CreateJSObject(context,content);
+    m_callback->invokeCallback("oncontentupdated", jsObject);
+}
+
+void ContentChangeCallback::oncontentupdated(ContentPtr content)
+{
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef jsObject = JSContent::CreateJSObject(context, content);
+    m_callback->invokeCallback("oncontentupdated", jsObject);
+
+}
+
+void ContentChangeCallback::oncontentremoved(std::string id)
+{
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef jsResult = JSUtil::toJSValueRef(context,id);
+    m_callback->invokeCallback("oncontentremoved", jsResult);
+}
+
+JSContextRef ContentChangeCallback::getContext() const
+{
+    return m_callback->getContext();
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/ContentChangeCallback.h b/src/Content/ContentChangeCallback.h
new file mode 100755 (executable)
index 0000000..3cd6959
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_CHANGE_CALLBACK_H__
+#define __TIZEN_CONTENT_CHANGE_CALLBACK_H__
+
+#include <string>
+#include <memory>
+#include <list>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+
+#include "Content.h"
+#include "ImageContent.h"
+#include "VideoContent.h"
+#include "AudioContent.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+class ContentChangeCallback
+{
+public:
+    ContentChangeCallback(JSContextRef globalCtx, JSObjectRef object);
+    virtual ~ContentChangeCallback();
+
+    void oncontentadded(ContentPtr content);
+    void oncontentadded(ImageContentPtr content);
+    void oncontentadded(VideoContentPtr content);
+    void oncontentadded(AudioContentPtr content);
+
+    void oncontentupdated(ContentPtr content);
+    void oncontentupdated(ImageContentPtr content);
+    void oncontentupdated(VideoContentPtr content);
+    void oncontentupdated(AudioContentPtr content);
+
+    void oncontentremoved(std::string id);
+
+    JSContextRef getContext() const;
+
+private:
+    MultiCallbackUserData *m_callback;
+};
+
+typedef std::shared_ptr<ContentChangeCallback> ContentChangeCallbackPtr;
+typedef std::list<std::shared_ptr<ContentChangeCallback>> ContentChangeCallbackPtrList;
+
+} // Content
+} // DeviceAPI
+
+
+
+#endif // __TIZEN_CONTENT_CHANGE_CALLBACK_H__
diff --git a/src/Content/ContentDirectory.cpp b/src/Content/ContentDirectory.cpp
new file mode 100644 (file)
index 0000000..40dfefe
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "ContentDirectory.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+ContentDirectory::ContentDirectory():
+            m_directoryURI(""),
+            m_title(""),
+            m_storageType("")
+{
+}
+
+ContentDirectory::~ContentDirectory()
+{
+}
+
+std::string ContentDirectory::getId() const
+{
+    return m_id;
+}
+
+void ContentDirectory::setId(const std::string& id)
+{
+    m_id = id;
+}
+
+std::string ContentDirectory::getDirectoryURI() const
+{
+    return m_directoryURI;
+}
+
+void ContentDirectory::setDirectoryURI(const std::string& directoryURI)
+{
+    m_directoryURI = directoryURI;
+}
+
+std::string ContentDirectory::getTitle() const
+{
+    return m_title;
+}
+
+void ContentDirectory::setTitle(const std::string& title)
+{
+    m_title = title;
+}
+
+std::string ContentDirectory::getStorageType() const
+{
+    return m_storageType;
+}
+
+void ContentDirectory::setStorageType(const std::string& storageType)
+{
+    m_storageType = storageType;
+}
+
+time_t ContentDirectory::getModifiedDate() const
+{
+    return m_modifiedDate;
+}
+
+void ContentDirectory::setModifiedDate(time_t modifiedDate)
+{
+    m_modifiedDate = modifiedDate;
+}
+
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/ContentDirectory.h b/src/Content/ContentDirectory.h
new file mode 100755 (executable)
index 0000000..75e8670
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_DIRECTORY_H__
+#define __TIZEN_CONTENT_DIRECTORY_H__
+
+#include <MultiCallbackUserData.h>
+
+#include "ContentTypes.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+class ContentDirectory;
+typedef std::shared_ptr<ContentDirectory> ContentDirectoryPtr;
+typedef std::vector<ContentDirectoryPtr> DirectoryLst;
+
+class ContentDirectory
+{
+public:
+    ContentDirectory();
+    virtual ~ContentDirectory();
+
+    std::string getId() const;
+    void setId(const std::string& id);
+
+    std::string getDirectoryURI() const;
+    void setDirectoryURI(const std::string& directoryURI);
+
+    std::string getTitle() const;
+    void setTitle(const std::string& title);
+
+    std::string getStorageType() const;
+    void setStorageType(const std::string& storageType);
+
+    time_t getModifiedDate() const;
+    void setModifiedDate(time_t modifiedDate);
+
+private:
+    std::string m_id;
+    std::string m_directoryURI;
+    std::string m_title;
+    std::string m_storageType;
+    time_t m_modifiedDate;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_CONTENT_DIRECTORY_H__
diff --git a/src/Content/ContentFilterQueryGenerator.cpp b/src/Content/ContentFilterQueryGenerator.cpp
new file mode 100644 (file)
index 0000000..ba24b24
--- /dev/null
@@ -0,0 +1,421 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ContentFilterQueryGenerator.h"
+#include <Logger.h>
+#include <map>
+#include "ContentUtility.h"
+
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Content {
+
+const std::string STR_LEFT_BRACKET = " (";
+const std::string STR_RIGHT_BRACKET = ") ";
+const std::string STR_AND = " AND ";
+const std::string STR_OR = " OR ";
+const std::string STR_GREATER_THAN = ">";
+const std::string STR_LESS_THAN = "<";
+const std::string STR_EQUAL = "=";
+const std::string STR_S_QUOTATION = "'";
+const std::string STR_PERCENT = "%";
+
+enum condition_e {
+    EQUAL,
+    NOT_EQUAL,
+    GREATER_THAN,
+    LESS_THAN,
+    GREATER_THAN_OR_EQUAL,
+    LESS_THAN_OR_EQUAL,
+    LIKE,
+    EXISTS,
+    CONDITION_MAX
+};
+
+static std::string operatorKey[] =
+{
+        " = ",              //EQUAL
+        " NOT IN ",     //NOT_EQUAL
+        " > ",              //GREATER_THAN
+        " < ",              //LESS_THAN
+        " >= ",             //GREATER_THAN_OR_EQUAL
+        " <= ",             //LESS_THAN_OR_EQUAL
+        " LIKE ",       // like
+        " is not null "         //EXISTS
+};
+
+//enum media_attribute_e {
+//    MEDIA_ID = 0,
+//    MEDIA_TITLE,
+//    MEDIA_FILEPATH,
+//    MEDIA_THUMBNAILPATH,
+//    MEDIA_CREATEDDATE,
+//    MEDIA_MODIFIEDDATE,
+//    MEDIA_DESCRIPTION,
+//    MEDIA_RATING
+//};
+
+std::map<std::string, std::string> ContentFilterQueryGenerator::attrEnumMap = {
+        //media item attribues.
+        {"id", "MEDIA_ID"},
+        {"type", "MEDIA_TYPE"},
+        {"mimeType", "MEDIA_MIME_TYPE"},
+        {"name", "MEDIA_DISPLAY_NAME"},
+        {"title", "MEDIA_TITLE"},
+        {"contentURI", "MEDIA_PATH"},
+        {"thumbnailURIs", "MEDIA_THUMBNAIL_PATH"},
+        {"description", "MEDIA_DESCRIPTION"},
+        {"rating", "MEDIA_RATING"},
+        {"createdDate", "MEDIA_ADDED_TIME"},
+        {"releaseDate", "MEDIA_DATETAKEN"},
+        {"modifiedDate", "MEDIA_MODIFIED_TIME"},
+        {"isFavorite", "MEDIA_FAVORITE"},
+        //media image,video,audio attribues.
+        {"geolocation.latitude", "MEDIA_LATITUDE"},
+        {"geolocation.longitude", "MEDIA_LONGITUDE"},
+        {"album", "MEDIA_ALBUM"},
+        {"artists", "MEDIA_ARTIST"},
+        {"width", "MEDIA_WIDTH"},
+        {"height", "MEDIA_HEIGHT"},
+        {"genres", "MEDIA_GENRE"},
+        {"size", "MEDIA_SIZE"}
+};
+
+ContentFilterQueryGenerator::ContentFilterQueryGenerator()
+{
+    m_query = "";
+}
+
+ContentFilterQueryGenerator::~ContentFilterQueryGenerator()
+{
+}
+
+void ContentFilterQueryGenerator::generate(AbstractFilterPtr src_filter)
+{
+    LOGD("Entered");
+
+    if(!src_filter) {
+        LOGW("src_filter is NULL");
+    }
+    else {
+        LOGD("src_filter is %p, type:%d", src_filter.get(), src_filter->getFilterType());
+    }
+
+    for(FilterIterator it(src_filter); it.isEnd() == false; ++it) {
+
+        switch(it.getState()) {
+            case FIS_COMPOSITE_START: {
+                LOGD("COMPOSITE START {");
+                m_query.append(STR_LEFT_BRACKET);
+            } break;
+            case FIS_COMPOSITE_END: {
+                LOGD("} COMPOSITE END");
+                m_query.append(STR_RIGHT_BRACKET);
+            } break;
+            case FIS_ATTRIBUTE_FILTER:
+            case FIS_ATTRIBUTE_RANGE_FILTER: {
+
+                if(FIS_ATTRIBUTE_FILTER == it.getState()) {
+                    LOGD("ATTRIBUTE Filter");
+                    visitAttribute(castToAttributeFilter(*it));
+                }
+                else {
+                    LOGD("ATTRIBUTE RANGE Filter");
+                    visitAttributeRange(castToAttributeRangeFilter(*it));
+                }
+
+                if(it.isInsideCompositeFilter() && !it.isLastCompositeSubFilter()) {
+                    CompositeFilterPtr c_filter = it.getCurrentCompositeFilter();
+
+                    if(Tizen::UNION == c_filter->getType()) {
+                        m_query.append(STR_OR);
+                        LOGD("added OR operator");
+                    }
+                    else {
+                        m_query.append(STR_AND);
+                        LOGD("added AND operator");
+                    }
+                }
+            } break;
+
+            default:
+                break;
+        }
+    }
+}
+
+std::string ContentFilterQueryGenerator::getResult() const
+{
+    return m_query;
+}
+
+void ContentFilterQueryGenerator::visitAttribute(AttributeFilterPtr attr_filter)
+{
+    LOGD("Entered");
+    if(!attr_filter) {
+        LOGW("AttributeFilterPtr is NULL");
+        return;
+    }
+
+    const AnyPtr& match_value = attr_filter->getMatchValue();
+    if (!match_value) {
+        LOGW("match_value is NULL");
+        return;
+    }
+
+    const std::string &attr_name = getPlatformAttr(attr_filter->getAttributeName());
+    const Tizen::FilterMatchFlag &match_flag = attr_filter->getMatchFlag();
+    m_query.append(convertAttribute(attr_name, match_value, match_flag));
+}
+
+void ContentFilterQueryGenerator::visitAttributeRange(
+        AttributeRangeFilterPtr attr_range_filter)
+{
+    LOGD("Entered");
+    if(!attr_range_filter) {
+        return;
+    }
+
+    AnyPtr initial_value = attr_range_filter->getInitialValue();
+    AnyPtr end_value = attr_range_filter->getEndValue();
+    if(!initial_value || !end_value) {
+        LOGD("initial_value or end_value is NULL");
+        return;
+    }
+
+    const std::string& attr_name = getPlatformAttr(attr_range_filter->getAttributeName());
+
+    std::string str;
+    std::string initialValueStr;
+    std::string endValueStr;
+
+    if(!initial_value->isNullOrUndefined())
+    {
+        if(attr_name.compare("MEDIA_DATETAKEN")==0
+                || attr_name.compare("MEDIA_MODIFIED_TIME")==0
+                || attr_name.compare("MEDIA_ADDED_TIME")==0)
+        {
+            tm date = *initial_value->toDateTm();
+            if(attr_name.compare("MEDIA_DATETAKEN")==0)
+            {
+                char buf[512];
+                strftime(buf, sizeof(buf), "'%Y:%m:%d %H:%M:%S'", &date);
+                initialValueStr = buf;
+            }
+            else
+            {
+                initialValueStr = toDateDbStr(date);
+            }
+        }
+        else
+        {
+            initialValueStr = initial_value->toString();
+        }
+    }
+
+    if (!end_value->isNullOrUndefined())
+    {
+        if(attr_name.compare("MEDIA_DATETAKEN")==0
+                || attr_name.compare("MEDIA_MODIFIED_TIME")==0
+                || attr_name.compare("MEDIA_ADDED_TIME")==0)
+        {
+            tm date = *end_value->toDateTm();
+            if(attr_name.compare("MEDIA_DATETAKEN")==0)
+            {
+                char buf[512];
+                strftime(buf, sizeof(buf), "'%Y:%m:%d %H:%M:%S'", &date);
+                endValueStr = buf;
+            }
+            else
+            {
+                endValueStr = toDateDbStr(date);
+            }
+        }
+        else
+        {
+            endValueStr = end_value->toString();
+        }
+    }
+
+    if (!initial_value->isNullOrUndefined() && end_value->isNullOrUndefined())
+    {
+        str = STR_LEFT_BRACKET + attr_name + STR_GREATER_THAN + STR_EQUAL +
+                STR_S_QUOTATION + initialValueStr + STR_S_QUOTATION + STR_RIGHT_BRACKET;
+    }
+    else if(initial_value->isNullOrUndefined() && !end_value->isNullOrUndefined())
+    {
+        str = STR_LEFT_BRACKET + attr_name + STR_LESS_THAN + STR_S_QUOTATION +
+                endValueStr + STR_S_QUOTATION + STR_RIGHT_BRACKET;
+    }
+    else if (!initial_value->isNullOrUndefined() && !end_value->isNullOrUndefined())
+    {
+        str = STR_LEFT_BRACKET + attr_name + STR_GREATER_THAN + STR_EQUAL + STR_S_QUOTATION +
+                initialValueStr + STR_S_QUOTATION + STR_AND + attr_name + STR_LESS_THAN + STR_S_QUOTATION +
+                endValueStr + STR_S_QUOTATION + STR_RIGHT_BRACKET;
+    }
+
+    m_query.append(str);
+}
+
+
+
+
+
+//TODO: the code below should be refactored:
+
+std::string ContentFilterQueryGenerator::getPlatformAttr(std::string attrName)
+{
+    std::string platformAttr;
+    std::map<std::string, std::string>::iterator pos;
+
+    pos = attrEnumMap.find(attrName);
+
+    if(attrEnumMap.end() != pos)
+    {
+        platformAttr = pos->second;
+    }
+    else
+    {
+        std::string msg = "Attribute(";
+        msg += attrName + ") is not available.";
+        throw Common::UnknownException(msg.c_str());
+    }
+    return platformAttr;
+}
+
+std::string ContentFilterQueryGenerator::toDateDbStr(tm &date) const
+{
+    time_t time;
+    time = mktime(&date);
+    std::stringstream ss;
+    ss << time;
+    return ss.str();
+}
+
+std::string ContentFilterQueryGenerator::convertAttribute(const std::string &attrName, const Tizen::AnyPtr& matchValue, const Tizen::FilterMatchFlag& matchFlag)
+{
+    std::string valueStr;
+    std::string operatorStr;
+    std::string conditionStr;
+
+    condition_e cond;
+    std::string matchValueStr;
+
+    if(attrName.compare("MEDIA_TYPE")==0)
+    {
+        if(matchValue->toString().compare("IMAGE")==0)
+            matchValueStr = "0";
+        else if(matchValue->toString().compare("VIDEO")==0)
+            matchValueStr = "1";
+        else if(matchValue->toString().compare("AUDIO")==0)
+            matchValueStr = "3";
+        else if(matchValue->toString().compare("OTHER")==0)
+            matchValueStr = "4";
+        else
+        {
+            std::string msg = "ContentType(";
+            msg += matchValue->toString();
+            msg += ") is not available.";
+            throw Common::UnknownException(msg.c_str());
+        }
+    }
+    else if(attrName.compare("MEDIA_PATH")==0) {
+        std::string uri = matchValue->toString();
+        if(ContentUtility::isContentUri(uri)) {
+            matchValueStr = ContentUtility::convertUriToPath(uri);
+        } else {
+            matchValueStr = "";
+        }
+    }
+    else if(attrName.compare("MEDIA_THUMBNAIL_PATH")==0)
+    {
+        matchValueStr = ContentUtility::convertUriToPath(matchValue->toString());
+    }
+    else
+    {
+        matchValueStr = matchValue->toString();
+    }
+
+    if(attrName.compare("MEDIA_DATETAKEN")==0
+            || attrName.compare("MEDIA_MODIFIED_TIME")==0
+            || attrName.compare("MEDIA_ADDED_TIME")==0)
+    {
+        tm date = *matchValue->toDateTm();
+        if(attrName.compare("MEDIA_DATETAKEN")==0)
+        {
+            char buf[512];
+            strftime(buf, sizeof(buf), "'%Y:%m:%d %H:%M:%S'", &date);
+            valueStr = buf;
+        }
+        else
+        {
+            valueStr = toDateDbStr(date);
+        }
+        cond = EQUAL;
+    }
+    else if(attrName.compare("MEDIA_FAVORITE") == 0) {
+        valueStr = "0";
+        if (matchValue->toBool()) {
+            cond = GREATER_THAN;
+        }
+        else {
+            cond = EQUAL;
+        }
+    }
+    else
+    {
+        //STARTSWITH('%, ENDSWITH, EXISTS
+        //valueStr = matchValue->getString();
+
+        std::ostringstream os;
+
+        if(matchFlag == STARTSWITH)
+        {
+            cond = LIKE;
+            os << STR_S_QUOTATION << matchValueStr << STR_PERCENT << STR_S_QUOTATION;
+        }
+        else if( matchFlag == ENDSWITH )
+        {
+            cond = LIKE;
+            os << STR_S_QUOTATION <<  STR_PERCENT << matchValueStr << STR_S_QUOTATION;
+        }
+        else if(  matchFlag ==  CONTAINS )
+        {
+            cond = LIKE;
+            os << STR_S_QUOTATION <<  STR_PERCENT << matchValueStr << STR_PERCENT << STR_S_QUOTATION;
+        }
+        else if( matchFlag ==  Tizen::EXISTS )
+        {
+            return STR_LEFT_BRACKET + attrName + operatorKey[EXISTS] + STR_RIGHT_BRACKET;
+        }
+        else
+        {
+            cond = EQUAL;
+            os << STR_S_QUOTATION << matchValueStr << STR_S_QUOTATION;
+        }
+
+        valueStr = os.str();
+    }
+    operatorStr = operatorKey[cond];
+    conditionStr = STR_LEFT_BRACKET + attrName + operatorStr + valueStr + STR_RIGHT_BRACKET;
+
+    return conditionStr;
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/ContentFilterQueryGenerator.h b/src/Content/ContentFilterQueryGenerator.h
new file mode 100644 (file)
index 0000000..d4530ca
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __CONTENT_CONTENT_FILTER_QUERY_GENERATOR_H__
+#define __CONTENT_CONTENT_FILTER_QUERY_GENERATOR_H__
+
+#include <string>
+#include <stack>
+
+#include <media_content.h>
+#include <AbstractFilter.h>
+#include <FilterIterator.h>
+#include <Any.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+class ContentFilterQueryGenerator {
+public:
+    ContentFilterQueryGenerator();
+    ~ContentFilterQueryGenerator();
+
+    void generate(Tizen::AbstractFilterPtr src_filter);
+    std::string getResult() const;
+
+    std::string getPlatformAttr(std::string attr_name);
+
+private:
+    void visitAttribute(Tizen::AttributeFilterPtr attr_filter);
+    void visitAttributeRange(Tizen::AttributeRangeFilterPtr attr_range_filter);
+
+    std::string toDateDbStr(tm &date) const;
+    std::string convertAttribute(const std::string &attr_name, const Tizen::AnyPtr& match_value, const Tizen::FilterMatchFlag& match_flag);
+
+    std::string m_query;
+
+    static std::map<std::string, std::string> attrEnumMap;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif // __CONTENT_CONTENT_FILTER_QUERY_GENERATOR_H__
diff --git a/src/Content/ContentFindCallback.h b/src/Content/ContentFindCallback.h
new file mode 100755 (executable)
index 0000000..e25c037
--- /dev/null
@@ -0,0 +1,144 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_FIND_CALLBACK_H__
+#define __TIZEN_CONTENT_FIND_CALLBACK_H__
+
+#include <string>
+#include <memory>
+
+#include <AbstractFilter.h>
+#include <SortMode.h>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include "JSContent.h"
+#include "JSImageContent.h"
+#include "JSVideoContent.h"
+#include "JSAudioContent.h"
+
+
+
+
+#include "ContentCallback.h"
+#include "Content.h"
+
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Content {
+
+class ContentFindCallback : public ContentCallback
+{
+public:
+    ContentFindCallback(JSContextRef globalCtx ) : ContentCallback(globalCtx){
+        m_count = -1;
+        m_offset =  0;
+    };
+
+    virtual ~ContentFindCallback(){
+        m_contents.clear();
+    };
+
+    void onSuccess(){
+        JSValueRef valueArray[m_contents.size()];
+        for( unsigned int i = 0 ; i < m_contents.size(); i++){
+            if(std::dynamic_pointer_cast<ImageContent>(m_contents[i])){
+                valueArray[i] = JSImageContent::CreateJSObject(m_callback->getContext(), m_contents[i]);
+            }
+            else if(std::dynamic_pointer_cast<VideoContent>(m_contents[i])){
+                valueArray[i] = JSVideoContent::CreateJSObject(m_callback->getContext(), m_contents[i]);
+            }
+            else if(std::dynamic_pointer_cast<AudioContent>(m_contents[i])){
+                valueArray[i] = JSAudioContent::CreateJSObject(m_callback->getContext(), m_contents[i]);
+            }
+            else if(m_contents[i]){
+                valueArray[i] = JSContent::CreateJSObject(m_callback->getContext(), m_contents[i]);
+            }
+        }
+        JSValueRef exception = NULL;
+        JSObjectRef jsResult = JSObjectMakeArray(m_callback->getContext(), m_contents.size(), valueArray, &exception);
+        if (exception != NULL) {
+            throw DeviceAPI::Common::UnknownException(m_callback->getContext(), exception);
+        }
+        m_callback->invokeCallback("onsuccess", jsResult);
+        TIME_TRACER_ITEM_END(CONTENT_TT_FIND_TOTAL, CONTENT_TIME_TRACER_SHOW);
+    };
+
+    std::string getDirectoryId(){
+        return m_directoryId;
+    }
+
+    void setDirectoryId(std::string& directoryId){
+        m_directoryId = directoryId;
+    }
+
+    AbstractFilterPtr& getFilter(){
+        return m_filter;
+    };
+
+    void  setFilter(AbstractFilterPtr& filter){
+        m_filter = filter;
+    };
+
+    SortModePtr& getSortMode(){
+        return m_sortMode;
+    }
+
+    void  setSortMode(SortModePtr& sortMode){
+        m_sortMode = sortMode;
+    }
+
+    unsigned long getCount(){
+        return m_count;
+    }
+
+    void setCount(unsigned long count){
+        m_count = count;
+    }
+
+    unsigned long getOffset(){
+        return m_offset;
+    }
+
+    void setOffset(unsigned long offset){
+        m_offset = offset;
+    }
+
+    ContentLst* getContents(){
+        return &m_contents;
+    };
+
+private:
+    std::string m_directoryId;
+    AbstractFilterPtr m_filter;
+    SortModePtr m_sortMode;
+    unsigned long m_count;
+    unsigned long m_offset;
+
+    ContentLst m_contents;
+};
+
+typedef std::shared_ptr<ContentFindCallback> ContentFindCallbackPtr;
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_CONTENT_FIND_CALLBACK_H__
diff --git a/src/Content/ContentGetDirectoryCallback.h b/src/Content/ContentGetDirectoryCallback.h
new file mode 100755 (executable)
index 0000000..f089146
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_GETDIRECTORY_CALLBACK_H__
+#define __TIZEN_CONTENT_GETDIRECTORY_CALLBACK_H__
+
+#include <string>
+#include <memory>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+
+#include "ContentDirectory.h"
+#include "JSContentDirectory.h"
+#include "ContentCallback.h"
+#include <TimeTracer.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+class ContentGetDirectoryCallback : public ContentCallback
+{
+public:
+    ContentGetDirectoryCallback(JSContextRef globalCtx):ContentCallback(globalCtx){};
+
+    virtual ~ContentGetDirectoryCallback(){
+//        for(unsigned int i = 0; i < m_directroies.size(); i++){
+//            delete m_directroies[i];
+//        }
+        m_directroies.clear();
+    };
+
+    void onSuccess(){
+        JSValueRef valueArray[m_directroies.size()];
+        for( unsigned int i = 0 ; i < m_directroies.size(); i++){
+            valueArray[i] = JSContentDirectory::CreateJSObject(m_callback->getContext(),m_directroies[i]);
+        }
+        JSValueRef exception = NULL;
+        JSObjectRef jsResult = JSObjectMakeArray(m_callback->getContext(), m_directroies.size(), valueArray, &exception);
+        if (exception != NULL) {
+            throw DeviceAPI::Common::UnknownException(m_callback->getContext(), exception);
+        }
+        m_callback->invokeCallback("onsuccess", jsResult);
+        TIME_TRACER_ITEM_END(CONTENT_TT_GET_DIR_TOTAL, CONTENT_TIME_TRACER_SHOW);
+    };
+
+    DirectoryLst* getDirectories(){
+        return &m_directroies;
+    };
+private:
+    DirectoryLst m_directroies;
+};
+
+
+typedef std::shared_ptr<ContentGetDirectoryCallback> ContentGetDirectoryCallbackPtr;
+
+} // Content
+} // DeviceAPI
+
+
+
+#endif // __TIZEN_CONTENT_GETDIRECTORY_CALLBACK_H__
diff --git a/src/Content/ContentHelper.cpp b/src/Content/ContentHelper.cpp
new file mode 100755 (executable)
index 0000000..b28da34
--- /dev/null
@@ -0,0 +1,1550 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <glib.h>
+#include <list>
+
+#include <Export.h>
+#include <Logger.h>
+#include <JSWebAPIError.h>
+#include <Commons/StringUtils.h>
+#include <GlobalContextManager.h>
+
+#include "ContentUtility.h"
+#include "ContentHelper.h"
+
+#include "ContentGetDirectoryCallback.h"
+#include "ContentScanFileCallback.h"
+#include "ContentFindCallback.h"
+#include "ContentFilterQueryGenerator.h"
+#include "ContentUpdateBatchCallback.h"
+#include "ContentChangeCallback.h"
+#include <TimeTracer.h>
+
+
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Content {
+
+#define TAG_DELIMETER '/'
+#define UNDEFINED_GEO -200.0
+
+ContentHelper::ContentHelper()
+{
+}
+
+ContentHelper::~ContentHelper()
+{
+}
+
+bool ContentHelper::Connect()
+{
+    bool ret = false;
+    int err = media_content_connect();
+    if( MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        LOGI("Content DB is connected.");
+        ret =  true;
+    }
+    else {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_content_connect()").c_str());
+    }
+    return ret;
+
+}
+bool ContentHelper::DisConnect()
+{
+    bool ret = false;
+    int err = media_content_disconnect();
+    if ( MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        LOGI("Content DB is disconnected.");
+        ret =  true;
+    } else {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_content_disconnect()").c_str());
+    }
+    return ret;
+
+}
+
+int ContentHelper::getCallbackCompleted(void *data)
+{
+    ContentCallbackPtr callbackPtr(static_cast<ContentCallback*>(data));
+    try
+    {
+        callbackPtr->onSuccess();
+    }
+    catch(...)
+    {
+        callbackPtr->onError("This operation is failed by platform.");
+    }
+
+    LOGI("getCallbackCompleted");
+    return false;
+}
+
+int ContentHelper::getCallbackCanceled(void *data)
+{
+    ContentCallbackPtr callbackPtr(static_cast<ContentCallback*>(data));
+
+    callbackPtr->onError();
+    return false;
+}
+
+gboolean ContentHelper::getDirectoryWork(void* data)
+{
+    ContentGetDirectoryCallback* callback = static_cast<ContentGetDirectoryCallback*>(data);
+    DirectoryLst *directories = callback->getDirectories();
+
+    filter_h filter = NULL;
+    TIME_TRACER_ITEM_BEGIN("getDirectoriesPlatform", 1);
+    int err = media_filter_create(&filter);
+    if ( MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        std::string condition="(FOLDER_STORAGE_TYPE = 0 OR FOLDER_STORAGE_TYPE = 1)";
+        //set condition
+        err = media_filter_set_condition(filter, condition.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
+        if ( MEDIA_CONTENT_ERROR_NONE != err)
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "media_filter_set_condition()").c_str());
+        }
+
+        err = media_folder_foreach_folder_from_db(filter, ContentHelper::getDirectoryCallback, directories);
+        if( MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            TIME_TRACER_ITEM_END("getDirectoriesPlatform", 1);
+            if (G_IDLE_FAILED == g_idle_add(ContentHelper::getCallbackCompleted, callback)) {
+                delete callback;
+                callback = NULL;
+                LOGE("g_idle addition failed");
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "media_folder_foreach_folder_from_db()").c_str());
+
+            callback->setErrMsg("getDirectoryWork() is failed");
+            if (G_IDLE_FAILED == g_idle_add(ContentHelper::getCallbackCanceled, callback)) {
+                delete callback;
+                callback = NULL;
+                LOGE("g_idle addition failed");
+            }
+        }
+
+        err = media_filter_destroy(filter);
+        if ( MEDIA_CONTENT_ERROR_NONE != err)
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "media_filter_destroy()").c_str());
+        }
+    }
+    else
+    {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_filter_create()").c_str());
+    }
+    return false;
+}
+
+
+bool ContentHelper::getDirectoryCallback(media_folder_h folder, void *user_data)
+{
+    int err;
+    if (user_data != NULL) {
+        if (folder != NULL) {
+            char *str = NULL;
+            ContentDirectoryPtr dirPtr = ContentDirectoryPtr(new ContentDirectory());
+
+            err = media_folder_get_folder_id(folder, &str);
+            if (MEDIA_CONTENT_ERROR_NONE == err) {
+                if (str) {
+                    dirPtr->setId(str);
+                    free(str);
+                    str = NULL;
+                }
+            }
+            else
+            {
+                LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                        err, "media_folder_get_folder_id()").c_str());
+            }
+
+            err = media_folder_get_path(folder, &str);
+            if (MEDIA_CONTENT_ERROR_NONE == err) {
+                if (str) {
+                    dirPtr->setDirectoryURI(str);
+                    free(str);
+                    str = NULL;
+                }
+            }
+            else
+            {
+                LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                        err, "media_folder_get_path()").c_str());
+            }
+
+            err = media_folder_get_name(folder, &str);
+            if (MEDIA_CONTENT_ERROR_NONE == err) {
+                if (str) {
+                    dirPtr->setTitle(str);
+                    free(str);
+                    str = NULL;
+                }
+            }
+            else
+            {
+                LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                        err, "media_folder_get_name()").c_str());
+            }
+
+            {
+                time_t date;
+                err = media_folder_get_modified_time(folder, &date);
+                if (MEDIA_CONTENT_ERROR_NONE == err) {
+                    dirPtr->setModifiedDate(date);
+                }
+                else
+                {
+                    LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                            err, "media_folder_get_modified_time()").c_str());
+                }
+            }
+            {
+                media_content_storage_e storageType;
+                err = media_folder_get_storage_type(folder, &storageType);
+                if (MEDIA_CONTENT_ERROR_NONE == err) {
+                    if (storageType == MEDIA_CONTENT_STORAGE_INTERNAL) {
+                        dirPtr->setStorageType("INTERNAL");
+                    }
+                    else if (storageType == MEDIA_CONTENT_STORAGE_EXTERNAL) {
+                        dirPtr->setStorageType("EXTERNAL");
+                    }
+                }
+                else
+                {
+                    LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                            err, "media_folder_get_storage_type()").c_str());
+                }
+            }
+
+            if (DirectoryLst* directories = static_cast<DirectoryLst*>(user_data)) {
+                directories->push_back(dirPtr);
+            }
+            else {
+                LOGE("User data is invalid.");
+            }
+        }
+        else {
+            LOGE("Get Directories Iterator is failed.");
+            //return false;
+        }
+    }
+    else {
+        LOGD("user data is NULL");
+        //return false;
+    }
+    return true;
+}
+
+
+gboolean ContentHelper::scanFileWork(void* data)
+{
+    LOGD("Entered");
+    ContentScanFileCallback* callback = static_cast<ContentScanFileCallback*>(data);
+    std::string uri = callback->getContentURI();
+
+    TIME_TRACER_ITEM_BEGIN("scanFilePlatform", 1);
+
+    int err = media_content_scan_file(uri.c_str());
+    if( MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        TIME_TRACER_ITEM_END("scanFilePlatform", 1);
+        if (G_IDLE_FAILED == g_idle_add(ContentHelper::getCallbackCompleted, callback)) {
+            delete callback;
+            callback = NULL;
+            LOGE("g_idle addition failed");
+        }
+    }
+    else
+    {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_content_scan_file()").c_str());
+        callback->setErrMsg("scanFile operation is failed.");
+        if (G_IDLE_FAILED == g_idle_add(ContentHelper::getCallbackCanceled, callback)) {
+            delete callback;
+            callback = NULL;
+            LOGE("g_idle addition failed");
+        }
+    }
+    return false;
+}
+
+gboolean ContentHelper::findWork(void* data)
+{
+    ContentFindCallback* callback = static_cast<ContentFindCallback*>(data);
+    ContentLst *contents = callback->getContents();
+
+    TIME_TRACER_ITEM_BEGIN("findPlatform", 1);
+    int err;
+    try
+    {
+
+        filter_h filter = NULL;
+        err = media_filter_create(&filter);
+        if ( MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            std::shared_ptr<ContentFilterQueryGenerator> query(new ContentFilterQueryGenerator());
+            std::string condition;
+            AbstractFilterPtr& jsfilter = callback->getFilter();
+
+            if(jsfilter)
+            {
+                query->generate(jsfilter);
+                condition = query->getResult();
+                err = media_filter_set_condition(
+                        filter, condition.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
+                if (MEDIA_CONTENT_ERROR_NONE != err)
+                {
+                    LOGE("ret: %d", err);
+                    ContentUtility::throwMediaContentException<Common::UnknownException>(
+                            err, "media_filter_set_condition()");
+                }
+            }
+
+            SortModePtr& jssortMode = callback->getSortMode();
+            if(jssortMode)
+            {
+                media_content_order_e order = MEDIA_CONTENT_ORDER_ASC;
+                std::string attrName = query->getPlatformAttr(jssortMode->getAttributeName());
+                if(jssortMode->getOrder() == Tizen::ASC)
+                {
+                    order = MEDIA_CONTENT_ORDER_ASC;
+                }
+                else if(jssortMode->getOrder() == Tizen::DESC)
+                {
+                    order = MEDIA_CONTENT_ORDER_DESC;
+                }
+                else
+                {
+                    throw Common::UnknownException("SortMode is invalid value.");
+                }
+
+                err = media_filter_set_order(
+                        filter, order, attrName.c_str(), MEDIA_CONTENT_COLLATE_DEFAULT);
+                if (MEDIA_CONTENT_ERROR_NONE != err)
+                {
+                    LOGE("ret: %d", err);
+                    ContentUtility::throwMediaContentException<Common::UnknownException>(
+                            err, "media_filter_set_order()");
+                }
+            }
+
+            int count = callback->getCount();
+            int offset = callback->getOffset();
+
+            err = media_filter_set_offset(filter, offset, count);
+            if ( MEDIA_CONTENT_ERROR_NONE != err)
+            {
+                LOGE("ret: %d", err);
+                ContentUtility::throwMediaContentException<Common::UnknownException>(
+                        err, "media_filter_set_offset()");
+            }
+
+            if(callback->getDirectoryId().empty())
+            {
+                err = media_info_foreach_media_from_db(filter,findCallback, contents);
+                if( MEDIA_CONTENT_ERROR_NONE != err)
+                {
+                    LOGE("ret: %d", err);
+                    ContentUtility::throwMediaContentException<Common::UnknownException>(
+                            err, "media_info_foreach_media_from_db()");
+                }
+            }
+            else
+            {
+                err = media_folder_foreach_media_from_db(
+                        callback->getDirectoryId().c_str(),
+                        filter,
+                        findCallback,
+                        contents);
+                if( MEDIA_CONTENT_ERROR_NONE != err)
+                {
+                    LOGE("ret: %d", err);
+                    ContentUtility::throwMediaContentException<Common::UnknownException>(
+                            err, "media_folder_foreach_media_from_db()");
+                }
+            }
+            TIME_TRACER_ITEM_END("findPlatform", 1);
+            if (G_IDLE_FAILED == g_idle_add(ContentHelper::getCallbackCompleted, callback)) {
+                delete callback;
+                callback = NULL;
+                LOGE("g_idle addition failed");
+            }
+        }
+        else
+        {
+            LOGE("ret: %d", err);
+            ContentUtility::throwMediaContentException<Common::UnknownException>(
+                    err, "media_filter_create()");
+        }
+
+        int ret = media_filter_destroy(filter);
+        if ( MEDIA_CONTENT_ERROR_NONE != ret){
+            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                    ret, "media_filter_destroy()").c_str());
+        }
+    }
+    catch (const BasePlatformException &err) {
+        callback->setErrMsg(err.getMessage().c_str());
+        if (G_IDLE_FAILED == g_idle_add(ContentHelper::getCallbackCanceled, callback)) {
+            delete callback;
+            callback = NULL;
+            LOGE("g_idle addition failed");
+        }
+    }
+
+    return false;
+}
+
+bool ContentHelper::findCallback(media_info_h info, void *user_data)
+{
+    int err;
+    if (user_data != NULL) {
+        if (info != NULL) {
+            ContentLst* contents = static_cast<ContentLst*>(user_data);
+
+            media_content_type_e type;
+
+            err = media_info_get_media_type(info, &type);
+            if (MEDIA_CONTENT_ERROR_NONE
+                    == err) {
+                if (type == MEDIA_CONTENT_TYPE_IMAGE) {
+                    ImageContentPtr image = ImageContentPtr(new ImageContent());
+                    ContentHelper::loadImageContentFromPlatform(info, image);
+                    contents->push_back(image);
+                }
+                else if (type == MEDIA_CONTENT_TYPE_VIDEO) {
+                    VideoContentPtr video = VideoContentPtr(new VideoContent());
+                    ContentHelper::loadVideoContentFromPlatform(info, video);
+                    contents->push_back(video);
+                }
+                else if (type == MEDIA_CONTENT_TYPE_MUSIC) {
+                    AudioContentPtr audio = AudioContentPtr(new AudioContent());
+                    ContentHelper::loadAudioContentFromPlatform(info, audio);
+                    contents->push_back(audio);
+                }
+                else if (type == MEDIA_CONTENT_TYPE_OTHERS) {
+                    ContentPtr content = ContentPtr(new Content());
+                    ContentHelper::loadContentFromPlatform(info, content);
+                    contents->push_back(content);
+                }
+            }
+            else
+            {
+                LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                        err, "media_info_get_media_type()").c_str());
+            }
+        }
+        else {
+            LOGE("content handle is not valid.");
+            //return false;
+        }
+    }
+    else {
+        LOGD("user data is NULL");
+        //return false;
+    }
+    return true;
+}
+
+bool ContentHelper::update(ContentPtr content)
+{
+    bool ret = false;
+    TIME_TRACER_ITEM_BEGIN("updatePlatform", 1);
+    ret = updateContentToPlatform(content);
+    TIME_TRACER_ITEM_END("updatePlatform", 1);
+
+    return ret;
+}
+
+gboolean ContentHelper::updateBatchWork(void* data)
+{
+    ContentUpdateBatchCallback* callback = static_cast<ContentUpdateBatchCallback*>(data);
+    ContentLst *contents = callback->getContents();
+
+    TIME_TRACER_ITEM_BEGIN("updateBatchPlatform", 1);
+
+    if(!(contents->empty()))
+    {
+        for(unsigned int i = 0 ; i < contents->size(); i++)
+        {
+            updateContentToPlatform(contents->at(i));
+        }
+        TIME_TRACER_ITEM_END("updateBatchPlatform", 1);
+        if (G_IDLE_FAILED == g_idle_add(ContentHelper::getCallbackCompleted, callback)) {
+            delete callback;
+            callback = NULL;
+            LOGE("g_idle addition failed");
+        }
+    }
+    else
+    {
+        callback->setErrMsg("The Private object is null.");
+
+        if (G_IDLE_FAILED == g_idle_add(ContentHelper::getCallbackCanceled, callback)) {
+            delete callback;
+            callback = NULL;
+            LOGE("g_idle addition failed");
+        }
+    }
+
+    return false;
+}
+
+bool ContentHelper::updateContentToPlatform(ContentPtr content)
+{
+
+    bool ret = true;
+    int err;
+
+    std::string id = content->getId();
+    if(!id.empty())
+    {
+        media_info_h info = NULL;
+        err = media_info_get_media_from_db(id.c_str(), &info);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            err = media_info_set_rating(info, content->getRating());
+            if(MEDIA_CONTENT_ERROR_NONE != err)
+            {
+                LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                        err, "media_info_set_rating()").c_str());
+            }
+
+            err = media_info_set_description (info, content->getDescription().c_str());
+            if(MEDIA_CONTENT_ERROR_NONE != err)
+            {
+                LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                        err, "media_info_set_description()").c_str());
+            }
+
+            err = media_info_set_display_name (info, content->getName().c_str());
+            if(MEDIA_CONTENT_ERROR_NONE != err)
+            {
+                LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                        err, "media_info_set_display_name()").c_str());
+            }
+
+            err = media_info_set_favorite (info, content->getIsFavorite());
+            if(MEDIA_CONTENT_ERROR_NONE != err)
+            {
+                LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                        err, "media_info_set_favorite()").c_str());
+            }
+
+            if(content->getType().compare("IMAGE") == 0)
+            {
+                image_meta_h img=NULL;
+                ImageContentPtr imagePtr = std::dynamic_pointer_cast<ImageContent>(content);
+                if(imagePtr)
+                {
+                    err = media_info_get_image(info, &img);
+                    if(MEDIA_CONTENT_ERROR_NONE == err)
+                    {
+                        err = image_meta_set_orientation(img, imagePtr->getOrientationEnum());
+                        if(MEDIA_CONTENT_ERROR_NONE != err)
+                        {
+                            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                    err, "image_meta_set_orientation()").c_str());
+                        }
+
+                        double latitude = UNDEFINED_GEO;
+                        double longitude = UNDEFINED_GEO;
+                        if (imagePtr->isGeolocationSet()) {
+                            latitude = imagePtr->getLatitude();
+                            longitude = imagePtr->getLongitude();
+                        }
+
+                        err = media_info_set_latitude(info, latitude);
+                        if(MEDIA_CONTENT_ERROR_NONE != err)
+                        {
+                            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                    err, "media_info_set_latitude()").c_str());
+                        }
+
+                        err = media_info_set_longitude(info, longitude);
+                        if(MEDIA_CONTENT_ERROR_NONE != err)
+                        {
+                            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                    err, "media_info_set_longitude()").c_str());
+                        }
+
+                        err = image_meta_update_to_db(img);
+                        if(MEDIA_CONTENT_ERROR_NONE != err)
+                        {
+                            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                    err, "image_meta_update_to_db()").c_str());
+                            ret = false;
+                        }
+
+                        err = image_meta_destroy(img);
+                        if ( MEDIA_CONTENT_ERROR_NONE != err)
+                        {
+                            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                    err, "image_meta_destroy()").c_str());
+                        }
+                    }
+                    else
+                    {
+                        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                err, "media_info_get_image()").c_str());
+                    }
+                }
+            }
+            if(content->getType().compare("VIDEO") == 0)
+            {
+                video_meta_h video = NULL;
+                VideoContentPtr videoPtr = std::dynamic_pointer_cast<VideoContent>(content);
+                if(videoPtr)
+                {
+                    err = media_info_get_video(info, &video);
+                    if ( MEDIA_CONTENT_ERROR_NONE == err)
+                    {
+                        double latitude = UNDEFINED_GEO;
+                        double longitude = UNDEFINED_GEO;
+                        if (videoPtr->isGeolocationSet()) {
+                            latitude = videoPtr->getLatitude();
+                            longitude = videoPtr->getLongitude();
+                        }
+
+                        err = media_info_set_latitude(info, latitude);
+                        if(MEDIA_CONTENT_ERROR_NONE != err)
+                        {
+                            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                    err, "media_info_set_latitude()").c_str());
+                        }
+
+                        err = media_info_set_longitude(info, longitude);
+                        if(MEDIA_CONTENT_ERROR_NONE != err)
+                        {
+                            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                    err, "media_info_set_longitude()").c_str());
+                        }
+
+                        err = video_meta_update_to_db(video);
+                        if(MEDIA_CONTENT_ERROR_NONE != err)
+                        {
+                            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                    err, "video_meta_update_to_db()").c_str());
+                            ret = false;
+                        }
+
+                        err = video_meta_destroy(video);
+                        if(MEDIA_CONTENT_ERROR_NONE != err)
+                        {
+                            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                                    err, "video_meta_destroy()").c_str());
+                        }
+                    }
+                    else
+                    {
+                        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                                err, "media_info_get_video()").c_str());
+                    }
+                }
+            }
+
+            err = media_info_update_to_db(info);
+            if(MEDIA_CONTENT_ERROR_NONE != err)
+            {
+                LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                        err, "media_info_update_to_db()").c_str());
+                ret = false;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "media_info_get_media_from_db()").c_str());
+        }
+        int error = media_info_destroy(info);
+        if (error != MEDIA_CONTENT_ERROR_NONE) {
+            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                    error, "media_info_destroy()").c_str());
+        }
+    }
+
+    return ret;
+}
+
+
+
+void ContentHelper::changeCallbackWork(
+        media_content_error_e error,
+        int pid,
+        media_content_db_update_item_type_e update_item,
+        media_content_db_update_type_e update_type,
+        media_content_type_e media_type,
+        char *uuid,
+        char *path,
+        char *mime_type,
+        void *user_data)
+{
+    ContentChangeCallbackPtrList listener = *(ContentChangeCallbackPtrList*)user_data;
+    std::string err_msg;
+    int err;
+    if( error == MEDIA_CONTENT_ERROR_NONE)
+    {
+
+        err_msg = "";
+        if( update_item == MEDIA_ITEM_FILE)
+        {
+            std::string condition = "MEDIA_ID=\"";
+            condition += uuid;
+            condition += "\"";
+
+            ContentPtr content;
+            if(update_type == MEDIA_CONTENT_INSERT ||
+                    update_type == MEDIA_CONTENT_UPDATE) {
+
+                filter_h filter = NULL;
+                err = media_filter_create(&filter);
+                if (MEDIA_CONTENT_ERROR_NONE == err) {
+
+                    err = media_filter_set_condition(filter, condition.c_str(),
+                            MEDIA_CONTENT_COLLATE_DEFAULT);
+                    if ( MEDIA_CONTENT_ERROR_NONE != err)
+                    {
+                        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                                err, "media_filter_set_condition()").c_str());
+                    }
+
+                    if(media_type == MEDIA_CONTENT_TYPE_IMAGE) {
+                        content = ContentPtr(new ImageContent());
+                    }
+                    else if(media_type == MEDIA_CONTENT_TYPE_VIDEO) {
+                        content = ContentPtr(new VideoContent());
+                    }
+                    else if(media_type == MEDIA_CONTENT_TYPE_SOUND ||
+                            media_type == MEDIA_CONTENT_TYPE_MUSIC) {
+                        content = ContentPtr(new AudioContent());
+                    }
+                    else {
+                        content = ContentPtr(new Content());
+                    }
+
+                    ContentHolder* content_ptr_holder = new ContentHolder();
+                    content_ptr_holder->ptr = content;
+
+                    err = media_info_foreach_media_from_db(
+                            filter, loadContent, (void*)content_ptr_holder);
+                    if( MEDIA_CONTENT_ERROR_NONE == err) {
+
+                        content->setContentURI(ContentUtility::convertPathToUri(content->getContentURI()));
+                        ContentChangeCallbackPtrList::iterator itr = listener.begin();
+                        while( itr != listener.end() ) {
+                            ContentChangeCallbackPtr callback = *itr;
+                            if(callback) {
+                                if(!GlobalContextManager::getInstance()->isAliveGlobalContext(
+                                        callback->getContext())) {
+                                    LOGW("context was closed, so skip");
+                                    ++itr;
+                                    continue;
+                                }
+
+                                if(update_type == MEDIA_CONTENT_INSERT) {
+                                    callback->oncontentadded(content);
+                                }
+                                else {
+                                    callback->oncontentupdated(content);
+                                }
+                            }
+                            ++itr;
+                        }
+                    }
+                    else {
+                        delete content_ptr_holder;
+                        content_ptr_holder = NULL;
+
+                        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                                err, "media_info_foreach_media_from_db()").c_str());
+
+                    }
+                    err = media_filter_destroy(filter);
+                    if (MEDIA_CONTENT_ERROR_NONE != err) {
+                        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                                err, "media_filter_destroy()").c_str());
+                    }
+                }
+                else
+                {
+                    LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                            err, "media_filter_create()").c_str());
+                }
+            }
+            else if(update_type == MEDIA_CONTENT_DELETE)
+            {
+                ContentChangeCallbackPtrList::iterator itr = listener.begin();
+                while( itr != listener.end() ) {
+                    ContentChangeCallbackPtr callback = *itr;
+                    if(callback) {
+                        if(!GlobalContextManager::getInstance()->isAliveGlobalContext(
+                                callback->getContext())) {
+                            LOGW("context was closed, so skip");
+                            ++itr;
+                            continue;
+                        }
+
+                        callback->oncontentremoved(uuid);
+                    }
+                    ++itr;
+                }
+            }
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                error, "media_content_set_db_updated_cb()").c_str());
+    }
+
+}
+
+
+
+int ContentHelper::get_utc_offset()
+{
+    time_t zero = 24*60*60L;
+    struct tm * timeptr;
+    int gmtime_hours;
+
+    /* get the local time for Jan 2, 1900 00:00 UTC */
+    timeptr = localtime( &zero );
+    gmtime_hours = timeptr->tm_hour;
+
+    /* if the local time is the "day before" the UTC, subtract 24 hours
+    from the hours to get the UTC offset */
+    if( timeptr->tm_mday < 2 )
+        gmtime_hours -= 24;
+
+    return gmtime_hours;
+
+}
+
+bool ContentHelper::loadContent(media_info_h info, void* user_data)
+{
+    ContentHolder* hold = static_cast<ContentHolder*>(user_data);
+    media_content_type_e type;
+
+    int err;
+    err = media_info_get_media_type(info, &type);
+    if ( MEDIA_CONTENT_ERROR_NONE == err) {
+        if ( type == MEDIA_CONTENT_TYPE_IMAGE) {
+            loadImageContentFromPlatform(info,
+                    std::dynamic_pointer_cast<ImageContent>(hold->ptr));
+        }
+        else if ( type == MEDIA_CONTENT_TYPE_VIDEO) {
+            loadVideoContentFromPlatform(info,
+                    std::dynamic_pointer_cast<VideoContent>(hold->ptr));
+        }
+        else if ( type == MEDIA_CONTENT_TYPE_MUSIC || type == MEDIA_CONTENT_TYPE_SOUND) {
+            loadAudioContentFromPlatform(info,
+                    std::dynamic_pointer_cast<AudioContent>(hold->ptr));
+        }
+        else if( type == MEDIA_CONTENT_TYPE_OTHERS) {
+            loadContentFromPlatform(info, hold->ptr);
+        }
+    }
+    else
+    {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_media_type()").c_str());
+    }
+
+    delete hold;
+    hold = NULL;
+    return false;
+}
+
+void ContentHelper::loadContentFromPlatform(media_info_h info, ContentPtr content)
+{
+    if(!content)
+    {
+        LOGE("Content creation is failed.");
+        return;
+    }
+
+    if(info == NULL)
+    {
+        LOGE("find operation is failed.");
+        return;
+    }
+
+    char* tmpStr = NULL;
+    int tmpInt = 0;
+    unsigned long long tmplong = 0;
+    bool tmpBool = false;
+
+    time_t tmpDate;
+
+
+    int err = media_info_get_media_id(info, &tmpStr);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        if(tmpStr)
+        {
+            content->setId(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_media_id()").c_str());
+    }
+
+    err = media_info_get_mime_type(info, &tmpStr);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        if(tmpStr)
+        {
+            content->setMimeType(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_mime_type()").c_str());
+    }
+
+    err = media_info_get_display_name(info, &tmpStr);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        if(tmpStr)
+        {
+            content->setName(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_display_name()").c_str());
+    }
+
+    err = media_info_get_title(info, &tmpStr);
+    if (MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        if (tmpStr)
+        {
+            content->setTitle(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_title()").c_str());
+    }
+
+    err = media_info_get_file_path(info, &tmpStr);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        if(tmpStr)
+        {
+            content->setContentURI(ContentUtility::convertPathToUri(tmpStr));
+            free(tmpStr);
+            tmpStr = NULL;
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_file_path()").c_str());
+    }
+
+    err = media_info_get_thumbnail_path (info, &tmpStr);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        if(tmpStr)
+        {
+            std::vector<std::string> thumbnailURIs;
+            thumbnailURIs.push_back(ContentUtility::convertPathToUri(tmpStr));
+            content->setThumbnailURIs(thumbnailURIs);
+            free(tmpStr);
+            tmpStr = NULL;
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_thumbnail_path()").c_str());
+    }
+
+    err = media_info_get_description(info, &tmpStr);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        if(tmpStr)
+        {
+            content->setDescription(tmpStr);
+            free(tmpStr);
+            tmpStr = NULL;
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_description()").c_str());
+    }
+
+    err = media_info_get_modified_time(info, &tmpDate);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        if(tmpDate)
+        {
+            content->setModifiedDate(tmpDate);
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_modified_time()").c_str());
+    }
+
+    err = media_info_get_rating(info, &tmpInt);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        content->setRating(tmpInt);
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_rating()").c_str());
+    }
+
+    err = media_info_get_favorite(info, &tmpBool);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        content->setIsFavorite(tmpBool);
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_favorite()").c_str());
+    }
+
+    err = media_info_get_size(info, &tmplong);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        content->setSize(tmplong);
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_size()").c_str());
+    }
+}
+
+ImageContentPtr ContentHelper::loadImageContentFromPlatform(media_info_h info,
+        ImageContentPtr image)
+{
+
+    if(!image)
+    {
+        LOGE("Image Content creation is failed.");
+        return ImageContentPtr();
+    }
+
+    if(info == NULL)
+    {
+        LOGE("find operation is failed.");
+        return ImageContentPtr();
+    }
+
+    char* tmpStr = NULL;
+    int tmpInt = 0;
+    double tmpDouble;
+
+    image_meta_h img;
+
+    ContentHelper::loadContentFromPlatform(info, image);
+
+    int err = media_info_get_image(info, &img);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        //created time
+        err = image_meta_get_date_taken(img, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr )
+            {
+                struct tm *result = (struct tm *)calloc(1, sizeof(struct tm));
+                if(strptime(tmpStr, "%Y:%m:%d %H:%M:%S", result) == NULL)
+                {
+                    LOGE( "Couldn't convert supplied date.");
+                }
+
+                time_t t = mktime( result );// + get_utc_offset() * 3600;
+                image->setReleaseDate(t);
+                free(tmpStr);
+                free(result);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "image_meta_get_date_taken()").c_str());
+        }
+
+        err = image_meta_get_width(img, &tmpInt);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            image->setWidth(tmpInt);
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "image_meta_get_width()").c_str());
+        }
+
+        err = image_meta_get_height(img, &tmpInt);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            image->setHeight(tmpInt);
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "image_meta_get_height()").c_str());
+        }
+
+        err = media_info_get_latitude(info, &tmpDouble);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            LOGD("Latitude: %f", tmpDouble);
+            if (UNDEFINED_GEO != tmpDouble) {
+                image->setLatitude(tmpDouble);
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "media_info_get_latitude()").c_str());
+        }
+
+        err = media_info_get_longitude(info, &tmpDouble);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            LOGD("Longitude: %f", tmpDouble);
+            if (UNDEFINED_GEO != tmpDouble) {
+                image->setLongitude(tmpDouble);
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "media_info_get_longitude()").c_str());
+        }
+
+        media_content_orientation_e orientation;
+        err = image_meta_get_orientation(img, &orientation);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            image->setOrientation(orientation);
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "image_meta_get_orientation()").c_str());
+        }
+
+        err = image_meta_destroy(img);
+        if(MEDIA_CONTENT_ERROR_NONE != err)
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "image_meta_destroy()").c_str());
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_image()").c_str());
+    }
+    return image;
+}
+
+VideoContentPtr ContentHelper::loadVideoContentFromPlatform(media_info_h info,
+        VideoContentPtr videoPtr)
+{
+
+    if(!videoPtr)
+    {
+        LOGE("Video Content creation is failed.");
+        return VideoContentPtr();
+    }
+
+    if(info == NULL)
+    {
+        LOGE("find operation is failed.");
+        return VideoContentPtr();
+    }
+
+    char* tmpStr;
+    int tmpInt = 0;
+    double tmpDouble;
+
+    video_meta_h video;
+
+    ContentHelper::loadContentFromPlatform(info, videoPtr);
+
+    int err = media_info_get_video(info, &video);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        err = video_meta_get_recorded_date(video, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                struct tm *result=(struct tm *)calloc(1, sizeof(struct tm));
+                if (strptime(tmpStr, "%Y:%m:%d %H:%M:%S", result) == NULL) {
+                    LOGE( "Couldn't convert supplied date.");
+                }
+                time_t t = mktime( result ) + get_utc_offset() * 3600;
+                videoPtr->setReleaseDate(t);
+                free(tmpStr);
+                free(result);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "video_meta_get_recorded_date()").c_str());
+        }
+
+        err = video_meta_get_album(video, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                videoPtr->setAlbum(tmpStr);
+                free(tmpStr);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "video_meta_get_album()").c_str());
+        }
+
+        err = video_meta_get_artist(video, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                std::vector<std::string> artists = WrtDeviceApis::Commons::String::split(tmpStr, TAG_DELIMETER);
+                videoPtr->setArtists(artists);
+                free(tmpStr);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "video_meta_get_artist()").c_str());
+        }
+
+        err = media_info_get_latitude(info, &tmpDouble);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            LOGD("Latitude: %f", tmpDouble);
+            if (UNDEFINED_GEO != tmpDouble) {
+                videoPtr->setLatitude(tmpDouble);
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "media_info_get_latitude()").c_str());
+        }
+
+        err = media_info_get_longitude(info, &tmpDouble);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            LOGD("Longitude: %f", tmpDouble);
+            if (UNDEFINED_GEO != tmpDouble) {
+                videoPtr->setLongitude(tmpDouble);
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "media_info_get_longitude()").c_str());
+        }
+
+        err = video_meta_get_width(video, &tmpInt);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            videoPtr->setWidth(tmpInt);
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "video_meta_get_width()").c_str());
+        }
+
+        err = video_meta_get_height(video, &tmpInt);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            videoPtr->setHeight(tmpInt);
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "video_meta_get_height()").c_str());
+        }
+
+        err = video_meta_get_duration(video, &tmpInt);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            videoPtr->setDuration(tmpInt);
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "video_meta_get_duration()").c_str());
+        }
+
+        err = video_meta_destroy(video);
+        if(MEDIA_CONTENT_ERROR_NONE != err)
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "video_meta_destroy()").c_str());
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_video()").c_str());
+    }
+
+    return videoPtr;
+}
+
+AudioContentPtr ContentHelper::loadAudioContentFromPlatform(media_info_h info,
+        AudioContentPtr audioPtr)
+{
+    if(!audioPtr)
+    {
+        LOGE("Video Content creation is failed.");
+        return AudioContentPtr();
+    }
+
+    if(info == NULL)
+    {
+        LOGE("find operation is failed.");
+        return AudioContentPtr();
+    }
+
+    audio_meta_h audio;
+
+    char* tmpStr;
+    int tmpInt = 0;
+
+    ContentHelper::loadContentFromPlatform(info, audioPtr);
+
+    int err = media_info_get_audio(info, &audio);
+    if(MEDIA_CONTENT_ERROR_NONE == err)
+    {
+        err = audio_meta_get_recorded_date(audio, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                struct tm *result = (struct tm *)calloc(1, sizeof(struct tm));
+                if (strptime(tmpStr, "%Y:%m:%d %H:%M:%S", result) == NULL)
+                {
+                    LOGE( "Couldn't convert supplied date.");
+                }
+                time_t t = mktime( result ) + get_utc_offset() * 3600;
+                audioPtr->setReleaseDate(t);
+                free(tmpStr);
+                free(result);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_get_recorded_date()").c_str());
+        }
+
+        err = audio_meta_get_album(audio, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                audioPtr->setAlbum(tmpStr);
+                free(tmpStr);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_get_album()").c_str());
+        }
+
+        err = audio_meta_get_artist(audio, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                std::vector<std::string> artists = String::split(tmpStr, TAG_DELIMETER);
+                audioPtr->setArtists(artists);
+                free(tmpStr);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_get_artist()").c_str());
+        }
+
+        err = audio_meta_get_composer(audio, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                std::vector<std::string> composers = String::split(tmpStr, TAG_DELIMETER);
+                audioPtr->setComposers(composers);
+                free(tmpStr);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_get_composer()").c_str());
+        }
+
+        err = audio_meta_get_duration(audio, &tmpInt);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            audioPtr->setDuration(tmpInt);
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_get_duration()").c_str());
+        }
+
+        err = audio_meta_get_copyright(audio, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                audioPtr->setCopyright(tmpStr);
+                free(tmpStr);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_get_copyright()").c_str());
+        }
+
+        err = audio_meta_get_track_num(audio, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                audioPtr->setTrackNumber(atoi(tmpStr));
+                free(tmpStr);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_get_track_num()").c_str());
+        }
+
+        err = audio_meta_get_bit_rate(audio, &tmpInt);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            audioPtr->setBitrate(tmpInt);
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_get_bit_rate()").c_str());
+        }
+
+        err = audio_meta_get_genre(audio, &tmpStr);
+        if(MEDIA_CONTENT_ERROR_NONE == err)
+        {
+            if(tmpStr)
+            {
+                std::vector<std::string> genres = String::split(tmpStr, TAG_DELIMETER);
+
+                audioPtr->setGenres(genres);
+                free(tmpStr);
+                tmpStr = NULL;
+            }
+        }
+        else
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_get_genre()").c_str());
+        }
+
+        err = audio_meta_destroy(audio);
+        if(MEDIA_CONTENT_ERROR_NONE != err)
+        {
+            LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                    err, "audio_meta_destroy()").c_str());
+        }
+    }
+    else
+    {
+        LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                err, "media_info_get_audio()").c_str());
+    }
+
+    return audioPtr;
+}
+
+
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/ContentHelper.h b/src/Content/ContentHelper.h
new file mode 100755 (executable)
index 0000000..71b8f4a
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_HELPER_H__
+#define __TIZEN_CONTENT_HELPER_H__
+
+#include <glib.h>
+#include <vector>
+#include <media_content.h>
+//#include <IFilter.h>
+//#include <SortMode.h>
+
+#include "Content.h"
+#include "ContentDirectory.h"
+#include "ImageContent.h"
+#include "VideoContent.h"
+#include "AudioContent.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+namespace {
+const guint G_IDLE_FAILED = 0;
+}
+
+class JSPlaylistItem;
+
+class ContentHelper
+{
+public:
+    virtual ~ContentHelper();
+    static bool Connect();
+    static bool DisConnect();
+
+    static int getCallbackCompleted(void *data);
+    static int getCallbackCanceled(void *data);
+
+    static gboolean getDirectoryWork(void* data);
+    static bool getDirectoryCallback(media_folder_h folder, void *user_data);
+
+    static gboolean findWork(void* data);
+    static bool findCallback(media_info_h info, void *user_data);
+
+    static gboolean scanFileWork(void* data);
+
+    static bool update(ContentPtr content);
+
+    static gboolean updateBatchWork(void* content);
+
+    static void changeCallbackWork(
+            media_content_error_e error,
+            int pid,
+            media_content_db_update_item_type_e update_item,
+            media_content_db_update_type_e update_type,
+            media_content_type_e media_type,
+            char *uuid,
+            char *path,
+            char *mime_type,
+            void *user_data);
+
+private:
+    ContentHelper();
+
+    static int get_utc_offset();
+    static bool loadContent(media_info_h info, void* user_data);
+    static bool updateContentToPlatform(ContentPtr content);
+    static void loadContentFromPlatform(media_info_h info, ContentPtr content);
+    static ImageContentPtr loadImageContentFromPlatform(media_info_h info,
+            ImageContentPtr image);
+    static VideoContentPtr loadVideoContentFromPlatform(media_info_h info,
+            VideoContentPtr video);
+    static AudioContentPtr loadAudioContentFromPlatform(media_info_h info,
+            AudioContentPtr audio);
+
+    friend class Playlist;
+    friend class JSPlaylistItem;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_CONTENT_DIRECTORY_H__
diff --git a/src/Content/ContentManager.cpp b/src/Content/ContentManager.cpp
new file mode 100755 (executable)
index 0000000..39f0b91
--- /dev/null
@@ -0,0 +1,523 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+
+#include "ContentManager.h"
+#include "ContentHelper.h"
+#include "GetPlaylistsRequest.h"
+#include "JSPlaylist.h"
+#include "PlaylistUtils.h"
+#include "PlaylistCopyUtil.h"
+
+#include <glib.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+ContentManager::ContentManager()
+{
+    m_isConnected = ContentHelper::Connect();
+}
+
+ContentManager::~ContentManager()
+{
+    if(m_isConnected)
+    {
+        ContentHelper::DisConnect();
+    }
+}
+
+ContentManager& ContentManager::getInstance()
+{
+    static ContentManager instance;
+    return instance;
+}
+
+void ContentManager::update(ContentPtr content)
+{
+    if(m_isConnected)
+    {
+        if(!ContentHelper::update(content))
+        {
+            throw UnknownException("This operation is failed by platform.");
+        }
+    }
+    else
+    {
+        throw UnknownException("DB Connection is failed.");
+    }
+}
+void ContentManager::updateBatch(ContentCallback *callback)
+{
+    LOGD("Entered");
+
+    if(m_isConnected)
+    {
+        if (0 == g_idle_add(ContentHelper::updateBatchWork, static_cast<void * >(callback))) {
+            LOGE("g_idle addition failed");
+            throw UnknownException("Unknown error.");
+        }
+    }
+    else
+    {
+        throw UnknownException("DB Connection is failed.");
+    }
+}
+
+void ContentManager::getDirectories(ContentCallback *callback)
+{
+    LOGD("Entered");
+
+    if(m_isConnected)
+    {
+        if (0 == g_idle_add(ContentHelper::getDirectoryWork,
+                static_cast<void*>(callback))) {
+            LOGE("g_idle addition failed");
+            throw UnknownException("Unknown error.");
+        }
+    }
+    else
+    {
+        throw UnknownException("DB Connection is failed.");
+    }
+}
+
+void ContentManager::find(ContentCallback *callback)
+{
+    LOGD("Entered");
+
+    if(m_isConnected)
+    {
+        if (0 == g_idle_add(ContentHelper::findWork,
+                static_cast<void*>(callback))) {
+            delete callback;
+            callback = NULL;
+            LOGE("g_idle addition failed");
+        }
+    }
+    else
+    {
+        throw UnknownException("DB Connection is failed.");
+    }
+}
+void ContentManager::scanFile(ContentCallback *callback)
+{
+    LOGD("Entered");
+
+    if(m_isConnected)
+    {
+        if (0 == g_idle_add(ContentHelper::scanFileWork,
+                static_cast<void*>(callback))) {
+            delete callback;
+            callback = NULL;
+            LOGE("g_idle addition failed");
+        }
+    }
+    else
+    {
+        throw UnknownException("DB Connection is failed.");
+    }
+}
+bool ContentManager::setChangeListener(ContentChangeCallbackPtr changeCallback)
+{
+    ContentChangeCallbackPtrList::iterator itr;
+    m_listeners_list.push_back(changeCallback);
+
+    bool ret = false;
+    if(m_isConnected)
+    {
+        if(m_listeners_list.size() <= 1) {
+            int ret_code = media_content_set_db_updated_cb(ContentHelper::changeCallbackWork,
+                    static_cast<void*>(&m_listeners_list));
+            if( MEDIA_CONTENT_ERROR_NONE == ret_code )
+            {
+                ret = true;
+            } else {
+                LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                        ret_code, "media_content_set_db_updated_cb()").c_str());
+            }
+        } else {
+            ret = true;
+        }
+    }
+    else
+    {
+        throw UnknownException("DB Connection is failed.");
+    }
+    return ret;
+}
+bool ContentManager::unsetChangeListener(ContentChangeCallbackPtr changeCallback)
+{
+    bool ret = false;
+    if(m_isConnected)
+    {
+        TIME_TRACER_ITEM_BEGIN("unsetChangeListenerPlatform", 1);
+        m_listeners_list.remove(changeCallback);
+        if (m_listeners_list.empty()) {
+            int ret_code = media_content_unset_db_updated_cb();
+            if ( MEDIA_CONTENT_ERROR_NONE != ret_code ){
+                LOGW("%s", ContentUtility::getMediaContentLogMessage(
+                        ret_code, "media_content_unset_db_updated_cb()").c_str());
+            }
+        }
+        ret = true;
+        TIME_TRACER_ITEM_END("unsetChangeListenerPlatform", 1);
+    }
+    else
+    {
+        throw UnknownException("DB Connection is failed.");
+    }
+    return ret;
+}
+
+static gboolean getPlaylistsCompleteCB(void* data)
+{
+    LOGD("Entered");
+    PlaylistArraySuccessCallbackUserData* callback =
+            static_cast<PlaylistArraySuccessCallbackUserData*>(data);
+    if(!callback) {
+        LOGE("Callback is NULL!");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+
+            JSValueRef playlists_array = JSPlaylist::playlistsVectorToJSObjectArray(
+                    context, *(callback->getPlaylists().get()));
+            callback->callSuccessCallback(playlists_array);
+        }
+
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling getPlaylists callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Failed to call get playlists callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* ContentManager::getPlaylistsThread(void* data)
+{
+    LOGD("Entered");
+    PlaylistArraySuccessCallbackUserData* callback =
+            static_cast<PlaylistArraySuccessCallbackUserData*>(data);
+    if(!callback) {
+        LOGE("Callback is NULL!");
+        return NULL;
+    }
+
+    try {
+        callback->setPlaylists(GetPlaylistsRequest::getPlaylists());
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Get playlists failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Get playlists failed");
+    }
+
+    if (!g_idle_add(getPlaylistsCompleteCB, static_cast<void*>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+
+    return NULL;
+}
+
+void ContentManager::getPlaylists(PlaylistArraySuccessCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, getPlaylistsThread,
+            static_cast<void *>(callback))) {
+        LOGE("Failed to create pthread for getPlaylists()");
+        throw UnknownException("Could not run get playlists task");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for getPlaylists()");
+    }
+}
+
+static gboolean createPlaylistCompleteCB(void* data)
+{
+    LOGD("Entered");
+    CreatePlaylistCallbackUserData* callback =
+            static_cast<CreatePlaylistCallbackUserData*>(data);
+    if(!callback) {
+        LOGE("Callback is NULL!");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback(
+                    JSPlaylist::makeJSObject(context, callback->getPlaylist()));
+        }
+
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling createPlaylist callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Failed to call create playlist callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* ContentManager::createPlaylistThread(void* data)
+{
+    LOGD("Entered");
+    CreatePlaylistCallbackUserData* callback =
+            static_cast<CreatePlaylistCallbackUserData*>(data);
+    if(!callback) {
+        LOGE("Callback is NULL!");
+        return NULL;
+    }
+
+    media_playlist_h playlist_handle = NULL;
+
+    try {
+        if(callback->getPlaylistName().empty()) {
+            LOGE("Playlist name is empty!");
+            throw InvalidValuesException("Playlist name is empty!");
+        }
+
+        int ret_code = media_playlist_insert_to_db(callback->getPlaylistName().c_str(),
+                &playlist_handle);
+        if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+            LOGE("ret : %d", ret_code);
+
+            if(MEDIA_CONTENT_ERROR_INVALID_OPERATION == ret_code) {
+                LOGE("Playlist name: %s is probably already used",
+                        callback->getPlaylistName().c_str());
+                ContentUtility::throwMediaContentException<InvalidValuesException>(
+                        ret_code, "media_playlist_insert_to_db()");
+            } else {
+                ContentUtility::throwMediaContentException(ret_code, "media_playlist_insert_to_db()");
+            }
+        }
+
+        if(!playlist_handle) {
+            LOGE("playlist_handle is NULL");
+            throw UnknownException("Failed to create new playlist!");
+        }
+
+        int playlist_id = 0;
+        ret_code = media_playlist_get_playlist_id(playlist_handle, &playlist_id);
+        if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+            LOGE("ret : %d", ret_code);
+            ContentUtility::throwMediaContentException(ret_code, "media_playlist_get_playlist_id()");
+        }
+
+        PlaylistPtr new_playlist(new Playlist(playlist_id));
+        callback->setPlaylist(new_playlist);
+
+        PlaylistPtr source_playlist = callback->getSourcePlaylist();
+        if(source_playlist) {
+            PlaylistCopyUtil::copyItems(source_playlist, new_playlist);
+            LOGD("sucessfully copied items from playlist with id:%d to:%d",
+                    source_playlist->getId(), playlist_id);
+        }
+
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Create playlist failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Create playlist failed");
+    }
+
+    destroyMediaPlaylistHandle(playlist_handle);
+
+    if (!g_idle_add(createPlaylistCompleteCB, static_cast<void*>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+
+    return NULL;
+}
+
+void ContentManager::createPlaylist(CreatePlaylistCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, createPlaylistThread,
+            static_cast<void *>(callback))) {
+        LOGE("Failed to create pthread for createPlaylist()");
+        throw UnknownException("Could not run create playlist task");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for createPlaylist()");
+    }
+}
+
+static gboolean removePlaylistCompleteCB(void* data)
+{
+    LOGD("Entered");
+
+    RemovePlaylistCallbackUserData* callback =
+            static_cast<RemovePlaylistCallbackUserData*>(data);
+    if(!callback) {
+        LOGE("Callback is NULL!");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling removePlaylist callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Failed to call removePlaylist callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* ContentManager::removePlaylistThread(void* data)
+{
+    LOGD("Entered");
+
+    RemovePlaylistCallbackUserData* callback =
+            static_cast<RemovePlaylistCallbackUserData*>(data);
+    if(!callback) {
+        LOGE("Callback is NULL!");
+        return NULL;
+    }
+
+    try {
+        int id = 0;
+        try {
+            id = std::stoi(callback->getPlaylistId());
+        }
+        catch (const std::invalid_argument& error) {
+            LOGE("Cannot convert playlist id to integer");
+            id = -1;
+        }
+        const int ret_code = media_playlist_delete_from_db(id);
+        LOGD("media_playlist_delete_from_db(%d) returned: %s",
+                id, ContentUtility::getMediaContentErrorMessage(ret_code));
+
+        if(MEDIA_CONTENT_ERROR_NONE != ret_code
+                && MEDIA_CONTENT_ERROR_INVALID_PARAMETER != ret_code) {
+            LOGE("ret : %d", ret_code);
+            ContentUtility::throwMediaContentException(ret_code, "media_playlist_delete_from_db()");
+        }
+
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Remove playlist failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Remove playlist failed");
+    }
+
+    if (!g_idle_add(removePlaylistCompleteCB, static_cast<void*>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+
+    return NULL;
+}
+
+void ContentManager::removePlaylist(RemovePlaylistCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, removePlaylistThread,
+            static_cast<void *>(callback))) {
+        LOGE("Failed to create pthread for removePlaylist()");
+        throw UnknownException("Could not run remove playlist task");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for removePlaylist()");
+    }
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/ContentManager.h b/src/Content/ContentManager.h
new file mode 100755 (executable)
index 0000000..b8e8376
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_MANAGER_H__
+#define __TIZEN_CONTENT_MANAGER_H__
+
+#include "ContentTypes.h"
+#include "Content.h"
+#include "ContentChangeCallback.h"
+#include "ContentCallback.h"
+#include <list>
+#include <Security.h>
+
+#include "PlaylistArraySuccessCallbackUserData.h"
+#include "CreatePlaylistCallbackUserData.h"
+#include "RemovePlaylistCallbackUserData.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+class ContentManager: public DeviceAPI::Common::SecurityAccessor
+{
+public:
+    static ContentManager& getInstance();
+
+    virtual ~ContentManager();
+
+    void update(ContentPtr content);
+
+    void updateBatch(ContentCallback *callback);
+
+    void getDirectories(ContentCallback *callback);
+
+    void find(ContentCallback *callback);
+
+    void scanFile(ContentCallback *callback);
+
+    bool setChangeListener(ContentChangeCallbackPtr changeCallback);
+
+    bool unsetChangeListener(ContentChangeCallbackPtr changeCallback);
+
+    void getPlaylists(PlaylistArraySuccessCallbackUserData* callback);
+
+    void createPlaylist(CreatePlaylistCallbackUserData* callback);
+
+    void removePlaylist(RemovePlaylistCallbackUserData* callback);
+
+private:
+    ContentManager();
+    ContentManager(const ContentManager&);
+    ContentManager& operator=(const ContentManager&);
+
+    ContentChangeCallbackPtrList m_listeners_list;
+
+    static void* getPlaylistsThread(void* data);
+    static void* createPlaylistThread(void* data);
+    static void* removePlaylistThread(void* data);
+
+    bool m_isConnected;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_CONTENT_MANAGER_H__
diff --git a/src/Content/ContentScanFileCallback.h b/src/Content/ContentScanFileCallback.h
new file mode 100755 (executable)
index 0000000..cba2758
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_SCANFILE_CALLBACK_H__
+#define __TIZEN_CONTENT_SCANFILE_CALLBACK_H__
+
+#include <string>
+#include <memory>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+
+#include "ContentUtility.h"
+#include "ContentCallback.h"
+#include <TimeTracer.h>
+
+using namespace DeviceAPI::Common;
+//using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Content {
+
+class ContentScanFileCallback : public ContentCallback
+{
+public:
+    ContentScanFileCallback(JSContextRef globalCtx, std::string URI):ContentCallback(globalCtx){
+        m_contentURI = URI;
+    };
+
+    virtual ~ContentScanFileCallback(){
+        LOGD("Entered");
+    };
+
+    void onSuccess(){
+        JSValueRef jsResult = JSUtil::toJSValueRef(
+                m_callback->getContext(),ContentUtility::convertPathToUri(m_contentURI));
+        if (jsResult == NULL) {
+            throw DeviceAPI::Common::UnknownException("This operation is failed by platform.");
+        }
+        m_callback->invokeCallback("onsuccess", jsResult);
+        TIME_TRACER_ITEM_END(CONTENT_TT_SCAN_FILE_TOTAL, CONTENT_TIME_TRACER_SHOW);
+    };
+
+    std::string getContentURI(){
+        return m_contentURI;
+    };
+
+private:
+    std::string m_contentURI;
+};
+
+
+typedef std::shared_ptr<ContentScanFileCallback> ContentScanFileCallbackPtr;
+
+} // Content
+} // DeviceAPI
+
+
+
+#endif // __TIZEN_CONTENT_GETDIRECTORY_CALLBACK_H__
diff --git a/src/Content/ContentTypes.h b/src/Content/ContentTypes.h
new file mode 100644 (file)
index 0000000..ef87885
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _CONTENT_TYPES_H_
+#define _CONTENT_TYPES_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace DeviceAPI {
+namespace Content {
+
+// enum ContentDirectoryStorageType
+#define TIZEN_CONTENT_DIRECTORY_STORAGE_TYPE_INTERNAL "INTERNAL"
+#define TIZEN_CONTENT_DIRECTORY_STORAGE_TYPE_EXTERNAL "EXTERNAL"
+
+// enum ContentType
+#define TIZEN_CONTENT_TYPE_IMAGE "IMAGE"
+#define TIZEN_CONTENT_TYPE_VIDEO "VIDEO"
+#define TIZEN_CONTENT_TYPE_AUDIO "AUDIO"
+#define TIZEN_CONTENT_TYPE_OTHER "OTHER"
+
+// enum AudioContentLyricsType
+#define TIZEN_AUDIO_CONTENT_LYRICS_TYPE_SYNCHRONIZED "SYNCHRONIZED"
+#define TIZEN_AUDIO_CONTENT_LYRICS_TYPE_UNSYNCHRONIZED "UNSYNCHRONIZED"
+
+// enum ImageContentOrientation
+#define TIZEN_IMAGE_CONTENT_ORIENTATION_NORMAL "NORMAL"
+#define TIZEN_IMAGE_CONTENT_ORIENTATION_FLIP_HORIZONTAL "FLIP_HORIZONTAL"
+#define TIZEN_IMAGE_CONTENT_ORIENTATION_ROTATE_180 "ROTATE_180"
+#define TIZEN_IMAGE_CONTENT_ORIENTATION_FLIP_VERTICAL "FLIP_VERTICAL"
+#define TIZEN_IMAGE_CONTENT_ORIENTATION_TRANSPOSE "TRANSPOSE"
+#define TIZEN_IMAGE_CONTENT_ORIENTATION_ROTATE_90 "ROTATE_90"
+#define TIZEN_IMAGE_CONTENT_ORIENTATION_TRANSVERSE "TRANSVERSE"
+#define TIZEN_IMAGE_CONTENT_ORIENTATION_ROTATE_270 "ROTATE_270"
+
+// typedef ContentId
+typedef std::string ContentId;
+// typedef ContentDirectoryId
+typedef std::string ContentDirectoryId;
+
+} // Content
+} // DeviceAPI
+
+#endif // _CONTENT_TYPES_H_
diff --git a/src/Content/ContentUpdateBatchCallback.h b/src/Content/ContentUpdateBatchCallback.h
new file mode 100755 (executable)
index 0000000..5b21fb7
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_UPDATEBATCH_CALLBACK_H__
+#define __TIZEN_CONTENT_UPDATEBATCH_CALLBACK_H__
+
+#include <string>
+#include <memory>
+
+//#include <IFilter.h>
+//#include <SortMode.h>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include "JSContent.h"
+#include "JSImageContent.h"
+#include "JSVideoContent.h"
+#include "JSAudioContent.h"
+
+#include "ContentCallback.h"
+#include "Content.h"
+#include <TimeTracer.h>
+
+using namespace DeviceAPI::Common;
+//using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Content {
+
+class ContentUpdateBatchCallback : public ContentCallback
+{
+public:
+    ContentUpdateBatchCallback(JSContextRef globalCtx ) : ContentCallback(globalCtx){};
+
+    virtual ~ContentUpdateBatchCallback(){
+        m_contents.clear();
+    };
+
+    void setContents(ContentLst contents)
+    {
+        m_contents = contents;
+    }
+    ContentLst* getContents(){
+        return &m_contents;
+    };
+
+private:
+    ContentLst m_contents;
+};
+
+typedef std::shared_ptr<ContentUpdateBatchCallback> ContentUpdateBatchCallbackPtr;
+
+} // Content
+} // DeviceAPI
+
+
+
+#endif // __TIZEN_CONTENT_UPDATEBATCH_CALLBACK_H__
diff --git a/src/Content/ContentUtility.cpp b/src/Content/ContentUtility.cpp
new file mode 100755 (executable)
index 0000000..044b951
--- /dev/null
@@ -0,0 +1,196 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ContentUtility.h"
+#include <Commons/Regex.h>
+#include <Logger.h>
+#include <sstream>
+#include <metadata_extractor.h>
+#include <media_content.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+
+namespace {
+const char* ERROR_UNKNOWN = "Unknown";
+const char* ERROR_NONE_STR = "Successful";
+const char* ERROR_INVALID_PARAMETER_STR = "Invalid parameter";
+const char* ERROR_OUT_OF_MEMORY_STR = "Out of memory";
+const char* ERROR_INVALID_OPERATION_STR = "Invalid Operation";
+const char* ERROR_FILE_NO_SPACE_ON_DEVICE_STR = "No space left on device";
+const char* ERROR_DB_FAILED_STR = "DB operation failed";
+const char* ERROR_DB_BUSY_STR = "DB operation BUSY";
+const char* ERROR_NETWORK_STR = "Network Fail";
+const char* ERROR_UNSUPPORTED_CONTENT_STR = "Unsupported Content";
+const char* ERROR_PERMISSION_DENIED_STR = "Permission denied";
+}
+
+ContentUtility::ContentUtility()
+{
+}
+
+ContentUtility::~ContentUtility()
+{
+}
+
+bool ContentUtility::isContentUri(const std::string str)
+{
+    std::string schema("file://");
+    std::size_t found = str.find(schema);
+
+    if (found == std::string::npos || found != 0) {
+        return false;
+    }
+
+    return true;
+}
+
+string ContentUtility::convertUriToPath(const string str)
+{
+    string result;
+    std::string schema ("file://");
+    std::string _str = ContentUtility::ltrim(str);
+
+    std::string _schema = _str.substr(0,schema.size());
+
+    if(_schema == schema)
+    {
+        result = _str.substr(schema.size());
+    }
+    else
+    {
+        result = _str;
+    }
+    return result;
+}
+
+string ContentUtility::convertPathToUri(const string str)
+{
+    string result;
+    std::string schema ("file://");
+    std::string _str = ContentUtility::ltrim(str);
+
+    std::string _schema = _str.substr(0,schema.size());
+
+    if(_schema == schema)
+    {
+        result = _str;
+    }
+    else
+    {
+        result = schema + _str;
+    }
+    return result;
+}
+
+std::string ContentUtility::ltrim(const std::string s)
+{
+    std::string str = s;
+    std::string::iterator i;
+    for (i = str.begin(); i != str.end(); i++) {
+        if (!isspace(*i)) {
+            break;
+        }
+    }
+    if (i == str.end()) {
+        str.clear();
+    } else {
+        str.erase(str.begin(), i);
+    }
+    return str;
+}
+
+bool ContentUtility::checkLocation(double lati, double longi)
+{
+    bool ret = true;
+    if(lati < MIN_LATITUDE || lati > MAX_LATITUDE ||
+            longi < MIN_LONGITUDE || longi > MAX_LONGITUDE){
+        ret = false;
+    }
+    return ret;
+}
+
+std::string ContentUtility::getMetadataErrorMessage(
+        const int errorCode, const std::string& hint) {
+    std::stringstream ss;
+    ss << "Failed " << hint << ": ";
+
+    switch(errorCode) {
+        case METADATA_EXTRACTOR_ERROR_INVALID_PARAMETER:
+            ss << "Invalid parameter";
+            break;
+        case METADATA_EXTRACTOR_ERROR_FILE_EXISTS:
+            ss << "File does not exist";
+            break;
+        case METADATA_EXTRACTOR_ERROR_OUT_OF_MEMORY:
+            ss << "Out of memory";
+            break;
+        case METADATA_EXTRACTOR_ERROR_PERMISSION_DENIED:
+            ss << "Permission denied";
+            break;
+        case METADATA_EXTRACTOR_ERROR_OPERATION_FAILED:
+            ss << "Invalid internal operation";
+            break;
+        default:
+            ss << "Unknown Error";
+            break;
+    }
+
+    ss << ", " << errorCode;
+    return ss.str();
+}
+
+std::string ContentUtility::getMediaContentLogMessage(
+        const int errorCode, const std::string &hint){
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getMediaContentErrorMessage(errorCode)
+                    << ", " << errorCode;
+    return ss.str();
+}
+
+const char* ContentUtility::getMediaContentErrorMessage(const int errorCode) {
+    switch(errorCode) {
+        case MEDIA_CONTENT_ERROR_NONE:
+            return ERROR_NONE_STR;
+        case MEDIA_CONTENT_ERROR_INVALID_PARAMETER:
+            return ERROR_INVALID_PARAMETER_STR;
+        case MEDIA_CONTENT_ERROR_PERMISSION_DENIED:
+            return ERROR_PERMISSION_DENIED_STR;
+        case MEDIA_CONTENT_FILE_NO_SPACE_ON_DEVICE:
+            return ERROR_FILE_NO_SPACE_ON_DEVICE_STR;
+        case MEDIA_CONTENT_ERROR_INVALID_OPERATION:
+            return ERROR_INVALID_OPERATION_STR;
+        case MEDIA_CONTENT_ERROR_DB_FAILED:
+            return ERROR_DB_FAILED_STR;
+        case MEDIA_CONTENT_ERROR_DB_BUSY:
+            return ERROR_DB_BUSY_STR;
+        case MEDIA_CONTENT_ERROR_NETWORK:
+            return ERROR_NETWORK_STR;
+        case MEDIA_CONTENT_ERROR_UNSUPPORTED_CONTENT:
+            return ERROR_UNSUPPORTED_CONTENT_STR;
+        case MEDIA_CONTENT_ERROR_OUT_OF_MEMORY:
+            return ERROR_OUT_OF_MEMORY_STR;
+        default:
+            return ERROR_UNKNOWN;
+    }
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/ContentUtility.h b/src/Content/ContentUtility.h
new file mode 100755 (executable)
index 0000000..a12cf86
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _PLATFORM_CONTENT_UTILITY_H_
+#define _PLATFORM_CONTENT_UTILITY_H_
+
+#include <string>
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+const double MAX_LATITUDE = 90;
+const double MIN_LATITUDE = -90;
+const double MAX_LONGITUDE = 180;
+const double MIN_LONGITUDE = -180;
+
+class ContentUtility
+{
+public:
+    ContentUtility();
+    virtual ~ContentUtility();
+
+    static bool isContentUri(const std::string str);
+    static std::string convertUriToPath(const std::string str);
+    static std::string convertPathToUri(const std::string str);
+    static bool checkLocation(double lati, double longi);
+
+    static std::string getMetadataErrorMessage(const int errorCode, const std::string& hint);
+    static const char* getMediaContentErrorMessage(const int errorCode);
+    static std::string getMediaContentLogMessage(const int errorCode, const std::string& hint);
+
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwMetadataException(const int errorCode, const std::string& hint) {
+        std::string message = ContentUtility::getMetadataErrorMessage(errorCode, hint);
+
+        LOGE("%s", message.c_str());
+        throw T(message.c_str());
+    }
+
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwMediaContentException(const int errorCode, const std::string& hint) {
+        std::string message = ContentUtility::getMediaContentLogMessage(errorCode, hint);
+
+        LOGE("%s", message.c_str());
+        throw T(message.c_str());
+    }
+private:
+    static std::string ltrim(const std::string s);
+
+};
+
+} // Content
+} // DeviceAPI
+
+#endif // _PLATFORM_CONTENT_UTILITY_H_
diff --git a/src/Content/CreatePlaylistCallbackUserData.cpp b/src/Content/CreatePlaylistCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..976e487
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "CreatePlaylistCallbackUserData.h"
+
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+CreatePlaylistCallbackUserData::CreatePlaylistCallbackUserData(
+        JSContextRef global_ctx) :
+                BaseCallbackUserData(global_ctx)
+{
+}
+
+CreatePlaylistCallbackUserData::~CreatePlaylistCallbackUserData()
+{
+}
+
+const std::string& CreatePlaylistCallbackUserData::getPlaylistName()
+{
+    return m_playlist_name;
+}
+
+void CreatePlaylistCallbackUserData::setPlaylistName(const std::string& playlist_name)
+{
+    m_playlist_name = playlist_name;
+}
+
+PlaylistPtr CreatePlaylistCallbackUserData::getPlaylist() const
+{
+    return m_playlist;
+}
+
+void CreatePlaylistCallbackUserData::setPlaylist(PlaylistPtr playlist)
+{
+    m_playlist = playlist;
+}
+
+PlaylistPtr CreatePlaylistCallbackUserData::getSourcePlaylist() const
+{
+    return m_source_playlist;
+}
+
+void CreatePlaylistCallbackUserData::setSourcePlaylist(PlaylistPtr source_playlist)
+{
+    m_source_playlist = source_playlist;
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/CreatePlaylistCallbackUserData.h b/src/Content/CreatePlaylistCallbackUserData.h
new file mode 100644 (file)
index 0000000..34b3ab2
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_CREATE_PLAYLIST_CALLBACK_USER_DATA_H__
+#define __TIZEN_CONTENT_CREATE_PLAYLIST_CALLBACK_USER_DATA_H__
+
+#include <string>
+
+#include "BaseCallbackUserData.h"
+#include "Playlist.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class CreatePlaylistCallbackUserData : public BaseCallbackUserData
+{
+public:
+    CreatePlaylistCallbackUserData(JSContextRef global_ctx);
+    virtual ~CreatePlaylistCallbackUserData();
+
+    const std::string& getPlaylistName();
+    void setPlaylistName(const std::string& playlist_name);
+
+    PlaylistPtr getPlaylist() const;
+    void setPlaylist(PlaylistPtr playlist);
+
+    PlaylistPtr getSourcePlaylist() const;
+    void setSourcePlaylist(PlaylistPtr source_playlist);
+
+private:
+    std::string m_playlist_name;
+    PlaylistPtr m_playlist;
+    PlaylistPtr m_source_playlist;
+};
+
+} //Content
+} //DeviceAPI
+
+#endif /* __TIZEN_CONTENT_CREATE_PLAYLIST_CALLBACK_USER_DATA_H__ */
diff --git a/src/Content/GetPlaylistItemsRequest.cpp b/src/Content/GetPlaylistItemsRequest.cpp
new file mode 100755 (executable)
index 0000000..e54a8cd
--- /dev/null
@@ -0,0 +1,198 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "GetPlaylistItemsRequest.h"
+
+#include <limits>
+
+#include <Logger.h>
+
+#include "PlaylistUtils.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+const long GetPlaylistItemsRequest::COUNT_NOT_LIMITED = std::numeric_limits<long>::max();
+
+std::shared_ptr<PlaylistItemPtrVec> GetPlaylistItemsRequest::getItems(
+        PlaylistPtr src_playlist,
+        media_playlist_h playlist_handle,
+        long count,
+        long offset,
+        bool sort_in_play_order)
+{
+    LOGD("Entered playlist_id:%d offset:%d count:%d",
+            src_playlist ? src_playlist->getId() : -1,
+                    offset, count);
+
+    if(!src_playlist) {
+        LOGE("Playlist is NULL!");
+        throw InvalidValuesException("Invalid playlist");
+    }
+
+    if(count <= 0) {
+        LOGE("count:%d is <= 0", count);
+        throw InvalidValuesException("value of count parameter is invalid");
+    }
+
+    if(offset < 0) {
+        LOGE("offset:%d is < 0", offset);
+        throw InvalidValuesException("value of offset parameter is invalid");
+    }
+
+    LOGD("Fixed: offset:%d count:%d", offset, count);
+
+    media_playlist_h playlist_handle_to_destroy = NULL;
+    if(!playlist_handle) {
+        playlist_handle = src_playlist->getPlaylistHandle();
+        playlist_handle_to_destroy = playlist_handle;
+    }
+
+    try {
+        GetPlaylistItemsRequest req(playlist_handle, src_playlist->getId(), count,
+                offset, sort_in_play_order);
+        req.runRequest();
+
+        if(playlist_handle_to_destroy) {
+            destroyMediaPlaylistHandle(playlist_handle_to_destroy);
+        }
+        return req.m_items;
+    }
+    catch(...) {
+        LOGE("GetPlaylistItemsRequest failed!");
+        if(playlist_handle_to_destroy) {
+            destroyMediaPlaylistHandle(playlist_handle_to_destroy);
+        }
+        throw;
+    }
+}
+
+GetPlaylistItemsRequest::GetPlaylistItemsRequest(media_playlist_h handle, int playlist_id,
+        long count, long offset, bool sort_in_play_order) :
+                m_handle(handle),
+                m_filter(NULL),
+                m_playlist_id(playlist_id),
+                m_count(count),
+                m_offset(offset),
+                m_sort_in_play_order(sort_in_play_order),
+                m_failed(false)
+{
+    PlaylistItemPtrVec* items = new(std::nothrow) PlaylistItemPtrVec();
+    if(!items) {
+        LOGE("Couldn't allocate m_items PlaylistItemPtrVec!");
+        throw UnknownException("Memory allocation failed");
+    }
+
+    m_items = std::shared_ptr<PlaylistItemPtrVec>(items);
+}
+
+GetPlaylistItemsRequest::~GetPlaylistItemsRequest()
+{
+    if(m_filter) {
+        destroyMediaFilterHandle(m_filter);
+    }
+}
+
+bool GetPlaylistItemsRequest::receviedMember(int playlist_member_id,
+        media_info_h media, void *user_data)
+{
+    LOGD("Entered playlist_member_id:%d", playlist_member_id);
+    GetPlaylistItemsRequest* req = NULL;
+
+    try {
+        req = static_cast<GetPlaylistItemsRequest*>(user_data);
+        if(!req) {
+            LOGE("user_data is NULL");
+            return false;
+        }
+
+        PlaylistItem* new_item = new(std::nothrow) PlaylistItem(
+                req->m_playlist_id, playlist_member_id, media);
+        if(!new_item) {
+            LOGE("Couldn't allocate PlaylistItem");
+            throw UnknownException("Memory allocation failed");
+        }
+
+        req->m_items->push_back(PlaylistItemPtr(new_item));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        if(req) {
+            req->m_failed = true;
+        }
+        return false;
+    }
+    catch(...) {
+        LOGE("Unknown exception occured in GetPlaylistItemsRequest::receviedMember");
+        if(req) {
+            req->m_failed = true;
+        }
+        return false;
+    }
+
+    return true;
+}
+
+void GetPlaylistItemsRequest::runRequest()
+{
+    LOGD("Entered playlist_id:%d offset:%d count:%d", m_playlist_id,
+            m_offset, m_count);
+
+    int ret_code = MEDIA_CONTENT_ERROR_NONE;
+    m_filter = NULL;
+    const bool limit_fetch = m_offset > 0 || m_count != COUNT_NOT_LIMITED;
+
+    if(m_sort_in_play_order || limit_fetch) {
+        ret_code = media_filter_create(&m_filter);
+        if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
+            LOGE("ret : %d", ret_code);
+            ContentUtility::throwMediaContentException(ret_code, "media_filter_create()");
+        }
+
+        if(m_sort_in_play_order) {
+            ret_code = media_filter_set_order(m_filter, MEDIA_CONTENT_ORDER_ASC,
+                    PLAYLIST_MEMBER_ORDER, MEDIA_CONTENT_COLLATE_NOCASE);
+            if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
+                LOGE("ret : %d", ret_code);
+                ContentUtility::throwMediaContentException(ret_code, "media_filter_set_order()");
+            }
+        }
+
+        if(limit_fetch) {
+            ret_code = media_filter_set_offset(m_filter, m_offset, m_count);
+            if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
+                LOGE("ret : %d", ret_code);
+                ContentUtility::throwMediaContentException(ret_code, "media_filter_set_offset()");
+            }
+        }
+    }
+
+    ret_code = media_playlist_foreach_media_from_db(m_playlist_id, m_filter,
+            receviedMember, this);
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("ret : %d", ret_code);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_foreach_media_from_db()");
+    }
+
+    if(m_failed) {
+        LOGE("m_failed is TRUE");
+        throw UnknownException("Could not get playlists track list");
+    }
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/GetPlaylistItemsRequest.h b/src/Content/GetPlaylistItemsRequest.h
new file mode 100644 (file)
index 0000000..ef29abd
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_GET_PLAYLISTS_ITEMS_REQUEST_H__
+#define __TIZEN_CONTENT_GET_PLAYLISTS_ITEMS_REQUEST_H__
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <media_content.h>
+#include <media_info.h>
+#include <media_playlist.h>
+
+#include "Playlist.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+
+class GetPlaylistItemsRequest
+{
+public:
+    static const long COUNT_NOT_LIMITED;
+
+    static std::shared_ptr<PlaylistItemPtrVec> getItems(PlaylistPtr src_playlist,
+            media_playlist_h playlist_handle = NULL,
+            long count = COUNT_NOT_LIMITED,
+            long offset = 0,
+            bool sort_in_play_order = true);
+
+private:
+    GetPlaylistItemsRequest(media_playlist_h handle, int playlist_id, long count,
+            long offset = 0, bool sort_in_play_order = true);
+    ~GetPlaylistItemsRequest();
+
+    static bool receviedMember(int playlist_member_id, media_info_h media,
+            void *user_data);
+    void runRequest();
+
+    media_playlist_h m_handle;
+    filter_h m_filter;
+    int m_playlist_id;
+    long m_count;
+    long m_offset;
+    bool m_sort_in_play_order;
+
+    bool m_failed;
+    std::shared_ptr<PlaylistItemPtrVec> m_items;
+};
+
+} //namespace Content
+} //namespace DeviceAPI
+
+#endif // __TIZEN_CONTENT_GET_PLAYLISTS_ITEMS_REQUEST_H__
diff --git a/src/Content/GetPlaylistsRequest.cpp b/src/Content/GetPlaylistsRequest.cpp
new file mode 100644 (file)
index 0000000..08301b8
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "GetPlaylistsRequest.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <sstream>
+
+#include "PlaylistUtils.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+GetPlaylistsRequest::GetPlaylistsRequest() :
+                m_fetch_failed(false),
+                m_playlists(std::shared_ptr<PlaylistPtrVec>(new PlaylistPtrVec()))
+{
+}
+
+GetPlaylistsRequest::~GetPlaylistsRequest()
+{
+}
+
+std::shared_ptr<PlaylistPtrVec> GetPlaylistsRequest::getPlaylists()
+{
+    std::unique_ptr<GetPlaylistsRequest> new_request =
+            std::unique_ptr<GetPlaylistsRequest>(new GetPlaylistsRequest());
+
+    int ret_code = media_playlist_foreach_playlist_from_db(NULL, receivedPlaylistFromDBCB,
+            new_request.get());
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code ||
+            new_request->m_fetch_failed) {
+
+        if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                    ret_code, "media_playlist_foreach_playlist_from_db()").c_str());
+        } else {
+            LOGE("new_request->m_fetch_failed is TRUE");
+        }
+
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_foreach_playlist_from_db()");
+    }
+
+    return new_request->m_playlists;
+}
+
+bool GetPlaylistsRequest::receivedPlaylistFromDBCB(media_playlist_h playlist,
+        void *user_data)
+{
+    GetPlaylistsRequest* request = static_cast<GetPlaylistsRequest*>(user_data);
+    if(!request) {
+        LOGE("user_data is NULL, aborting fetch!");
+        return false;   //Core API doc for media_playlist_cb:
+        //"false" to break out of the loop"
+    }
+
+    return request->process(playlist);
+}
+
+bool GetPlaylistsRequest::process(media_playlist_h playlist)
+{
+    int playlist_id = 0;
+    int ret_code = media_playlist_get_playlist_id(playlist, &playlist_id);
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                ret_code, "media_playlist_get_playlist_id()").c_str());
+        m_fetch_failed = true;
+        return false;
+    }
+    m_playlists->push_back(PlaylistPtr(new Playlist(playlist_id)));
+
+    return true;
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/GetPlaylistsRequest.h b/src/Content/GetPlaylistsRequest.h
new file mode 100644 (file)
index 0000000..39a1078
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_GET_PLAYLISTS_REQUEST_H__
+#define __TIZEN_CONTENT_GET_PLAYLISTS_REQUEST_H__
+
+#include <media_content.h>
+#include <memory>
+
+#include "Playlist.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class GetPlaylistsRequest
+{
+public:
+    ~GetPlaylistsRequest();
+    static std::shared_ptr<PlaylistPtrVec> getPlaylists();
+
+private:
+    GetPlaylistsRequest();
+
+    static bool receivedPlaylistFromDBCB(media_playlist_h playlist, void *user_data);
+    bool process(media_playlist_h playlist);
+
+    bool m_fetch_failed;
+    std::shared_ptr<PlaylistPtrVec> m_playlists;
+
+};
+
+} //namespace Content
+} //namespace DeviceAPI
+
+#endif // __TIZEN_CONTENT_GET_PLAYLISTS_REQUEST_H__
diff --git a/src/Content/ImageContent.cpp b/src/Content/ImageContent.cpp
new file mode 100755 (executable)
index 0000000..04d90a6
--- /dev/null
@@ -0,0 +1,179 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "ImageContent.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+ImageContent::ImageContent() :
+            m_width(0),
+            m_height(0),
+            m_orientation(""),
+            m_is_geolocation_set(false)
+{
+    m_type = "IMAGE";
+    m_editableAttributes.push_back("geolocation");
+    m_editableAttributes.push_back("orientation");
+}
+
+ImageContent::~ImageContent()
+{
+}
+
+SimpleCoordinatesPtr ImageContent::getGeolocation() const
+{
+    return m_geolocation;
+}
+
+void ImageContent::setGeolocation(SimpleCoordinatesPtr geolocation)
+{
+    m_geolocation = geolocation;
+    m_is_geolocation_set = true;
+}
+
+bool ImageContent::isGeolocationSet() const
+{
+    return m_is_geolocation_set;
+}
+
+void ImageContent::unsetGeolocation()
+{
+    m_geolocation = SimpleCoordinatesPtr();
+    m_is_geolocation_set = false;
+}
+
+void ImageContent::setLatitude(double latitude)
+{
+    if(!isGeolocationSet()) {
+        setGeolocation(std::make_shared<SimpleCoordinates>(0.0, 0.0));
+    }
+    m_geolocation->setLatitude(latitude);
+}
+
+double ImageContent::getLatitude()
+{
+    return m_geolocation->getLatitude();
+}
+
+void ImageContent::setLongitude(double longitude)
+{
+    if(!isGeolocationSet()) {
+        setGeolocation(std::make_shared<SimpleCoordinates>(0.0, 0.0));
+    }
+    m_geolocation->setLongitude(longitude);
+}
+
+double ImageContent::getLongitude()
+{
+    return m_geolocation->getLongitude();
+}
+
+unsigned long ImageContent::getWidth() const
+{
+    return m_width;
+}
+
+void ImageContent::setWidth(unsigned long width)
+{
+    m_width = width;
+}
+
+unsigned long ImageContent::getHeight() const
+{
+    return m_height;
+}
+
+void ImageContent::setHeight(unsigned long height)
+{
+    m_height = height;
+}
+
+std::string ImageContent::getOrientation() const
+{
+    return m_orientation;
+}
+
+media_content_orientation_e ImageContent::getOrientationEnum() const
+{
+    media_content_orientation_e ret;
+    if(m_orientation == "NORMAL")
+        ret = MEDIA_CONTENT_ORIENTATION_NORMAL;
+    else if(m_orientation == "FLIP_HORIZONTAL")
+        ret = MEDIA_CONTENT_ORIENTATION_HFLIP;
+    else if(m_orientation == "ROTATE_180")
+        ret = MEDIA_CONTENT_ORIENTATION_ROT_180;
+    else if(m_orientation == "FLIP_VERTICAL")
+        ret = MEDIA_CONTENT_ORIENTATION_VFLIP;
+    else if(m_orientation == "TRANSPOSE")
+        ret = MEDIA_CONTENT_ORIENTATION_TRANSPOSE;
+    else if(m_orientation == "ROTATE_90")
+        ret = MEDIA_CONTENT_ORIENTATION_ROT_90;
+    else if(m_orientation == "TRANSVERSE")
+        ret =MEDIA_CONTENT_ORIENTATION_TRANSVERSE;
+    else if(m_orientation == "ROTATE_270")
+        ret =MEDIA_CONTENT_ORIENTATION_ROT_270;
+    else
+    {
+        ret = MEDIA_CONTENT_ORIENTATION_NOT_AVAILABLE;
+    }
+
+    return ret;
+}
+
+void ImageContent::setOrientation(std::string orientation)
+{
+    m_orientation = orientation;
+}
+
+void ImageContent::setOrientation(int orientation)
+{
+    switch(orientation)
+    {
+        case 0:
+        case 1:
+            m_orientation = "NORMAL";
+            break;
+        case 2:
+            m_orientation = "FLIP_HORIZONTAL";
+            break;
+        case 3:
+            m_orientation = "ROTATE_180";
+            break;
+        case 4:
+            m_orientation = "FLIP_VERTICAL";
+            break;
+        case 5:
+            m_orientation = "TRANSPOSE";
+            break;
+        case 6:
+            m_orientation = "ROTATE_90";
+            break;
+        case 7:
+            m_orientation = "TRANSVERSE";
+            break;
+        case 8:
+            m_orientation = "ROTATE_270";
+            break;
+    }
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/ImageContent.h b/src/Content/ImageContent.h
new file mode 100755 (executable)
index 0000000..1b09896
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_IMAGE_CONTENT_H__
+#define __TIZEN_IMAGE_CONTENT_H__
+
+#include <media_content.h>
+
+#include <MultiCallbackUserData.h>
+#include <SimpleCoordinates.h>
+
+#include "ContentTypes.h"
+#include "Content.h"
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Content {
+
+class ImageContent;
+typedef std::shared_ptr<ImageContent> ImageContentPtr;
+
+class ImageContent : public Content
+{
+public:
+    ImageContent();
+    virtual ~ImageContent();
+
+    SimpleCoordinatesPtr getGeolocation() const;
+    void setGeolocation(SimpleCoordinatesPtr geolocation);
+    bool isGeolocationSet() const;
+    void unsetGeolocation();
+
+    void setLatitude(double latitude);
+    double getLatitude();
+
+    void setLongitude(double longitude);
+    double getLongitude();
+
+    unsigned long getWidth() const;
+    void setWidth(unsigned long width);
+
+    unsigned long getHeight() const;
+    void setHeight(unsigned long height);
+
+    std::string getOrientation() const;
+    media_content_orientation_e getOrientationEnum() const;
+    void setOrientation(std::string orientation);
+    void setOrientation(int orientation);
+
+private:
+    unsigned long m_width;
+    unsigned long m_height;
+    std::string m_orientation;
+    SimpleCoordinatesPtr m_geolocation;
+    bool m_is_geolocation_set;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_IMAGE_CONTENT_H__
diff --git a/src/Content/JSAudioContent.cpp b/src/Content/JSAudioContent.cpp
new file mode 100755 (executable)
index 0000000..e52ac3b
--- /dev/null
@@ -0,0 +1,346 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+#include <Logger.h>
+
+#include <Export.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+
+#include "JSAudioContent.h"
+#include "JSContent.h"
+#include "JSAudioContentLyrics.h"
+
+#include "ContentUtility.h"
+#include "AudioLyricsUtil.h"
+
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Content {
+
+using namespace DeviceAPI::Common;
+
+JSClassDefinition JSAudioContent::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        "AudioContent",
+        JSContent::getClassRef(), //ParentClass
+        m_property, //StaticValues
+        NULL, //StaticFunctions
+        initialize, //Initialize
+        finalize, //Finalize
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL //ConvertToType
+};
+
+JSStaticValue JSAudioContent::m_property[] = {
+        { AUDIO_CONTENT_ALBUM, getAlbum, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_GENRES, getGenres, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_ARTISTS, getArtists, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_COMPOSERS, getComposers, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_LYRICS, getLyrics, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_COPYRIGHT, getCopyright, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_BITRATE, getBitrate, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_TRACK_NUMBER, getTrackNumbers, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_DURATION, getDuration, NULL, kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+JSClassRef JSAudioContent::m_jsClassRef = JSClassCreate(JSAudioContent::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSAudioContent::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAudioContent::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSAudioContent::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSAudioContent::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+AudioContentPtr DLL_EXPORT JSAudioContent::getPrivateObject(JSContextRef context, JSObjectRef object)
+{
+    if (!JSValueIsObjectOfClass(context, object, getClassRef())) {
+        LOGE("TypeMismatch");
+        throw TypeMismatchException("TypeMismatch");
+    }
+
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    return std::static_pointer_cast<AudioContent>(priv->ptr);
+}
+
+void DLL_EXPORT JSAudioContent::setPrivateObject(JSObjectRef object, ContentPtr native)
+{
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("AudioContent's private object is NULL.");
+        throw TypeMismatchException("AudioContent's private object is NULL.");
+    }
+    priv->ptr = native;
+}
+
+bool DLL_EXPORT JSAudioContent::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+JSObjectRef DLL_EXPORT JSAudioContent::CreateJSObject(JSContextRef context, ContentPtr native)
+{
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    if (!native) {
+        LOGE("ContentAudio's private object is NULL.");
+        throw TypeMismatchException("ContentAudio's private object is NULL.");
+    }
+
+    ContentHolder* priv = new(std::nothrow) ContentHolder;
+    if (!priv) {
+        LOGE("Can not be allocated memory");
+        throw UnknownException("Can not be allocated memory");
+    }
+
+    priv->ptr = native;
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+JSValueRef JSAudioContent::getAlbum(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentPtr priv = JSAudioContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getAlbum());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContent::getGenres(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentPtr priv = JSAudioContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getGenres());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContent::getArtists(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentPtr priv = JSAudioContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getArtists());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContent::getComposers(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentPtr priv = JSAudioContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getComposers());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContent::getLyrics(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentPtr priv = JSAudioContent::getPrivateObject(context, object);
+        std::string URI = ContentUtility::convertUriToPath(priv->getContentURI());
+        if (!(URI.empty())) {
+            AudioLyricsUtil LyricsUtil;
+            if (LyricsUtil.fetchLyrics(URI)) {
+                JSValueRef LyricsRef = JSAudioContentLyrics::CreateJSObject(context, LyricsUtil.getAudioLyrics());
+                return LyricsRef;
+            }
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContent::getCopyright(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentPtr priv = JSAudioContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getCopyright());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContent::getBitrate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentPtr priv = JSAudioContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getBitrate());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContent::getTrackNumbers(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentPtr priv = JSAudioContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context,
+                static_cast<unsigned long>(priv->getTrackNumber()));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContent::getDuration(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentPtr priv = JSAudioContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getDuration());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/JSAudioContent.h b/src/Content/JSAudioContent.h
new file mode 100755 (executable)
index 0000000..f516d23
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_AUDIO_CONTENT_H__
+#define __TIZEN_JS_AUDIO_CONTENT_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "AudioContent.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class JSAudioContent
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef CreateJSObject(JSContextRef ctx,  ContentPtr native);
+    static AudioContentPtr getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSObjectRef object, ContentPtr native);
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getAlbum(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getGenres(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getArtists(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getComposers(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLyrics(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCopyright(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getBitrate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTrackNumbers(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDuration(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Content/JSAudioContentLyrics.cpp b/src/Content/JSAudioContentLyrics.cpp
new file mode 100755 (executable)
index 0000000..58e81c3
--- /dev/null
@@ -0,0 +1,214 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+
+#include "JSAudioContentLyrics.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Content {
+
+using namespace DeviceAPI::Common;
+
+struct LyricsHolder{
+    AudioContentLyricsPtr ptr;
+};
+
+JSClassDefinition JSAudioContentLyrics::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        "AudioContentLyrics",
+        NULL, //ParentClass
+        m_property, //StaticValues
+        NULL, //StaticFunctions
+        initialize, //Initialize
+        finalize, //Finalize
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL //ConvertToType
+};
+
+JSStaticValue JSAudioContentLyrics::m_property[] = {
+        { AUDIO_CONTENT_LYRICS_TYPE, getType, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_LYRICS_TIMESTAMPS, getTimestamps, NULL, kJSPropertyAttributeReadOnly },
+        { AUDIO_CONTENT_LYRICS_TEXTS, getTexts, NULL, kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+JSClassRef JSAudioContentLyrics::m_jsClassRef = JSClassCreate(JSAudioContentLyrics::getClassInfo());
+
+const JSClassRef JSAudioContentLyrics::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAudioContentLyrics::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSAudioContentLyrics::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSAudioContentLyrics::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    LyricsHolder* priv = static_cast<LyricsHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSAudioContentLyrics::CreateJSObject(JSContextRef context,
+        AudioContentLyricsPtr native)
+{
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    if (!native) {
+        LOGE("AudioContentLyrics private object is NULL.");
+        throw TypeMismatchException("AudioContentLyrics private object is NULL.");
+    }
+
+    LyricsHolder* priv = new(std::nothrow) LyricsHolder;
+    if (!priv) {
+        LOGE("Can not be allocated memory");
+        throw UnknownException("Can not be allocated memory");
+    }
+
+    priv->ptr = native;
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+AudioContentLyricsPtr JSAudioContentLyrics::getPrivateObject(JSContextRef context,
+        JSObjectRef object)
+{
+    if (!JSValueIsObjectOfClass(context, object, getClassRef())) {
+        LOGE("TypeMismatch");
+        throw TypeMismatchException("TypeMismatch");
+    }
+
+    LyricsHolder* priv = static_cast<LyricsHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    return std::static_pointer_cast<AudioContentLyrics>(priv->ptr);
+}
+
+void JSAudioContentLyrics::setPrivateObject(JSObjectRef object,
+        AudioContentLyricsPtr native)
+{
+    LyricsHolder* priv = static_cast<LyricsHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("AudioContentLyrics private object is NULL.");
+        throw TypeMismatchException("AudioContentLyrics private object is NULL.");
+    }
+    priv->ptr = native;
+}
+
+JSValueRef JSAudioContentLyrics::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentLyricsPtr priv = JSAudioContentLyrics::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getType());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContentLyrics::getTimestamps(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentLyricsPtr priv = JSAudioContentLyrics::getPrivateObject(context, object);
+        if ("UNSYNCHRONIZED" != priv->getType()) {
+            return JSUtil::toJSValueRef_(context, priv->getTimestamps());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSAudioContentLyrics::getTexts(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AudioContentLyricsPtr priv = JSAudioContentLyrics::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getTexts());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/JSAudioContentLyrics.h b/src/Content/JSAudioContentLyrics.h
new file mode 100755 (executable)
index 0000000..3613d28
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_AUDIO_CONTENT_LYRICS_H__
+#define __TIZEN_JS_AUDIO_CONTENT_LYRICS_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "AudioContentLyrics.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class JSAudioContentLyrics
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSValueRef CreateJSObject(JSContextRef ctx, AudioContentLyricsPtr priv);
+    static AudioContentLyricsPtr getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSObjectRef object, AudioContentLyricsPtr native);
+private:
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTimestamps(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTexts(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Content/JSContent.cpp b/src/Content/JSContent.cpp
new file mode 100755 (executable)
index 0000000..6e5e3f2
--- /dev/null
@@ -0,0 +1,528 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+
+#include "JSContent.h"
+
+#include "ContentUtility.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Content {
+
+using namespace DeviceAPI::Common;
+
+JSClassDefinition JSContent::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        "Content",
+        NULL, //ParentClass
+        m_property, //StaticValues
+        NULL, //StaticFunctions
+        initialize, //Initialize
+        finalize, //Finalize
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL  //ConvertToType
+};
+
+JSStaticValue JSContent::m_property[] = {
+        { CONTENT_EDITABLE_ATTRIBUTES, getEditableAttributes, NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_ID, getId,  NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_NAME, getName, setName, kJSPropertyAttributeDontDelete },
+        { CONTENT_TYPE, getType, NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_MIME_TYPE, getMimeType, NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_TITLE, getTitle, NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_CONTENT_URI, getUri, NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_THUMBNAIL_URIS, getThumbnailUri, NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_RELEASE_DATE, getReleaseDate, NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_MODIFIED_DATE, getModifiedDate, NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_SIZE, getSize, NULL, kJSPropertyAttributeDontDelete
+                | kJSPropertyAttributeReadOnly },
+        { CONTENT_DESCRIPTION, getDescription, setDescription, kJSPropertyAttributeDontDelete },
+        { CONTENT_RATING, getRating, setRating, kJSPropertyAttributeDontDelete },
+        { CONTENT_IS_FAVORITE, getIsFavorite, setIsFavorite, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+JSClassRef JSContent::m_jsClassRef = JSClassCreate(JSContent::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSContent::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+bool DLL_EXPORT JSContent::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+ContentPtr DLL_EXPORT JSContent::getPrivateObject(JSContextRef context, JSObjectRef object)
+{
+    if (!JSValueIsObjectOfClass(context, object, getClassRef())) {
+        LOGE("TypeMismatch");
+        throw TypeMismatchException("TypeMismatch");
+    }
+
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    return priv->ptr;
+}
+
+void DLL_EXPORT JSContent::setPrivateObject(JSObjectRef object, ContentPtr native)
+{
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Content's private object is NULL.");
+        throw TypeMismatchException("Content's private object is NULL.");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef DLL_EXPORT JSContent::CreateJSObject(JSContextRef context, ContentPtr native)
+{
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    if (!native) {
+        LOGE("Content's private object is NULL.");
+        throw TypeMismatchException("Content's private object is NULL.");
+    }
+
+    ContentHolder* priv = new(std::nothrow) ContentHolder;
+    if (!priv) {
+        LOGE("Can not be allocated memory");
+        throw UnknownException("Can not be allocated memory");
+    }
+
+    priv->ptr = native;
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+const JSClassDefinition* JSContent::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSContent::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContent::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSContent::getEditableAttributes(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getEditableAttributes());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getId());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getName());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContent::setName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        if (!JSValueIsUndefined(context, value)
+                && !JSValueIsNull(context, value)) {
+            std::string val = JSUtil::JSValueToString(context, value);
+            priv->setName(val);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSContent::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getType());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getMimeType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getMimeType());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getTitle(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getTitle());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getContentURI());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getThumbnailUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getThumbnailURIs());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getReleaseDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::makeDateObject(context, priv->getReleaseDate());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getModifiedDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::makeDateObject(context, priv->getModifiedDate());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getSize(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getSize());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContent::getDescription(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getDescription());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContent::setDescription(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        priv->setDescription(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSContent::getRating(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getRating());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContent::setRating(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        if(!JSValueIsUndefined(context, value) && !JSValueIsNull(context, value)){
+            priv->setRating(JSUtil::JSValueToLong(context, value));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSContent::getIsFavorite(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getIsFavorite());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSContent::setIsFavorite(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentPtr priv = JSContent::getPrivateObject(context, object);
+        priv->setIsFavorite(JSUtil::JSValueToBoolean(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/JSContent.h b/src/Content/JSContent.h
new file mode 100755 (executable)
index 0000000..57fad65
--- /dev/null
@@ -0,0 +1,168 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_CONTENT_H__
+#define __TIZEN_JS_CONTENT_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "Content.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class JSContent
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static ContentPtr getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSObjectRef object, ContentPtr native);
+    static JSObjectRef CreateJSObject(JSContextRef context, ContentPtr native);
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getEditableAttributes(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMimeType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTitle(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getThumbnailUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getReleaseDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getModifiedDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getSize(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDescription(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setDescription(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getRating(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setRating(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getIsFavorite(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setIsFavorite(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Content/JSContentDirectory.cpp b/src/Content/JSContentDirectory.cpp
new file mode 100755 (executable)
index 0000000..c0995b7
--- /dev/null
@@ -0,0 +1,249 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+
+#include "JSContentDirectory.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Content {
+
+using namespace DeviceAPI::Common;
+
+struct DirectoryHolder{
+    ContentDirectoryPtr ptr;
+};
+
+JSClassDefinition JSContentDirectory::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        "ContentDirectory",
+        NULL, //ParentClass
+        m_property, //StaticValues
+        NULL, //StaticFunctions
+        initialize, //Initialize
+        finalize, //Finalize
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL //ConvertToType
+};
+
+JSStaticValue JSContentDirectory::m_property[] = {
+        { CONTENT_DIRECTORY_ID, getId, NULL, kJSPropertyAttributeReadOnly },
+        { CONTENT_DIRECTORY_DIRECTORY_URI, getDirectory, NULL, kJSPropertyAttributeReadOnly },
+        { CONTENT_DIRECTORY_TITLE, getTitle, NULL, kJSPropertyAttributeReadOnly },
+        { CONTENT_DIRECTORY_STORAGE_TYPE, getStorageType, NULL, kJSPropertyAttributeReadOnly },
+        { CONTENT_DIRECTORY_MODIFIED_DATE, getModifiedDate, NULL, kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+JSClassRef JSContentDirectory::m_jsClassRef = JSClassCreate(JSContentDirectory::getClassInfo());
+
+const JSClassRef JSContentDirectory::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSContentDirectory::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSContentDirectory::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSContentDirectory::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    DirectoryHolder* priv = static_cast<DirectoryHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef JSContentDirectory::CreateJSObject(JSContextRef context,  ContentDirectoryPtr native)
+{
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    if (!native) {
+        LOGE("ContentDirectory's private object is NULL.");
+        throw TypeMismatchException("ContentDirectory's private object is NULL.");
+    }
+
+    DirectoryHolder* priv = new(std::nothrow) DirectoryHolder;
+    if (!priv) {
+        LOGE("Can not be allocated memory");
+        throw UnknownException("Can not be allocated memory");
+    }
+
+    priv->ptr = native;
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+ContentDirectoryPtr JSContentDirectory::getPrivateObject(JSContextRef context, JSObjectRef object)
+{
+    if (!JSValueIsObjectOfClass(context, object, getClassRef())) {
+        LOGE("TypeMismatch");
+        throw TypeMismatchException("TypeMismatch");
+    }
+
+    DirectoryHolder* priv = static_cast<DirectoryHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    return std::static_pointer_cast<ContentDirectory>(priv->ptr);
+}
+
+void JSContentDirectory::setPrivateObject(JSObjectRef object, ContentDirectoryPtr native)
+{
+    DirectoryHolder* priv = static_cast<DirectoryHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("ContentDirectory's private object is NULL.");
+        throw TypeMismatchException("ContentDirectory's private object is NULL.");
+    }
+    priv->ptr = native;
+}
+
+JSValueRef JSContentDirectory::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentDirectoryPtr priv = JSContentDirectory::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getId());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContentDirectory::getDirectory(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentDirectoryPtr priv = JSContentDirectory::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getDirectoryURI());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContentDirectory::getTitle(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentDirectoryPtr priv = JSContentDirectory::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getTitle());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContentDirectory::getStorageType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentDirectoryPtr priv = JSContentDirectory::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getStorageType());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContentDirectory::getModifiedDate(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ContentDirectoryPtr priv = JSContentDirectory::getPrivateObject(context, object);
+        return JSUtil::makeDateObject(context,priv->getModifiedDate());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/JSContentDirectory.h b/src/Content/JSContentDirectory.h
new file mode 100755 (executable)
index 0000000..8376407
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_CONTENT_DIRECTORY_H__
+#define __TIZEN_JS_CONTENT_DIRECTORY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "ContentDirectory.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class JSContentDirectory
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef CreateJSObject(JSContextRef ctx,  ContentDirectoryPtr native);
+    static ContentDirectoryPtr getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSObjectRef object, ContentDirectoryPtr native);
+
+private:
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDirectory(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTitle(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getStorageType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getModifiedDate(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Content/JSContentManager.cpp b/src/Content/JSContentManager.cpp
new file mode 100755 (executable)
index 0000000..d9a481d
--- /dev/null
@@ -0,0 +1,724 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <Export.h>
+
+#include "plugin_config.h"
+#include "ContentCallback.h"
+
+#include "JSPlaylist.h"
+#include "JSContentManager.h"
+#include "JSContent.h"
+#include "JSImageContent.h"
+#include "JSVideoContent.h"
+#include "JSAudioContent.h"
+
+#include "Content.h"
+#include "ContentGetDirectoryCallback.h"
+#include "ContentScanFileCallback.h"
+#include "ContentFindCallback.h"
+#include "ContentUpdateBatchCallback.h"
+
+#include "ContentUtility.h"
+
+#include <AbstractFilter.h>
+#include <JSSortMode.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+std::map<JSObjectRef,ContentChangeCallbackPtr> JSContentManager::s_callback_map;
+
+JSClassDefinition JSContentManager::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        "ContentManager",
+        NULL, //ParentClass
+        NULL, //StaticValues
+        m_function, //StaticFunctions
+        initialize, //Initialize
+        finalize, //Finalize
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL //ConvertToType
+};
+
+JSStaticFunction JSContentManager::m_function[] = {
+        { CONTENT_MANAGER_API_UPDATE, update, kJSPropertyAttributeNone },
+        { CONTENT_MANAGER_API_UPDATE_BATCH, updateBatch, kJSPropertyAttributeNone },
+        { CONTENT_MANAGER_API_GET_DIRECTORIES, getDirectories, kJSPropertyAttributeNone },
+        { CONTENT_MANAGER_API_FIND, find, kJSPropertyAttributeNone },
+        { CONTENT_MANAGER_API_SCAN_FILE, scanFile, kJSPropertyAttributeNone },
+        { CONTENT_MANAGER_API_SET_CHANGE_LISTENER, setChangeListener, kJSPropertyAttributeNone },
+        { CONTENT_MANAGER_API_UNSET_CHANGE_LISTENER, unsetChangeListener, kJSPropertyAttributeNone },
+        { CONTENT_MANAGER_API_GET_PLAYLISTS, getPlaylists, kJSPropertyAttributeNone },
+        { CONTENT_MANAGER_API_CREATE_PLAYLIST, createPlaylist, kJSPropertyAttributeNone },
+        { CONTENT_MANAGER_API_REMOVE_PLAYLIST, removePlaylist, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+JSClassRef JSContentManager::m_jsClassRef = JSClassCreate(JSContentManager::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSContentManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSContentManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSContentManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+    JSObjectSetPrivate(object, static_cast<void*>(&(ContentManager::getInstance())));
+}
+
+void JSContentManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+JSValueRef JSContentManager::update(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(CONTENT_TIME_TRACER_SHOW);
+    try {
+        TIZEN_CHECK_ACCESS(context,
+                exception,
+                static_cast<void*>(&(ContentManager::getInstance())),
+                CONTENT_MANAGER_API_UPDATE);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // content
+        JSObjectRef contentObj = validator.toObject(0, JSContent::getClassRef());
+        ContentPtr content;
+
+        if(JSImageContent::isObjectOfClass(context,contentObj)){
+            content = JSImageContent::getPrivateObject(context,contentObj);
+        }else if(JSVideoContent::isObjectOfClass(context,contentObj)){
+            content = JSVideoContent::getPrivateObject(context,contentObj);
+        }else if(JSAudioContent::isObjectOfClass(context,contentObj)){
+            content = JSAudioContent::getPrivateObject(context,contentObj);
+        }else if(JSContent::isObjectOfClass(context,contentObj)){
+            content = JSContent::getPrivateObject(context,contentObj);
+        }
+
+        if (!content) {
+            throw TypeMismatchException("Content's private object is NULL.");
+        }
+
+        // perform
+        ContentManager::getInstance().update(content);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ContentManager.update().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSContentManager::updateBatch(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(CONTENT_TIME_TRACER_SHOW);
+    TIME_TRACER_ITEM_BEGIN(CONTENT_TT_UPDATE_BATCH_TOTAL, CONTENT_TIME_TRACER_SHOW);
+    ContentUpdateBatchCallback *callback = NULL;
+    try {
+
+        TIZEN_CHECK_ACCESS(context,
+                exception,
+                static_cast<void*>(&(ContentManager::getInstance())),
+                CONTENT_MANAGER_API_UPDATE_BATCH);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        ContentLst contents;
+
+        std::vector<JSValueRef> contentsRef = validator.toJSValueRefVector(0);
+
+        if(contentsRef.size() == 0){
+            LOGE("throwing TypeMismatchException: \"Content type mismatched.\"");
+            throw TypeMismatchException("Content type mismatched.");
+        }
+
+        for(unsigned int i=0; i < contentsRef.size(); i++){
+
+            ContentPtr contentPriv;
+            if(JSImageContent::isObjectOfClass(context,contentsRef[i])){
+                contentPriv = JSImageContent::getPrivateObject(context,JSUtil::JSValueToObject(context,contentsRef[i]));
+            }else if(JSVideoContent::isObjectOfClass(context,contentsRef[i])){
+                contentPriv = JSVideoContent::getPrivateObject(context,JSUtil::JSValueToObject(context,contentsRef[i]));
+            }else if(JSAudioContent::isObjectOfClass(context,contentsRef[i])){
+                contentPriv = JSAudioContent::getPrivateObject(context,JSUtil::JSValueToObject(context,contentsRef[i]));
+            }else if(JSContent::isObjectOfClass(context,contentsRef[i])){
+                contentPriv = JSContent::getPrivateObject(context,JSUtil::JSValueToObject(context,contentsRef[i]));
+            }
+
+            if(contentPriv){
+                contents.push_back(contentPriv);
+            }
+            else {
+                LOGE("throwing TypeMismatchException: \"Content type mismatched.\"");
+                throw TypeMismatchException("Content type mismatched.");
+            }
+        }
+
+        callback = new ContentUpdateBatchCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(1,true);
+        if (successCallbackObj) {
+            callback->setSuccessCallback(successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(2, true);
+
+        if (errorCallbackObj) {
+            callback->setErrorCallback(errorCallbackObj);
+        }
+
+        if(!contents.empty()){
+            callback->setContents(contents);
+        }
+
+        // perform
+        ContentManager::getInstance().updateBatch(callback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ContentManager.updateBatch().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSContentManager::getDirectories(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(CONTENT_TIME_TRACER_SHOW);
+    TIME_TRACER_ITEM_BEGIN(CONTENT_TT_GET_DIR_TOTAL, CONTENT_TIME_TRACER_SHOW);
+    ContentCallback *callback = NULL;
+    try {
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new ContentGetDirectoryCallback(GlobalContextManager::getInstance()->getGlobalContext(context));
+        JSObjectRef successCallbackObj = validator.toFunction(0);
+        if (successCallbackObj) {
+            callback->setSuccessCallback(successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(1, true);
+        if (errorCallbackObj) {
+            callback->setErrorCallback(errorCallbackObj);
+        }
+        // perform
+        ContentManager::getInstance().getDirectories(callback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ContentManager.getDirectories().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSContentManager::find(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(CONTENT_TIME_TRACER_SHOW);
+    TIME_TRACER_ITEM_BEGIN(CONTENT_TT_FIND_TOTAL, CONTENT_TIME_TRACER_SHOW);
+
+    ContentFindCallback *callback = NULL;
+    Tizen::AbstractFilterPtr filter;
+    Tizen::SortModePtr sortMode;
+    JSValueRef filterObj;
+    JSValueRef sortModeObj;
+
+    try {
+        TIZEN_CHECK_ACCESS(context,
+                exception,
+                static_cast<void*>(&(ContentManager::getInstance())),
+                CONTENT_MANAGER_API_FIND);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // successCallback
+        callback = new ContentFindCallback(GlobalContextManager::getInstance()->getGlobalContext(context));
+        JSObjectRef successCallbackObj = validator.toFunction(0);
+        if (successCallbackObj) {
+            callback->setSuccessCallback(successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(1, true);
+        if (errorCallbackObj) {
+            callback->setErrorCallback(errorCallbackObj);
+        }
+
+        // directoryId
+        std::string directoryId = validator.toString(2, true);
+
+        if(!directoryId.empty()){
+            if(directoryId != "null" ){
+                callback->setDirectoryId(directoryId);
+            }
+            else if(directoryId == "undefined"){
+                throw InvalidValuesException("directoryId is not valid.");
+            }
+        }
+
+        // filter
+        //filterObj = validator.toObject(3, true);
+        filterObj = validator.toJSValueRef(3, true);
+        if(!JSValueIsNull(context, filterObj)) {
+            filter = Tizen::AbstractFilter::getPrivateObject(context, filterObj);
+            LOGD("Set filter with type: %d", filter->getFilterType());
+        }
+
+        // sortMode
+        //sortModeObj = validator.toObject(4, true);
+        sortModeObj = validator.toJSValueRef(4, true);
+        if(!JSValueIsNull(context, sortModeObj)) {
+            sortMode = Tizen::JSSortMode::getPrivateObject(context, sortModeObj);
+            LOGD("Set sort mode: %d for attribute: %s", sortMode->getOrder(),
+                    sortMode->getAttributeName().c_str());
+        }
+
+        // count
+        if(argumentCount >= 6){
+            if(!JSValueIsNull(context, arguments[5])){
+                long count = validator.toLong(5, true, 0);
+                if( count >= 0L ){
+                    callback->setCount(count);
+                }
+                else{
+                    throw InvalidValuesException( "count should be positive.");
+                }
+            }
+        }
+
+        // offset
+        if(argumentCount >= 7){
+            long offset = validator.toLong(6, true);
+            if( offset >= 0L ){
+                callback->setOffset(offset);
+            }
+            else{
+                throw InvalidValuesException("offset should be positive.");
+            }
+        }
+    } catch (const InvalidValuesException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                err.getName(), err.getMessage());
+
+        callback->onError(errobj);
+
+        delete callback;
+        callback = NULL;
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ContentManager.find().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    try
+    {
+        //ContentFilterConverterFactory::ConverterType fConverter = ContentFilterConverterFactory::getConverter(context);
+        if(filterObj){
+            //filter = fConverter->toFilter(filterObj);
+            callback->setFilter(filter);
+        }
+
+        if(sortModeObj){
+            //sortMode = fConverter->toSortMode(sortModeObj);
+            callback->setSortMode(sortMode);
+        }
+        // perform
+        ContentManager::getInstance().find(callback);
+
+        return JSValueMakeUndefined(context);
+    //TODO: to be changed in the future
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ContentManager.find().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSContentManager::scanFile(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(CONTENT_TIME_TRACER_SHOW);
+    TIME_TRACER_ITEM_BEGIN(CONTENT_TT_SCAN_FILE_TOTAL, CONTENT_TIME_TRACER_SHOW);
+
+    ContentCallback *callback = NULL;
+
+    try {
+        TIZEN_CHECK_ACCESS(context,
+                exception,
+                static_cast<void*>(&(ContentManager::getInstance())),
+                CONTENT_MANAGER_API_SCAN_FILE);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // contentURI
+        if ( validator.isUndefined(0) || validator.isNull(0)) {
+            LOGE("File path is not valid.");
+            throw InvalidValuesException("File path is not valid.");
+        }
+
+        JSObjectRef successCallbackObj = validator.toFunction(1, true);
+        JSObjectRef errorCallbackObj = validator.toFunction(2, true);
+
+        std::string contentURI = validator.toString(0);
+        if(contentURI.empty()){
+            LOGE("File path is not valid.");
+            throw InvalidValuesException("File path is not valid.");
+        }
+
+        contentURI = ContentUtility::convertUriToPath(contentURI);
+
+        callback = new ContentScanFileCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context),contentURI);
+        // successCallback
+        if (successCallbackObj) {
+            callback->setSuccessCallback(successCallbackObj);
+        }
+        // errorCallback
+        if (errorCallbackObj) {
+            callback->setErrorCallback(errorCallbackObj);
+        }
+
+        // perform
+        ContentManager::getInstance().scanFile(callback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ContentManager.scanFile().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSContentManager::setChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(CONTENT_TIME_TRACER_SHOW);
+
+    try {
+
+        TIZEN_CHECK_ACCESS(context,
+                exception,
+                static_cast<void*>(&(ContentManager::getInstance())),
+                CONTENT_MANAGER_API_SET_CHANGE_LISTENER);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // changeCallback
+        JSObjectRef changeCallbackObj = validator.toCallbackObject(0,false,"oncontentadded","oncontentupdated","oncontentremoved",NULL);
+        ContentChangeCallbackPtr changeCallback =
+                ContentChangeCallbackPtr(new ContentChangeCallback(
+                        GlobalContextManager::getInstance()->getGlobalContext(context),
+                        changeCallbackObj));
+
+        ContentManager::getInstance().unsetChangeListener(s_callback_map[thisObject]);
+        s_callback_map[thisObject] = changeCallback;
+        // perform
+        if(!(ContentManager::getInstance().setChangeListener(changeCallback))){
+            throw DeviceAPI::Common::UnknownException( "Unknown exception is occured by platfrom");
+        }
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ContentManager.setChangeListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSContentManager::unsetChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(CONTENT_TIME_TRACER_SHOW);
+
+    try {
+        TIZEN_CHECK_ACCESS(context,
+                exception,
+                static_cast<void*>(&(ContentManager::getInstance())),
+                CONTENT_MANAGER_API_UNSET_CHANGE_LISTENER);
+
+        // perform
+        ContentManager::getInstance().unsetChangeListener(s_callback_map[thisObject]);
+
+        s_callback_map.erase(thisObject);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ContentManager.unsetChangeListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSContentManager::getPlaylists(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    PlaylistArraySuccessCallbackUserData* callback = NULL;
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContentManager::getInstance(),
+                CONTENT_MANAGER_API_GET_PLAYLISTS);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        JSContextRef g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) PlaylistArraySuccessCallbackUserData(g_ctx);
+        if(!callback) {
+            LOGE("Couldn't allocate callback - PlaylistArraySuccessCallbackUserData!");
+            throw UnknownException("Could not get playlists");
+        }
+
+        callback->setSuccessCallback(validator.toFunction(0));
+        callback->setErrorCallback(validator.toFunction(1, true));
+
+        ContentManager::getInstance().getPlaylists(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error in getPlaylists method");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContentManager::createPlaylist(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    CreatePlaylistCallbackUserData* callback = NULL;
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContentManager::getInstance(),
+                CONTENT_MANAGER_API_CREATE_PLAYLIST);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        JSContextRef g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) CreatePlaylistCallbackUserData(g_ctx);
+        if(!callback) {
+            LOGE("Couldn't allocate callback - CreatePlaylistCallbackUserData!");
+            throw UnknownException("Could not create playlist");
+        }
+
+        callback->setPlaylistName(validator.toString(0));
+        callback->setSuccessCallback(validator.toFunction(1));
+
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        JSObjectRef js_src_playlist = validator.toObject(3, true);
+        if (js_src_playlist != NULL) {
+            callback->setSourcePlaylist(
+                    JSPlaylist::getPrivateObject(context, js_src_playlist));
+        }
+
+        ContentManager::getInstance().createPlaylist(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error in createPlaylist");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSContentManager::removePlaylist(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    RemovePlaylistCallbackUserData* callback = NULL;
+
+    try {
+        TIZEN_CHECK_ACCESS(context, exception, &ContentManager::getInstance(),
+                CONTENT_MANAGER_API_REMOVE_PLAYLIST);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        JSContextRef g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) RemovePlaylistCallbackUserData(g_ctx);
+        if(!callback) {
+            LOGE("Couldn't allocate callback - RemovePlaylistCallbackUserData!");
+            throw UnknownException("Could not remove playlist");
+        }
+
+        callback->setPlaylistId(validator.toString(0));
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        ContentManager::getInstance().removePlaylist(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error in removePlaylist");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/JSContentManager.h b/src/Content/JSContentManager.h
new file mode 100644 (file)
index 0000000..f0865ed
--- /dev/null
@@ -0,0 +1,141 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_CONTENT_MANAGER_H__
+#define __TIZEN_JS_CONTENT_MANAGER_H__
+#include <map>
+#include <JavaScriptCore/JavaScript.h>
+#include "ContentManager.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class JSContentManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+
+    static std::map<JSObjectRef,ContentChangeCallbackPtr> s_callback_map;
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef update(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef updateBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getDirectories(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef find(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef scanFile(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getPlaylists(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef createPlaylist(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removePlaylist(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_JS_CONTENT_MANAGER_H__
diff --git a/src/Content/JSImageContent.cpp b/src/Content/JSImageContent.cpp
new file mode 100755 (executable)
index 0000000..af9d18d
--- /dev/null
@@ -0,0 +1,296 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <JSSimpleCoordinates.h>
+
+#include "plugin_config.h"
+
+#include "JSImageContent.h"
+#include "JSContent.h"
+
+//using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+JSClassDefinition JSImageContent::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        "ImageContent",
+        JSContent::getClassRef(), //ParentClass
+        m_property, //StaticValues
+        NULL, //StaticFunctions
+        initialize, //Initialize
+        finalize, //Finalize
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL //ConvertToType
+};
+
+JSStaticValue JSImageContent::m_property[] = {
+        { IMAGE_CONTENT_GEOLOCATION, getSimpleCoordinates, setSimpleCoordinates, kJSPropertyAttributeDontDelete },
+        { IMAGE_CONTENT_WIDTH, getWidth, NULL, kJSPropertyAttributeReadOnly },
+        { IMAGE_CONTENT_HEIGHT, getHeight, NULL, kJSPropertyAttributeReadOnly },
+        { IMAGE_CONTENT_ORIENTATION, getImageContentOrientation, setImageContentOrientation, kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+JSClassRef JSImageContent::m_jsClassRef = JSClassCreate(JSImageContent::getClassInfo());
+
+const JSClassRef JSImageContent::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSImageContent::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSImageContent::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSImageContent::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+bool JSImageContent::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+JSValueRef JSImageContent::CreateJSObject(JSContextRef context, ContentPtr native)
+{
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    if (!native) {
+        LOGE("ContentImage's private object is NULL.");
+        throw TypeMismatchException("ContentImage's private object is NULL.");
+    }
+
+    ContentHolder* priv = new (std::nothrow) ContentHolder;
+    if (!priv) {
+        LOGE("Can not be allocated memory");
+        throw UnknownException("Can not be allocated memory");
+    }
+
+    priv->ptr = native;
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+
+ImageContentPtr JSImageContent::getPrivateObject(JSContextRef context, JSObjectRef object)
+{
+    if (!JSValueIsObjectOfClass(context, object, getClassRef())) {
+        throw TypeMismatchException("TypeMismatch");
+    }
+
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    return std::static_pointer_cast<ImageContent>(priv->ptr);
+}
+
+void JSImageContent::setPrivateObject(JSObjectRef object, ImageContentPtr native)
+{
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("ImageContent's private object is NULL.");
+        throw TypeMismatchException("ImageContent's private object is NULL.");
+    }
+    priv->ptr = native;
+}
+
+
+JSValueRef JSImageContent::getSimpleCoordinates(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ImageContentPtr priv = JSImageContent::getPrivateObject(context, object);
+        if (priv->isGeolocationSet()) {
+            return JSSimpleCoordinates::makeJSObject(context,priv->getGeolocation());
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSImageContent::setSimpleCoordinates(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ImageContentPtr priv = JSImageContent::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unsetGeolocation();
+        }
+        else {
+            priv->setGeolocation(JSSimpleCoordinates::getPrivateObject(context, value));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSImageContent::getWidth(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ImageContentPtr priv = JSImageContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getWidth());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSImageContent::getHeight(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ImageContentPtr priv = JSImageContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getHeight());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSImageContent::setImageContentOrientation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ImageContentPtr priv = JSImageContent::getPrivateObject(context, object);
+        if (!JSValueIsNull(context, value)) {
+            std::string orientation = JSUtil::JSValueToString(context, value);
+            if (orientation != "NORMAL" && orientation != "FLIP_HORIZONTAL" &&
+                    orientation != "ROTATE_180" && orientation != "FLIP_VERTICAL" &&
+                    orientation != "TRANSPOSE" && orientation != "ROTATE_90" &&
+                    orientation != "TRANSVERSE" && orientation != "ROTATE_270"){
+                LOGE("Invalid orientation type");
+                throw TypeMismatchException("Invalid orientation type");
+            }
+
+            if ((priv->getOrientation()).compare(orientation) != 0 )
+            {
+                priv->setOrientation(orientation);
+            }
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSImageContent::getImageContentOrientation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ImageContentPtr priv = JSImageContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getOrientation());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/JSImageContent.h b/src/Content/JSImageContent.h
new file mode 100755 (executable)
index 0000000..eeee026
--- /dev/null
@@ -0,0 +1,107 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_IMAGE_CONTENT_H__
+#define __TIZEN_JS_IMAGE_CONTENT_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "ImageContent.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class JSImageContent
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+
+    static ImageContentPtr getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSObjectRef object, ImageContentPtr native);
+    static JSValueRef CreateJSObject(JSContextRef ctx, ContentPtr priv);
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getSimpleCoordinates(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setSimpleCoordinates(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getWidth(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getHeight(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setImageContentOrientation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getImageContentOrientation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Content/JSPlaylist.cpp b/src/Content/JSPlaylist.cpp
new file mode 100644 (file)
index 0000000..97982da
--- /dev/null
@@ -0,0 +1,723 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <SecurityExceptions.h>
+#include <TimeTracer.h>
+
+#include "AddBatchCallbackUserData.h"
+#include "Content.h"
+#include "ContentManager.h"
+#include "JSAudioContent.h"
+#include "JSContent.h"
+#include "JSPlaylist.h"
+#include "JSPlaylistItem.h"
+#include "MoveItemCallbackUserData.h"
+#include "PlaylistContentCallback.h"
+#include "Playlist.h"
+#include "PlaylistUtils.h"
+#include "plugin_config.h"
+#include "RemoveBatchCallbackUserData.h"
+#include "SetItemsOrderCallbackUserData.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+namespace {
+const char* PLAYLIST_PROPERTY_ID = "id";
+const char* PLAYLIST_PROPERTY_NAME = "name";
+const char* PLAYLIST_PROPERTY_NUMBER_OF_TRACKS = "numberOfTracks";
+const char* PLAYLIST_PROPERTY_THUMBNAIL_URI = "thumbnailURI";
+}
+
+JSClassRef JSPlaylist::m_js_class_ref = NULL;
+
+JSClassDefinition JSPlaylist::m_class_info = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_PLAYLIST_PLAYLIST_INTERFACE,
+        NULL,
+        JSPlaylist::m_property,
+        JSPlaylist::m_function,
+        JSPlaylist::initialize,
+        JSPlaylist::finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //callAsFunction,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+
+JSStaticValue JSPlaylist::m_property[] = {
+        { PLAYLIST_PROPERTY_ID , getPlaylistId, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { PLAYLIST_PROPERTY_NAME , getName, setName,
+                kJSPropertyAttributeDontDelete },
+        { PLAYLIST_PROPERTY_NUMBER_OF_TRACKS , getNumberOfTracks, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { PLAYLIST_PROPERTY_THUMBNAIL_URI , getThumbnailURI, setThumbnailURI,
+                kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 } };
+
+JSStaticFunction JSPlaylist::m_function[] = {
+        { PLAYLIST_FUNCTION_API_ADD, add, kJSPropertyAttributeNone },
+        { PLAYLIST_FUNCTION_API_ADD_BATCH, addBatch, kJSPropertyAttributeNone },
+        { PLAYLIST_FUNCTION_API_REMOVE, remove, kJSPropertyAttributeNone },
+        { PLAYLIST_FUNCTION_API_REMOVE_BATCH, removeBatch, kJSPropertyAttributeNone },
+        { PLAYLIST_FUNCTION_API_GET_ITEMS, get, kJSPropertyAttributeNone },
+        { PLAYLIST_FUNCTION_API_MOVE_ITEM, move, kJSPropertyAttributeNone },
+        { PLAYLIST_FUNCTION_API_SET_ITEMS_ORDER, setOrder, kJSPropertyAttributeNone },
+        { 0, 0, 0 } };
+
+const JSClassDefinition* JSPlaylist::getClassInfo()
+{
+    LOGD("Entered");
+    return &(m_class_info);
+}
+
+const JSClassRef DLL_EXPORT JSPlaylist::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_js_class_ref) {
+        m_js_class_ref = JSClassCreate(&m_class_info);
+    }
+    return m_js_class_ref;
+}
+
+void JSPlaylist::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSPlaylist::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+
+    PlaylistHolder* priv = static_cast<PlaylistHolder*>(JSObjectGetPrivate(object));
+    if(priv) {
+        JSObjectSetPrivate(object,NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+PlaylistPtr JSPlaylist::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if(!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+
+    PlaylistHolder* priv = static_cast<PlaylistHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSPlaylist::setPrivateObject(JSObjectRef object, PlaylistPtr playlist)
+{
+    if (!playlist) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    PlaylistHolder* priv = static_cast<PlaylistHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = playlist;
+    }
+    else {
+        priv = new(std::nothrow) PlaylistHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = playlist;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in Playlist");
+            throw UnknownException("Failed to set Playlist private data");
+        }
+    }
+}
+
+JSObjectRef JSPlaylist::makeJSObject(JSContextRef context,
+        PlaylistPtr playlist)
+{
+    if (!playlist) {
+        LOGE("NULL pointer to playlist given");
+        throw UnknownException("NULL pointer to playlist given");
+    }
+
+    PlaylistHolder* priv = new(std::nothrow) PlaylistHolder();
+    if (!priv) {
+        LOGW("Failed to allocate memory for PlaylistHolder");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = playlist;
+    priv->ptr->copyAceCheckAccessFunction(ContentManager::getInstance());
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
+        LOGE("Failed to set private in Playlist");
+        delete priv;
+        priv = NULL;
+        throw UnknownException("Private data not set");
+    }
+    return obj;
+}
+
+JSObjectRef JSPlaylist::playlistsVectorToJSObjectArray(JSContextRef context,
+        const PlaylistPtrVec& playlists)
+{
+    const size_t count = playlists.size();
+
+    JSObjectRef array[count];
+    for (size_t i = 0; i < count; i++) {
+        array[i] = JSPlaylist::makeJSObject(context, playlists[i]);
+    }
+    JSObjectRef result = JSObjectMakeArray(context, count,
+            count > 0 ? array : NULL, NULL);
+    if (!result) {
+        LOGE("Failed to create Playlists array");
+        throw UnknownException("Playlists array is null");
+    }
+
+    return result;
+}
+
+JSValueRef JSPlaylist::getPlaylistId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSPlaylist::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, std::to_string(priv->getId()));
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get playlist id. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting playlist id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPlaylist::getName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSPlaylist::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getName());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get playlist name. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting playlist name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSPlaylist::setName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSPlaylist::getPrivateObject(context, object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                PLAYLIST_FUNCTION_API_SET_NAME);
+
+        priv->setName(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to set playlist name. %s : %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch(...) {
+        LOGE("Failed to set playlist name. Unknown exception caught");
+
+        Common::UnknownException err("Could not set playlist name.");
+        JSWebAPIErrorFactory::postException(context, exception, err);
+
+    }
+    return true;
+}
+
+JSValueRef JSPlaylist::getNumberOfTracks(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSPlaylist::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getNumberOfTracks());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get number of tracks in playlist. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting number of tracks in playlist.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPlaylist::getThumbnailURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSPlaylist::getPrivateObject(context, object);
+        std::string uri = priv->getThumbnailURI();
+        if (uri.empty() || uri == " ") {
+            return JSValueMakeNull(context);
+        }
+        return JSUtil::toJSValueRef(context, uri);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get playlist thumbnail URI. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting playlist thumbnail URI.");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSPlaylist::setThumbnailURI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSPlaylist::getPrivateObject(context, object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                PLAYLIST_FUNCTION_API_SET_THUMBNAIL_URI);
+
+        if(JSValueIsNull(context, value)) {
+            priv->setThumbnailURI(std::string());
+        } else {
+            priv->setThumbnailURI(JSUtil::JSValueToString(context, value));
+        }
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to set playlist thumbnail URI. %s : %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch(...) {
+        LOGE("Failed to set playlist thumbnail URI. Unknown exception caught");
+
+        Common::UnknownException err("Could not set playlist thumbnail URI.");
+        JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return true;
+}
+
+JSValueRef JSPlaylist::add(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        PlaylistPtr priv = JSPlaylist::getPrivateObject(context, this_object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                PLAYLIST_FUNCTION_API_ADD);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        JSObjectRef content_obj = validator.toObject(0);
+        AudioContentPtr audio_content = getAudioContentPtrFromJSObjectRef(context,
+                content_obj);
+
+        priv->add(audio_content);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error in add method");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPlaylist::addBatch(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+    AddBatchCallbackUserData* callback = NULL;
+
+    try {
+        PlaylistPtr priv = JSPlaylist::getPrivateObject(context, this_object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                PLAYLIST_FUNCTION_API_ADD_BATCH);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        std::vector<ContentPtr> content_item_vector;
+        std::vector<JSValueRef> items = validator.toJSValueRefVector(0);
+        const size_t size = items.size();
+
+        for(unsigned int i = 0; i < size; ++i) {
+            AudioContentPtr audio_content = getAudioContentPtrFromJSObjectRef(context,
+                    JSUtil::JSValueToObject(context, items[i]));
+            content_item_vector.push_back(audio_content);
+        }
+
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new AddBatchCallbackUserData(g_ctx, content_item_vector, priv);
+        if (!callback) {
+            LOGE("Failed to create callback data.");
+            throw UnknownException("Failed to create callback data.");
+        }
+
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        priv->addBatch(callback);
+    }
+    catch (const BasePlatformException& err) {
+        delete callback;
+        callback = NULL;
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        delete callback;
+        callback = NULL;
+        Common::UnknownException err("Unknown error in addBatch method");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPlaylist::remove(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        PlaylistPtr priv = JSPlaylist::getPrivateObject(context, this_object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                PLAYLIST_FUNCTION_API_REMOVE);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+        JSObjectRef item_js_obj = validator.toObject(0);
+        PlaylistItemPtr item = JSPlaylistItem::getPrivateObject(context, item_js_obj);
+        priv->remove(item);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error in remove method");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPlaylist::removeBatch(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+    RemoveBatchCallbackUserData* callback = NULL;
+
+    try {
+        PlaylistPtr priv = JSPlaylist::getPrivateObject(context, this_object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                PLAYLIST_FUNCTION_API_REMOVE_BATCH);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        std::vector<PlaylistItemPtr> items;
+        std::vector<JSValueRef> js_items = validator.toJSValueRefVector(0);
+        const size_t size = js_items.size();
+
+        for(unsigned int i = 0; i < size; ++i) {
+            JSObjectRef js_item = JSUtil::JSValueToObject(context, js_items[i]);
+            PlaylistItemPtr item = JSPlaylistItem::getPrivateObject(context, js_item);
+            items.push_back(item);
+        }
+
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new RemoveBatchCallbackUserData(g_ctx, items, priv);
+        if (!callback) {
+            LOGE("Failed to create callback data.");
+            throw UnknownException("Failed to create callback data.");
+        }
+
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        priv->removeBatch(callback);
+    }
+    catch (const BasePlatformException& err) {
+        delete callback;
+        callback = NULL;
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        delete callback;
+        callback = NULL;
+        Common::UnknownException err("Unknown error in removeBatch method");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPlaylist::get(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+    PlaylistContentCallback* callback = NULL;
+
+    try {
+        PlaylistPtr priv = JSPlaylist::getPrivateObject(context, this_object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                PLAYLIST_FUNCTION_API_GET_ITEMS);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) PlaylistContentCallback(g_ctx, priv);
+        if(!callback) {
+            LOGE("Couldn't allocate PlaylistContentCallback!");
+            throw UnknownException("Could not get playlist items");
+        }
+
+        //void get(PlaylistItemArraySuccessCallback successCallback,
+        //         optional ErrorCallback? errorCallback,
+        //         optional long? count,
+        //         optional long? offset);
+
+        callback->setSuccessCallback(validator.toFunction(0));
+        callback->setErrorCallback(validator.toFunction(1, true));
+
+        //count
+        if(!validator.isOmitted(2)) {
+            callback->setCount(validator.toLong(2, true));
+        }
+
+        //offset
+        if(!validator.isOmitted(3)) {
+            callback->setOffset(validator.toLong(3, true));
+        }
+
+        priv->get(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error in getItems method");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPlaylist::move(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+    MoveItemCallbackUserData* callback = NULL;
+
+    try {
+        PlaylistPtr priv = JSPlaylist::getPrivateObject(context, this_object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                PLAYLIST_FUNCTION_API_MOVE_ITEM);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        JSObjectRef content_obj = validator.toObject(0);
+        PlaylistItemPtr item = getPlaylistItemFromJSObjectRef(context, content_obj);
+
+        long delta = validator.toLong(1);
+        LOGD("item with playlist_member_id:%d delta:%d", item->getPlaylistMemberId(),
+                delta);
+
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) MoveItemCallbackUserData(g_ctx, priv, item, delta);
+        if(!callback) {
+            LOGE("Couldn't allocate callback - MoveItemCallbackUserData!");
+            throw UnknownException("Could not move item");
+        }
+
+        callback->setSuccessCallback(validator.toFunction(2,true));
+        callback->setErrorCallback(validator.toFunction(3,true));
+
+        priv->move(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error in setOrder method");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPlaylist::setOrder(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+    SetItemsOrderCallbackUserData* callback = NULL;
+
+    try {
+        PlaylistPtr priv = JSPlaylist::getPrivateObject(context, this_object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                PLAYLIST_FUNCTION_API_SET_ITEMS_ORDER);
+
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        std::vector<JSValueRef> js_items = validator.toJSValueRefVector(0);
+        const size_t js_items_size = js_items.size();
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) SetItemsOrderCallbackUserData(g_ctx, priv);
+        if(!callback) {
+            LOGE("Couldn't allocate callback - SetItemsOrderCallbackUserData!");
+            throw UnknownException("Could not set items order");
+        }
+
+        PlaylistItemPtrVec& playlist_items = callback->getItems();
+        playlist_items.reserve(js_items_size);
+
+        for(unsigned int i = 0; i < js_items_size; ++i) {
+            auto item = getPlaylistItemFromJSObjectRef(context,
+                    JSUtil::JSValueToObject(context, js_items[i]));
+            playlist_items.push_back(item);
+        }
+
+        callback->setSuccessCallback(validator.toFunction(1,true));
+        callback->setErrorCallback(validator.toFunction(2,true));
+
+        priv->setOrder(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error in setOrder method");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/JSPlaylist.h b/src/Content/JSPlaylist.h
new file mode 100644 (file)
index 0000000..89bf8ac
--- /dev/null
@@ -0,0 +1,162 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_JS_PLAYLIST_H__
+#define __TIZEN_CONTENT_JS_PLAYLIST_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "Playlist.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class JSPlaylist
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static PlaylistPtr getPrivateObject(JSContextRef context, JSValueRef value);
+    static void setPrivateObject(JSObjectRef object, PlaylistPtr playlist);
+    static JSObjectRef makeJSObject(JSContextRef context, PlaylistPtr playlist);
+    static JSObjectRef playlistsVectorToJSObjectArray(JSContextRef context,
+            const PlaylistPtrVec& playlists);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    //------------------------------------------------------------------------------------
+    //Properties:
+
+    static JSValueRef getPlaylistId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static bool setName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getNumberOfTracks(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getThumbnailURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static bool setThumbnailURI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    //------------------------------------------------------------------------------------
+    //Methods:
+
+    static JSValueRef add(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef remove(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeBatch(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef get(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef move(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setOrder(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_class_info;
+
+    /**
+     * This member variable contains the initialization values for the static properties
+     * of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSClassRef m_js_class_ref;
+};
+
+} //namespace Content
+} //namespace DeviceAPI
+
+#endif // __TIZEN_CONTENT_JS_PLAYLIST_H__
diff --git a/src/Content/JSPlaylistItem.cpp b/src/Content/JSPlaylistItem.cpp
new file mode 100644 (file)
index 0000000..a258691
--- /dev/null
@@ -0,0 +1,236 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSPlaylistItem.h"
+
+#include <Export.h>
+#include <JSUtil.h>
+
+#include "ContentHelper.h"
+#include "ContentManager.h"
+#include "JSAudioContent.h"
+#include "JSContent.h"
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+namespace {
+const char* PLAYLISTITEM_PROPERTY_CONTENT = "content";
+}
+
+JSClassRef JSPlaylistItem::m_js_class_ref = NULL;
+
+JSClassDefinition JSPlaylistItem::m_class_info = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_PLAYLIST_PLAYLIST_ITEM_INTERFACE,
+    NULL,
+    JSPlaylistItem::m_property,
+    NULL, //function
+    JSPlaylistItem::initialize,
+    JSPlaylistItem::finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //constructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSPlaylistItem::m_property[] = {
+        { PLAYLISTITEM_PROPERTY_CONTENT , getContent, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 } };
+
+const JSClassDefinition* JSPlaylistItem::getClassInfo()
+{
+    LOGD("Entered");
+    return &(m_class_info);
+}
+
+const JSClassRef DLL_EXPORT JSPlaylistItem::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_js_class_ref) {
+        m_js_class_ref = JSClassCreate(&m_class_info);
+    }
+    return m_js_class_ref;
+}
+
+void JSPlaylistItem::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSPlaylistItem::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+
+    PlaylistItemHolder* priv =
+            static_cast<PlaylistItemHolder*>(JSObjectGetPrivate(object));
+    if(priv) {
+        JSObjectSetPrivate(object,NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+bool JSPlaylistItem::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+PlaylistItemPtr JSPlaylistItem::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if(!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+
+    PlaylistItemHolder* priv =
+            static_cast<PlaylistItemHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSPlaylistItem::setPrivateObject(JSObjectRef object, PlaylistItemPtr item)
+{
+    if (!item) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    PlaylistItemHolder* priv =
+            static_cast<PlaylistItemHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = item;
+    }
+    else {
+        priv = new(std::nothrow) PlaylistItemHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = item;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in PlaylistItem");
+            throw UnknownException("Failed to set PlaylistItem private data");
+        }
+    }
+}
+
+JSObjectRef JSPlaylistItem::makeJSObject(JSContextRef context,
+        PlaylistItemPtr item)
+{
+    if (!item) {
+        LOGE("NULL pointer to playlist item given");
+        throw UnknownException("NULL pointer to playlist item given");
+    }
+
+    PlaylistItemHolder* priv = new(std::nothrow) PlaylistItemHolder();
+    if (!priv) {
+        LOGW("Failed to allocate memory for PlaylistItemHolder");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = item;
+    priv->ptr->copyAceCheckAccessFunction(ContentManager::getInstance());
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
+        LOGE("Failed to set private in PlaylistIem");
+        delete priv;
+        priv = NULL;
+        throw UnknownException("Private data not set");
+    }
+    return obj;
+}
+
+JSObjectRef JSPlaylistItem::playlistItemsVectorToJSObjectArray(JSContextRef context,
+            const PlaylistItemPtrVec& items)
+{
+    const size_t count = items.size();
+
+    JSObjectRef array[count];
+    for (size_t i = 0; i < count; i++) {
+        array[i] = JSPlaylistItem::makeJSObject(context, items[i]);
+    }
+    JSObjectRef result = JSObjectMakeArray(context, count,
+            count > 0 ? array : NULL, NULL);
+    if (!result) {
+        LOGE("Failed to create PlaylistItems array");
+        throw UnknownException("PlaylistItems array is null");
+    }
+
+    return result;
+}
+
+
+JSValueRef JSPlaylistItem::getContent(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSPlaylistItem::getPrivateObject(context, object);
+
+        AudioContentPtr content = priv->getAudioContent();
+        if(!content) {
+            //Lazy loading pattern
+
+            if(!priv->getMediaInfoHandle()) {
+                LOGE("getMediaInfoHandle() returned NULL");
+                throw UnknownException("Could not get details of Playlist item");
+            }
+
+            content = AudioContentPtr(new AudioContent());
+            ContentHelper::loadAudioContentFromPlatform(priv->getMediaInfoHandle(),
+                    content);
+            priv->setAudioContent(content);
+        }
+
+        return JSAudioContent::CreateJSObject(context, content);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get playlist id. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting playlist id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/JSPlaylistItem.h b/src/Content/JSPlaylistItem.h
new file mode 100644 (file)
index 0000000..b141ffd
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_JS_PLAYLIST_ITEM_H__
+#define __TIZEN_CONTENT_JS_PLAYLIST_ITEM_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "PlaylistItem.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class JSPlaylistItem
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+    static PlaylistItemPtr getPrivateObject(JSContextRef context, JSValueRef value);
+    static void setPrivateObject(JSObjectRef object, PlaylistItemPtr item);
+    static JSObjectRef makeJSObject(JSContextRef context, PlaylistItemPtr item);
+    static JSObjectRef playlistItemsVectorToJSObjectArray(JSContextRef context,
+            const PlaylistItemPtrVec& items);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    //------------------------------------------------------------------------------------
+    //Properties:
+    static JSValueRef getContent(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_class_info;
+
+    /**
+     * This member variable contains the initialization values for the static properties
+     * of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_js_class_ref;
+};
+
+} //namespace Content
+} //namespace DeviceAPI
+
+#endif // __TIZEN_CONTENT_JS_PLAYLIST_ITEM_H__
diff --git a/src/Content/JSVideoContent.cpp b/src/Content/JSVideoContent.cpp
new file mode 100755 (executable)
index 0000000..600421b
--- /dev/null
@@ -0,0 +1,302 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <JSSimpleCoordinates.h>
+
+#include "plugin_config.h"
+
+#include "JSVideoContent.h"
+#include "JSContent.h"
+
+
+//using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+JSClassDefinition JSVideoContent::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        "VideoContent",
+        JSContent::getClassRef(), //ParentClass
+        m_property,//StaticValues
+        NULL, //StaticFunctions
+        initialize, //Initialize
+        finalize, //Finalize
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL //ConvertToType
+};
+
+JSStaticValue JSVideoContent::m_property[] = {
+        { VIDEO_CONTENT_GEOLOCATION, getGeolocation, setGeolocation, kJSPropertyAttributeDontDelete },
+        { VIDEO_CONTENT_ALBUM, getAlbum, NULL, kJSPropertyAttributeReadOnly },
+        { VIDEO_CONTENT_ARTISTS, getArtists, NULL, kJSPropertyAttributeReadOnly },
+        { VIDEO_CONTENT_DURATION, getDuration, NULL, kJSPropertyAttributeReadOnly },
+        { VIDEO_CONTENT_WIDTH, getWidth, NULL, kJSPropertyAttributeReadOnly },
+        { VIDEO_CONTENT_HEIGHT, getHeight, NULL, kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+JSClassRef JSVideoContent::m_jsClassRef = JSClassCreate(JSVideoContent::getClassInfo());
+
+const JSClassRef JSVideoContent::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSVideoContent::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSVideoContent::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSVideoContent::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+VideoContentPtr JSVideoContent::getPrivateObject(JSContextRef context, JSObjectRef object)
+{
+    if (!JSValueIsObjectOfClass(context, object, getClassRef())) {
+        LOGE("Type Mismatch");
+        throw TypeMismatchException("TypeMismatch");
+    }
+
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    return std::static_pointer_cast<VideoContent>(priv->ptr);
+}
+
+void JSVideoContent::setPrivateObject(JSObjectRef object, ContentPtr native)
+{
+    ContentHolder* priv = static_cast<ContentHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("VideoContent's private object is NULL.");
+        throw TypeMismatchException("VideoContent's private object is NULL.");
+    }
+    priv->ptr = native;
+}
+
+bool JSVideoContent::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+JSValueRef JSVideoContent::CreateJSObject(JSContextRef context, ContentPtr native){
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    if (!native) {
+        LOGE("ContentVideo's private object is NULL.");
+        throw TypeMismatchException("ContentVideo's private object is NULL.");
+    }
+
+    ContentHolder* priv = new(std::nothrow) ContentHolder;
+    if (!priv) {
+        LOGE("Can not be allocated memory");
+        throw UnknownException("Can not be allocated memory");
+    }
+
+    priv->ptr = native;
+    JSObjectSetPrivate(obj, static_cast<void*>(priv));
+    return obj;
+}
+
+JSValueRef JSVideoContent::getGeolocation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        VideoContentPtr priv = JSVideoContent::getPrivateObject(context, object);
+        if (priv->isGeolocationSet()) {
+            return JSSimpleCoordinates::makeJSObject(context,priv->getGeolocation());
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSVideoContent::setGeolocation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        VideoContentPtr priv = JSVideoContent::getPrivateObject(context, object);
+
+        if (JSValueIsNull(context, value)) {
+            priv->unsetGeolocation();
+        }
+        else {
+            priv->setGeolocation(JSSimpleCoordinates::getPrivateObject(context, value));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSVideoContent::getAlbum(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        VideoContentPtr priv = JSVideoContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getAlbum());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSVideoContent::getArtists(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        VideoContentPtr priv = JSVideoContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getArtists());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSVideoContent::getDuration(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        VideoContentPtr priv = JSVideoContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getDuration());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSVideoContent::getWidth(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        VideoContentPtr priv = JSVideoContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getWidth());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSVideoContent::getHeight(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        VideoContentPtr priv = JSVideoContent::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getHeight());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/JSVideoContent.h b/src/Content/JSVideoContent.h
new file mode 100755 (executable)
index 0000000..9c695f6
--- /dev/null
@@ -0,0 +1,110 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_VIDEO_CONTENT_H__
+#define __TIZEN_JS_VIDEO_CONTENT_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "VideoContent.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class JSVideoContent
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static VideoContentPtr getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSObjectRef object, ContentPtr native);
+
+    static JSValueRef CreateJSObject(JSContextRef ctx, ContentPtr priv);
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getGeolocation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setGeolocation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getAlbum(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getArtists(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDuration(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getWidth(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getHeight(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Content/MoveItemCallbackUserData.cpp b/src/Content/MoveItemCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..a9356f4
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MoveItemCallbackUserData.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+MoveItemCallbackUserData::MoveItemCallbackUserData(JSContextRef global_ctx,
+        PlaylistPtr playlist, PlaylistItemPtr item, int delta) :
+                BaseCallbackUserData(global_ctx),
+                m_playlist(playlist),
+                m_item(item),
+                m_delta(delta)
+{
+}
+
+MoveItemCallbackUserData::~MoveItemCallbackUserData()
+{
+}
+
+PlaylistPtr MoveItemCallbackUserData::getPlaylist() const
+{
+    return m_playlist;
+}
+
+PlaylistItemPtr MoveItemCallbackUserData::getItem() const
+{
+    return m_item;
+}
+
+int MoveItemCallbackUserData::getDelta() const
+{
+    return m_delta;
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/MoveItemCallbackUserData.h b/src/Content/MoveItemCallbackUserData.h
new file mode 100644 (file)
index 0000000..ce5aed6
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CONTENT_MOVE_ITEM_CALLBACK_USER_DATA_H_
+#define _TIZEN_CONTENT_MOVE_ITEM_CALLBACK_USER_DATA_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <memory>
+
+#include "BaseCallbackUserData.h"
+#include "PlaylistItem.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class Playlist;
+typedef std::shared_ptr<Playlist> PlaylistPtr;
+
+class MoveItemCallbackUserData: public BaseCallbackUserData {
+
+public:
+    MoveItemCallbackUserData(JSContextRef globalCtx, PlaylistPtr playlist,
+            PlaylistItemPtr item, int delta);
+    virtual ~MoveItemCallbackUserData();
+
+    PlaylistPtr getPlaylist() const;
+    PlaylistItemPtr getItem() const;
+    int getDelta() const;
+
+private:
+    PlaylistPtr m_playlist;
+    PlaylistItemPtr m_item;
+    int m_delta;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif /* _TIZEN_CONTENT_MOVE_ITEM_CALLBACK_USER_DATA_H_ */
diff --git a/src/Content/Playlist.cpp b/src/Content/Playlist.cpp
new file mode 100644 (file)
index 0000000..3abe0f1
--- /dev/null
@@ -0,0 +1,1056 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "Playlist.h"
+
+#include <set>
+
+#include <FilesystemPathUtils.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+#include <Node.h>
+#include <Path.h>
+#include <PlatformException.h>
+
+#include "GetPlaylistItemsRequest.h"
+#include "JSPlaylistItem.h"
+#include "PlaylistItem.h"
+#include "PlaylistUtils.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+namespace {
+static const std::string uri_prefix = "file://";
+static const std::string uri_absolute_prefix = "file:///";
+}
+
+typedef struct {
+    media_playlist_h handle;
+    bool is_error;
+} RemoveMediaHolder;
+
+Playlist::Playlist(const int playlist_id) :
+            SecurityAccessor(),
+            m_id(playlist_id)
+{
+}
+
+Playlist::~Playlist()
+{
+}
+
+int Playlist::getId() const
+{
+    return m_id;
+}
+
+std::string Playlist::getName()
+{
+    LOGD("Entered");
+    media_playlist_h playlist_handle = getPlaylistHandle();
+
+    char* tmp_playlist_name = NULL;
+    const int ret_code = media_playlist_get_name(playlist_handle, &tmp_playlist_name);
+
+    std::string playlist_name;
+    if(tmp_playlist_name) {
+        playlist_name = tmp_playlist_name;
+        free(tmp_playlist_name);
+        tmp_playlist_name = NULL;
+    }
+
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("ret : %d", ret_code);
+        destroyMediaPlaylistHandle(playlist_handle);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_get_name()");
+    }
+
+    destroyMediaPlaylistHandle(playlist_handle);
+    return playlist_name;
+}
+
+void Playlist::setName(const std::string& name)
+{
+    LOGD("Entered");
+    if(name.empty()) {
+        LOGE("Cannot set empty playlist name!");
+        throw InvalidValuesException("Playlist name cannot be empty");
+    }
+
+    media_playlist_h playlist_handle = getPlaylistHandle();
+
+    const int ret_code = media_playlist_set_name(playlist_handle, name.c_str());
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("ret : %d", ret_code);
+
+        //Setting name that is used by other playlist does not return bad error code here.
+        //MEDIA_CONTENT_ERROR_INVALID_OPERATION is being returned in updatePlaylistInDB
+        destroyMediaPlaylistHandle(playlist_handle);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_set_name()");
+    }
+
+    try {
+        updatePlaylistInDB(playlist_handle);
+    }
+    catch (PlaylistUnknownException& exc) {
+        if(exc.getCoreAPIError() == MEDIA_CONTENT_ERROR_INVALID_OPERATION) {
+            //We could fetch list of playlists and check if other playlist is using this
+            //name, but that seems to be to much work in synchronous method
+            //
+            LOGE("Playlist name: %s is probably already used", name.c_str());
+            throw InvalidValuesException("Playlist name is already used");
+        }
+    }
+
+    destroyMediaPlaylistHandle(playlist_handle);
+}
+
+unsigned long Playlist::getNumberOfTracks()
+{
+    LOGD("Entered");
+    int media_count = 0;
+    const int ret_code = media_playlist_get_media_count_from_db(m_id, NULL,
+            &media_count);
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("ret : %d", ret_code);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_get_media_count_from_db()");
+    }
+
+    return media_count;
+}
+
+std::string Playlist::getThumbnailURI()
+{
+    LOGD("Entered");
+    media_playlist_h playlist_handle = getPlaylistHandle();
+
+    char* tmp_playlist_thb_path = NULL;
+    const int ret_code = media_playlist_get_thumbnail_path(playlist_handle,
+            &tmp_playlist_thb_path);
+    LOGD("ret_code: %d tmp_playlist_thb_path:%s", ret_code, tmp_playlist_thb_path);
+
+    std::string playlist_thb_path;
+    if(tmp_playlist_thb_path) {
+        playlist_thb_path = tmp_playlist_thb_path;
+        free(tmp_playlist_thb_path);
+        tmp_playlist_thb_path = NULL;
+    }
+
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("ret : %d", ret_code);
+        destroyMediaPlaylistHandle(playlist_handle);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_get_thumbnail_path()");
+    }
+
+    destroyMediaPlaylistHandle(playlist_handle);
+
+    //If thumbnail path is empty or temporary fix " " then return
+    //empty string without file:///
+    //
+    if(playlist_thb_path.empty() || " " == playlist_thb_path) {
+        return playlist_thb_path;
+    }
+
+    return uri_prefix + playlist_thb_path;
+}
+
+void Playlist::setThumbnailURI(const std::string& thb_uri)
+{
+    LOGD("Entered");
+
+    //Allow setting empty URI, unfortunately Core API does not allow to set empty
+    //path so we need to set one empty space. This is probably issue of Core API.
+    std::string absoulte_path = " ";
+
+    if(!thb_uri.empty()) {
+        if(thb_uri.find(uri_absolute_prefix) != 0) {
+            LOGE("thumbnail URI is not valid: [%s]", thb_uri.c_str());
+            throw InvalidValuesException("Thumbnail URI is not valid");
+        }
+
+        absoulte_path = thb_uri.substr(uri_prefix.length());
+        bool uri_is_pointing_at_file = false;
+        try {
+            Filesystem::PathPtr path = Filesystem::Path::create(absoulte_path);
+            Filesystem::NodePtr node = Filesystem::Node::resolve(path);
+            if(node->getType() == Filesystem::NT_FILE) {
+                uri_is_pointing_at_file = true;
+            }
+        }
+        catch (const BasePlatformException &err) {
+            LOGE("Couldn't resolve path: %s, got:%s (%s)", absoulte_path.c_str(),
+                    (err.getName()).c_str(), (err.getMessage()).c_str());
+        }
+        catch(...) {
+            LOGE("Couldn't resolve path: %s", absoulte_path.c_str());
+        }
+
+        if(!uri_is_pointing_at_file) {
+            LOGE("URI:%s is not poinintg at existing file", thb_uri.c_str());
+            throw InvalidValuesException("Thumbnail URI is not valid");
+        }
+    }
+
+    media_playlist_h playlist_handle = getPlaylistHandle();
+
+    const int ret_code = media_playlist_set_thumbnail_path(playlist_handle,
+            absoulte_path.c_str());
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("ret : %d", ret_code);
+        destroyMediaPlaylistHandle(playlist_handle);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_set_thumbnail_path()");
+    }
+
+    updatePlaylistInDB(playlist_handle);
+    destroyMediaPlaylistHandle(playlist_handle);
+}
+
+void Playlist::add(ContentPtr item)
+{
+    LOGD("Entered");
+    media_playlist_h playlist_handle = getPlaylistHandle();
+
+    const std::string& media_id = item->getId();
+    int ret_code = media_playlist_add_media(playlist_handle, media_id.c_str());
+    if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("ret : %d", ret_code);
+        destroyMediaPlaylistHandle(playlist_handle);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_add_media()");
+    }
+
+    updatePlaylistInDB(playlist_handle);
+    destroyMediaPlaylistHandle(playlist_handle);
+}
+
+gboolean Playlist::addBatchCompleteCB(void* data)
+{
+    LOGD("Entered");
+    AddBatchCallbackUserData* callback = NULL;
+
+    try {
+        callback = static_cast<AddBatchCallbackUserData*>(data);
+        if(!callback) {
+            LOGE("Callback is null");
+            return false;
+        }
+
+        JSContextRef context = callback->getContext();
+        if(!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("Context was closed");
+            delete callback;
+            callback = NULL;
+            return false;
+        }
+
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Error while calling addBatch callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Failed to call addBatch callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* Playlist::addBatchThread(void* data)
+{
+    LOGD("Entered");
+    AddBatchCallbackUserData* callback = NULL;
+    media_playlist_h playlist_handle = NULL;
+
+    try {
+        callback = static_cast<AddBatchCallbackUserData*>(data);
+        if (!callback) {
+            LOGE("Callback is null");
+            return NULL;
+        }
+
+        auto playlist = callback->getPlaylist();
+        playlist_handle = playlist->getPlaylistHandle();
+        const std::vector<ContentPtr>& content_items = callback->getItems();
+        std::size_t items_size = content_items.size();
+
+        for (size_t i = 0; i < items_size; ++i) {
+            std::string media_id = content_items[i]->getId();
+            int ret_code = media_playlist_add_media(playlist_handle, media_id.c_str());
+            if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
+                LOGE("ret : %d", ret_code);
+                ContentUtility::throwMediaContentException(ret_code, "media_playlist_add_media()");
+            }
+        }
+
+        playlist->updatePlaylistInDB(playlist_handle);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("addBatch failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "UnknownError.");
+    }
+
+    destroyMediaPlaylistHandle(playlist_handle);
+
+    if (!g_idle_add(addBatchCompleteCB, static_cast<void*>(callback))) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+void Playlist::addBatch(AddBatchCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, addBatchThread,
+            static_cast<void *>(callback))) {
+        LOGE("Failed to create pthread for addBatch()");
+        throw UnknownException("Could not run add batch task");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for addBatch()");
+    }
+}
+
+void Playlist::remove(PlaylistItemPtr item)
+{
+    LOGD("Entered");
+    if(item->getPlaylistId() != m_id) {
+        LOGE("Playlist item is not inside this playlist (playlist_id:%d != "
+                "current playlist id:%d)", item->getPlaylistId(), m_id);
+        throw UnknownException("Provided item is inside different playlist");
+    }
+
+    media_playlist_h playlist_handle = getPlaylistHandle();
+
+    const int playlist_member_id = item->getPlaylistMemberId();
+    LOGD("Remove item with playlist_member_id:%d", playlist_member_id);
+
+    int ret_code = media_playlist_remove_media(playlist_handle, playlist_member_id);
+    if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("ret : %d", ret_code);
+        destroyMediaPlaylistHandle(playlist_handle);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_remove_media()");
+    }
+
+    updatePlaylistInDB(playlist_handle);
+    destroyMediaPlaylistHandle(playlist_handle);
+}
+
+gboolean Playlist::removeBatchCompleteCB(void* data)
+{
+    LOGD("Entered");
+    RemoveBatchCallbackUserData* callback = NULL;
+
+    try {
+        callback = static_cast<RemoveBatchCallbackUserData*>(data);
+        if(!callback) {
+            LOGE("Callback is null");
+            return false;
+        }
+
+        JSContextRef context = callback->getContext();
+        if(!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("Context was closed");
+            delete callback;
+            callback = NULL;
+            return false;
+        }
+
+        if(callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Error while calling removeBatch callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Failed to call removeBatch callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* Playlist::removeBatchThread(void* data)
+{
+    LOGD("Entered");
+    RemoveBatchCallbackUserData* callback = NULL;
+    media_playlist_h playlist_handle = NULL;
+
+    try {
+        callback = static_cast<RemoveBatchCallbackUserData*>(data);
+        if (!callback) {
+            LOGE("Callback is null");
+            return NULL;
+        }
+
+        const std::vector<PlaylistItemPtr>& items = callback->getItems();
+        const std::size_t items_size = items.size();
+        PlaylistPtr playlist = callback->getPlaylist();
+        playlist_handle = playlist->getPlaylistHandle();
+
+        for (unsigned int i = 0; i < items_size; ++i) {
+            const PlaylistItemPtr& cur = items[i];
+            if(!cur) {
+                LOGE("PlaylistItem at index: %d is NULL", i);
+                throw UnknownException("Could not remove playlist item");
+            }
+
+            if(cur->getPlaylistId() != playlist->getId()) {
+                LOGE("Playlist item is not inside this playlist (playlist_id:%d != "
+                        "current playlist id:%d)",
+                        cur->getPlaylistId(), playlist->getId());
+                std::stringstream ss;
+                ss << "Playlist track at index:" << i;
+                ss << " in items array is inside different playlist";
+                throw UnknownException(ss.str().c_str());
+            }
+
+            LOGD("Remove item with playlist_member_id:%d",
+                    cur->getPlaylistMemberId());
+
+            int ret_code = media_playlist_remove_media(playlist_handle,
+                    cur->getPlaylistMemberId());
+            if (MEDIA_CONTENT_ERROR_NONE != ret_code) {
+                LOGE("ret : %d", ret_code);
+                ContentUtility::throwMediaContentException(ret_code, "media_playlist_remove_media()");
+            }
+        }
+
+        playlist->updatePlaylistInDB(playlist_handle);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("removeBatch failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "UnknownError.");
+    }
+
+    destroyMediaPlaylistHandle(playlist_handle);
+
+    if (!g_idle_add(removeBatchCompleteCB, static_cast<void*>(callback))) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+void Playlist::removeBatch(RemoveBatchCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, removeBatchThread, static_cast<void*>(callback))) {
+        LOGE("Failed to create pthread for removeBatch()");
+        throw UnknownException("Could not run remove batch task");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for removeBatch()");
+    }
+}
+
+gboolean Playlist::getCompleteCB(void *data)
+{
+    LOGD("Entered");
+    PlaylistContentCallback* callback = NULL;
+    JSObjectRef list_of_items = NULL;
+    JSContextRef context = NULL;
+
+    try {
+        callback = static_cast<PlaylistContentCallback*>(data);
+        if(!callback) {
+            LOGE("Callback is null");
+            return false;
+        }
+
+        context = callback->getContext();
+        if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            delete callback;
+            callback = NULL;
+            return false;
+        }
+
+        if(!callback->isError()) {
+
+            auto items = callback->getPlaylistItems();
+            if(!items) {
+                LOGE("Playlist items list is NULL!");
+                throw UnknownException("Could not get list of playlist items");
+            }
+
+            list_of_items = JSPlaylistItem::playlistItemsVectorToJSObjectArray(context,
+                    *(items.get()));
+        }
+    }
+    catch (const BasePlatformException &err){
+        LOGE("Error while creating list of PlaylistItems: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch(...) {
+        LOGE("Error while creating list of PlaylistItems");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Get items failed");
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback(list_of_items);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Error while calling removeBatch callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Failed to call removeBatch callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* Playlist::getThread(void *data)
+{
+    LOGD("Entered");
+    PlaylistContentCallback* callback = NULL;
+
+    try {
+        callback = static_cast<PlaylistContentCallback*>(data);
+        if (!callback) {
+            LOGE("Callback is null");
+            return NULL;
+        }
+
+        long count = GetPlaylistItemsRequest::COUNT_NOT_LIMITED;
+        if(callback->isCountSet()) {
+            count = callback->getCount();
+            if(count <= 0) {
+                LOGE("count:%d is <= 0", count);
+                throw InvalidValuesException("value of count parameter is invalid");
+            }
+        }
+
+        long offset = 0;
+        if(callback->isOffsetSet()) {
+            offset = callback->getOffset();
+            if(offset < 0) {
+                LOGE("offset:%d is < 0", offset);
+                throw InvalidValuesException("value of offset parameter is invalid");
+            }
+        }
+        LOGD("playlist_id:%d offset: %d count: %d",callback->getPlaylist()->getId(),
+                offset, count);
+
+        auto items = GetPlaylistItemsRequest::getItems(
+                callback->getPlaylist(), NULL, count, offset);
+        callback->setPlaylistItems(items);
+
+        LOGD("Got %d items", items ? items->size() : 0);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(),err.getMessage());
+    }
+    catch(...) {
+        LOGE("getItems failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Get items failed");
+    }
+
+    if (!g_idle_add(getCompleteCB, static_cast<void*>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+
+    return false;
+
+}
+
+void Playlist::get(PlaylistContentCallback *callback)
+{
+    LOGD("Entered");
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, getThread, static_cast<void*>(callback))) {
+        LOGE("Failed to create pthread for getItems()");
+        throw UnknownException("Could not run get items task");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for getItems()");
+    }
+}
+
+gboolean Playlist::moveCompleteCB(void* user_data)
+{
+    LOGD("Entered");
+
+    MoveItemCallbackUserData* callback = NULL;
+
+    try {
+        callback = static_cast<MoveItemCallbackUserData*>(user_data);
+        if(!callback) {
+            LOGE("Callback is null");
+            return false;
+        }
+
+        JSContextRef context = callback->getContext();
+        if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            delete callback;
+            callback = NULL;
+            return false;
+        }
+
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Error while calling moveItem callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Failed to call moveItem callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* Playlist::moveThread(void* user_data)
+{
+    LOGD("Entered");
+    MoveItemCallbackUserData* callback = NULL;
+    media_playlist_h playlist_handle = NULL;
+
+    try {
+        callback = static_cast<MoveItemCallbackUserData*>(user_data);
+        if(!callback) {
+            LOGE("callback is NULL!");
+            return NULL;
+        }
+
+        PlaylistPtr pls = callback->getPlaylist();
+        PlaylistItemPtr item = callback->getItem();
+
+        if(item->getPlaylistId() != pls->getId()) {
+            LOGE("Playlist item is not inside this playlist (playlist_id:%d != "
+                    "current playlist id:%d)", item->getPlaylistId(), pls->getId());
+            throw InvalidValuesException("Provided item is inside different playlist");
+        }
+
+        const int delta = callback->getDelta();
+        playlist_handle = pls->getPlaylistHandle();
+
+        std::shared_ptr<PlaylistItemPtrVec> all_items = GetPlaylistItemsRequest::getItems(
+                pls, playlist_handle);
+
+        //Iterate through items in playlist and verify that provided item belongs to this
+        //playlist
+        const size_t num_items_in_pls = all_items->size();
+        const int cur_item_member_id = item->getPlaylistMemberId();
+
+        bool item_is_in_playlist = false;
+        size_t item_is_at_index = 0;
+
+        for(size_t i = 0; i < num_items_in_pls; ++i) {
+            const int member_id = (*all_items.get())[i]->getPlaylistMemberId();
+            if(member_id == cur_item_member_id) {
+                item_is_in_playlist = true;
+                item_is_at_index = i;
+                break;
+            }
+        }
+
+        if(!item_is_in_playlist) {
+            LOGE("Playlist item with member id:%d does not exist in this playlist!",
+                    cur_item_member_id);
+            throw InvalidValuesException("Provided playlist item is not inside "
+                    "this playlist");
+        }
+
+        const int my_item_new_order_index = item_is_at_index + delta;
+        LOGD("Cur pos:%d delta:%d new pos:%d number of items in playlist:%d",
+                item_is_at_index, delta, my_item_new_order_index,
+                num_items_in_pls);
+
+
+        PlaylistItemPtrVec new_order;
+        new_order.reserve(num_items_in_pls);
+
+        const int items_in_pls = static_cast<int>(num_items_in_pls); //reduce casts in for
+
+        for(int i = 0; i < items_in_pls; ++i) {
+            PlaylistItemPtr cur = (*all_items.get())[i];
+
+            if(i == 0 && my_item_new_order_index < 0) {     //We need to insert at the top
+                new_order.push_back(item);
+            }
+
+            if(delta < 0) {                                               //When moving up
+                if (i == my_item_new_order_index) {
+                    new_order.push_back(item);
+                }
+                if(cur->getPlaylistMemberId() != cur_item_member_id) {
+                    new_order.push_back(cur);
+                }
+            } else {                                                    //When moving down
+                if(cur->getPlaylistMemberId() != cur_item_member_id) {
+                    new_order.push_back(cur);
+                }
+                if (i == my_item_new_order_index) {
+                    new_order.push_back(item);
+                }
+            }
+
+            if(i == items_in_pls - 1 && my_item_new_order_index > i) {
+                new_order.push_back(item);     //Insert at the end
+            }
+        }
+
+        pls->updatePlaylistItemsOrder(new_order, playlist_handle);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("moveItem failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "UnknownError.");
+    }
+
+    destroyMediaPlaylistHandle(playlist_handle);
+
+    if (!g_idle_add(moveCompleteCB, static_cast<void*>(callback))) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+void Playlist::move(MoveItemCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, moveThread, static_cast<void*>(callback))) {
+        LOGE("Failed to create pthread for moveItem()");
+        throw UnknownException("Could not run move item task");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for moveItem()");
+    }
+}
+
+gboolean Playlist::setOrderCompleteCB(void* user_data)
+{
+    LOGD("Entered");
+    SetItemsOrderCallbackUserData* callback = NULL;
+
+    try {
+        callback = static_cast<SetItemsOrderCallbackUserData*>(user_data);
+        if(!callback){
+            LOGE("Callback is null");
+            return false;
+        }
+
+        JSContextRef context = callback->getContext();
+        if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            delete callback;
+            callback = NULL;
+            return false;
+        }
+
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Error while calling setItemsOrder callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Failed to call setItemsOrder callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* Playlist::setOrderThread(void* user_data)
+{
+    LOGD("Entered");
+    SetItemsOrderCallbackUserData* callback = NULL;
+    media_playlist_h playlist_handle = NULL;
+
+    try {
+        callback = static_cast<SetItemsOrderCallbackUserData*>(user_data);
+        if(!callback) {
+            LOGE("callback is NULL!");
+            return NULL;
+        }
+
+        PlaylistPtr pls = callback->getPlaylist();
+        PlaylistItemPtrVec& new_order = callback->getItems();
+        playlist_handle = pls->getPlaylistHandle();
+
+        const size_t num_items_in_pls = new_order.size();
+        if (num_items_in_pls == 0) {
+            LOGE("List of items is empty!");
+            throw InvalidValuesException("List of items is empty!");
+        }
+
+        for(size_t i = 0; i < num_items_in_pls; ++i) {
+            if(new_order[i]->getPlaylistId() != pls->getId()) {
+
+                LOGE("Playlist item is not inside this playlist (playlist_id:%d != "
+                        "current playlist id:%d)",
+                        new_order[i]->getPlaylistId(), pls->getId());
+
+                std::stringstream ss;
+                ss << "Playlist track at index:" << i;
+                ss << " in items array is inside different playlist";
+                throw InvalidValuesException(ss.str().c_str());
+            }
+        }
+
+        //Get list of all items in current playlist
+        //
+        std::shared_ptr<PlaylistItemPtrVec> all_items = GetPlaylistItemsRequest::getItems(
+                pls, playlist_handle, GetPlaylistItemsRequest::COUNT_NOT_LIMITED, 0,
+                false); //We don't need to fetch current playlist in play order
+
+        if(all_items->size() != new_order.size()) {
+            LOGE("Playlist contains: %d items but provided order list contain: %d items!",
+                    all_items->size(), new_order.size());
+            throw InvalidValuesException(
+                    "Number of tracks in items array do not match count of items "
+                    "present in playlist");
+        }
+
+        //Generate set of member ids present in this playlist
+        //
+        std::set<int> member_ids;
+        for(size_t i = 0; i < num_items_in_pls; ++i) {
+            PlaylistItemPtr cur_item = (*all_items.get())[i];
+            member_ids.insert(cur_item->getPlaylistMemberId());
+        }
+
+        //Iterate through items array and verify that they are inside this playlist
+        for(size_t i = 0; i < num_items_in_pls; ++i) {
+            const int cur_member_id = new_order[i]->getPlaylistMemberId();
+            if(member_ids.find(cur_member_id) == member_ids.end()) {
+                LOGE("Playlist item with member id:%d does not exist in this playlist!",
+                        cur_member_id);
+
+                std::stringstream ss;
+                ss << "Track at index: " << i <<" in items array is not in this playlist";
+                throw InvalidValuesException(ss.str().c_str());
+            }
+        }
+
+        pls->updatePlaylistItemsOrder(new_order, playlist_handle);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch(...) {
+        LOGE("setItemsOrder failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "UnknownError.");
+    }
+
+    destroyMediaPlaylistHandle(playlist_handle);
+
+    if (!g_idle_add(setOrderCompleteCB, static_cast<void*>(callback))) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+void Playlist::setOrder(SetItemsOrderCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, setOrderThread, static_cast<void*>(callback))) {
+        LOGE("Failed to create pthread for setItemsOrder()");
+        throw UnknownException("Could not run set items order task");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for setItemsOrder()");
+    }
+}
+
+void Playlist::updatePlaylistItemsOrder(const PlaylistItemPtrVec& new_order,
+        media_playlist_h playlist_handle)
+{
+    LOGD("entered new_order.size():%d", new_order.size());
+
+    media_playlist_h playlist_handle_to_destroy = NULL;
+    if(!playlist_handle) {
+        playlist_handle = getPlaylistHandle();
+        playlist_handle_to_destroy = playlist_handle;
+    }
+
+    try {
+        LOGD("Updating playlist order in DB:");
+        const size_t num_items = new_order.size();
+        for(size_t i = 0; i < num_items; ++i) {
+            int cur_member_id = new_order[i]->getPlaylistMemberId();
+            LOGD("[%d] member_id:%d -> order_index: %d", i, cur_member_id, i);
+
+            int ret_code = media_playlist_set_play_order (playlist_handle, cur_member_id,
+                    static_cast<int>(i));
+            if(MEDIA_CONTENT_ERROR_NONE != ret_code ||
+                    playlist_handle == NULL) {
+                LOGE("media_playlist_set_play_order (for member id: %d) "
+                        "failed with:%d desc:%s playlist:%p", cur_member_id,
+                        ret_code, ContentUtility::getMediaContentErrorMessage(ret_code), playlist_handle);
+                LOGE("ret : %d", ret_code);
+                ContentUtility::throwMediaContentException(ret_code, "media_playlist_set_play_order()");
+            }
+        }
+
+        updatePlaylistInDB(playlist_handle);
+        destroyMediaPlaylistHandle(playlist_handle_to_destroy);
+    }
+    catch(...) {
+        destroyMediaPlaylistHandle(playlist_handle_to_destroy);
+        throw;
+    }
+}
+
+media_playlist_h Playlist::getPlaylistHandle()
+{
+    LOGD("Entered");
+    media_playlist_h playlist_handle = NULL;
+    int ret_code = media_playlist_get_playlist_from_db(m_id, &playlist_handle);
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code ||
+            playlist_handle == NULL) {
+        LOGE("media_playlist_get_playlist_from_db failed with:%d desc:%s playlist:%p",
+                ret_code, ContentUtility::getMediaContentErrorMessage(ret_code), playlist_handle);
+        LOGE("ret : %d", ret_code);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_get_playlist_from_db()");
+    }
+
+    return playlist_handle;
+}
+
+void Playlist::updatePlaylistInDB(media_playlist_h playlist_handle)
+{
+    LOGD("Entered");
+    media_playlist_h handle_to_destroy = NULL;
+
+    if(!playlist_handle) {
+        handle_to_destroy = getPlaylistHandle();
+        playlist_handle = handle_to_destroy;
+    }
+
+    int ret_code = media_playlist_update_to_db(playlist_handle);
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("media_playlist_update_to_db failed with:%d desc:%s",
+                ret_code, ContentUtility::getMediaContentErrorMessage(ret_code));
+        LOGE("ret : %d", ret_code);
+        destroyMediaPlaylistHandle(handle_to_destroy);
+        ContentUtility::throwMediaContentException<PlaylistUnknownException>(
+                ret_code, "media_playlist_update_to_db()");
+    }
+
+    destroyMediaPlaylistHandle(handle_to_destroy);
+}
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/Playlist.h b/src/Content/Playlist.h
new file mode 100644 (file)
index 0000000..1755a2b
--- /dev/null
@@ -0,0 +1,137 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_PLAYLIST_H__
+#define __TIZEN_CONTENT_PLAYLIST_H__
+
+#include <glib.h>
+#include <media_content.h>
+#include <media_info.h>
+#include <media_playlist.h>
+#include <memory>
+#include <vector>
+
+#include <GlobalContextManager.h>
+#include <Security.h>
+
+#include "AudioContent.h"
+#include "ContentCallback.h"
+#include "Content.h"
+#include "ContentHelper.h"
+#include "ContentUtility.h"
+#include "JSContent.h"
+#include "PlaylistItem.h"
+
+#include "AddBatchCallbackUserData.h"
+#include "MoveItemCallbackUserData.h"
+#include "PlaylistContentCallback.h"
+#include "RemoveBatchCallbackUserData.h"
+#include "SetItemsOrderCallbackUserData.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class PlaylistCopyUtil;
+typedef const std::vector<ContentPtr> ContentPtrVec;
+typedef std::vector<PlaylistPtr> PlaylistPtrVec;
+
+class AddBatchCallbackUserData;
+class PlaylistContentCallback;
+class RemoveBatchCallbackUserData;
+class SetItemsOrderCallbackUserData;
+
+
+struct PlaylistHolder {
+    PlaylistPtr ptr;
+};
+
+class Playlist : public Common::SecurityAccessor
+{
+public:
+    Playlist(const int playlist_id);
+    ~Playlist();    //virtual not needed, this class is not intended to be a base class
+
+    int getId() const;
+
+    std::string getName();
+    void setName(const std::string& name);
+
+    unsigned long getNumberOfTracks();
+
+    std::string getThumbnailURI();
+    void setThumbnailURI(const std::string& thb_uri);
+
+    void add(ContentPtr item);
+    void addBatch(AddBatchCallbackUserData* callback);
+
+    void remove(PlaylistItemPtr item);
+    void removeBatch(RemoveBatchCallbackUserData* callback);
+
+    void get(PlaylistContentCallback *callback);
+    void move(MoveItemCallbackUserData* callback);
+    void setOrder(SetItemsOrderCallbackUserData* callback);
+
+private:
+    static gboolean addBatchCompleteCB(void *data);
+    static void* addBatchThread(void *data);
+
+    static gboolean removeBatchCompleteCB(void *data);
+    static void* removeBatchThread(void *data);
+
+    static gboolean getCompleteCB(void *data);
+    static void* getThread(void *data);
+
+    static gboolean moveCompleteCB(void *data);
+    static void* moveThread(void* user_data);
+
+    static gboolean setOrderCompleteCB(void* user_data);
+    static void* setOrderThread(void* user_data);
+
+    /**
+     * \brief Sets the new order of items in playlist
+     * \param new_order List of items in new order
+     * \param playlist_handle Handle to playlist, if NULL is provided then this method
+     * will aquire it with getPlaylistHandle() function.
+     */
+    void updatePlaylistItemsOrder(const PlaylistItemPtrVec& new_order,
+            media_playlist_h playlist_handle = NULL);
+
+    /**
+     * \brief Gets media_playlist_h for current playlist id.
+     * This method will throw UnknownException if any error occur
+     * Please call destroyMediaPlaylistHandle(...) to release this handle.
+     */
+    media_playlist_h getPlaylistHandle();
+
+    /**
+     * \brief Update playlist in DB (apply changes made with core API)
+     * \param playlist_handle Handle to playlist, if NULL is provided then this method
+     * will aquire it with getPlaylistHandle() function.
+     * This method will throw UnknownException if any error occur.
+     */
+    void updatePlaylistInDB(media_playlist_h playlist_handle = NULL);
+
+    int m_id;
+
+    friend class GetPlaylistItemsRequest;
+    friend class PlaylistCopyUtil;
+};
+
+} //namespace Content
+} //namespace DeviceAPI
+
+#endif // __TIZEN_CONTENT_PLAYLIST_H__
diff --git a/src/Content/PlaylistArraySuccessCallbackUserData.cpp b/src/Content/PlaylistArraySuccessCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..799e510
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PlaylistArraySuccessCallbackUserData.h"
+
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+PlaylistArraySuccessCallbackUserData::PlaylistArraySuccessCallbackUserData(
+        JSContextRef global_ctx) :
+                BaseCallbackUserData(global_ctx)
+{
+}
+
+PlaylistArraySuccessCallbackUserData::~PlaylistArraySuccessCallbackUserData()
+{
+}
+
+std::shared_ptr<PlaylistPtrVec> PlaylistArraySuccessCallbackUserData::getPlaylists()
+{
+    return m_playlists;
+}
+
+void PlaylistArraySuccessCallbackUserData::setPlaylists(
+        std::shared_ptr<PlaylistPtrVec> playlists)
+{
+    m_playlists = playlists;
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/PlaylistArraySuccessCallbackUserData.h b/src/Content/PlaylistArraySuccessCallbackUserData.h
new file mode 100644 (file)
index 0000000..edcc9a6
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN__CONTENT_PLAYLIST_ARRAY_SUCCESS_CALLBACK_USER_DATA_H__
+#define __TIZEN__CONTENT_PLAYLIST_ARRAY_SUCCESS_CALLBACK_USER_DATA_H__
+
+#include <CallbackUserData.h>
+#include <string>
+#include <vector>
+
+#include "BaseCallbackUserData.h"
+#include "Playlist.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class PlaylistArraySuccessCallbackUserData : public BaseCallbackUserData
+{
+public:
+    PlaylistArraySuccessCallbackUserData(JSContextRef global_ctx);
+    virtual ~PlaylistArraySuccessCallbackUserData();
+
+    std::shared_ptr<PlaylistPtrVec> getPlaylists();
+    void setPlaylists(std::shared_ptr<PlaylistPtrVec> playlists);
+
+private:
+    std::shared_ptr<PlaylistPtrVec> m_playlists;
+};
+
+} //Content
+} //DeviceAPI
+
+#endif /* __TIZEN_CONTENT_PLAYLIST_ARRAY_SUCCESS_CALLBACK_USER_DATA_H__ */
diff --git a/src/Content/PlaylistContentCallback.cpp b/src/Content/PlaylistContentCallback.cpp
new file mode 100644 (file)
index 0000000..fd5e5e4
--- /dev/null
@@ -0,0 +1,95 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PlaylistContentCallback.h"
+
+using namespace DeviceAPI::Content;
+
+namespace DeviceAPI {
+namespace Content {
+
+PlaylistContentCallback::PlaylistContentCallback(JSContextRef globalCtx,
+        PlaylistPtr playlist_ptr) :
+                BaseCallbackUserData(globalCtx),
+                m_playlist_ptr(playlist_ptr),
+                m_count(0),
+                m_count_set(false),
+                m_offset(0),
+                m_offset_set(false)
+{
+}
+
+PlaylistPtr PlaylistContentCallback::getPlaylist() const
+{
+    return m_playlist_ptr;
+}
+
+void PlaylistContentCallback::setPlaylistItems(std::shared_ptr<PlaylistItemPtrVec> items)
+{
+    m_playlist_items = items;
+}
+
+std::shared_ptr<PlaylistItemPtrVec> PlaylistContentCallback::getPlaylistItems()
+{
+    return m_playlist_items;
+}
+
+long PlaylistContentCallback::getCount() const
+{
+    return m_count;
+}
+
+void PlaylistContentCallback::setCount(long count)
+{
+    m_count = count;
+    m_count_set = true;
+}
+bool PlaylistContentCallback::isCountSet() const
+{
+    return m_count_set;
+}
+
+void PlaylistContentCallback::unsetCount()
+{
+    m_count = 0;
+    m_count_set = false;
+}
+
+long PlaylistContentCallback::getOffset() const
+{
+    return m_offset;
+}
+
+void PlaylistContentCallback::setOffset(long offset)
+{
+    m_offset = offset;
+    m_offset_set = true;
+}
+
+bool PlaylistContentCallback::isOffsetSet() const
+{
+    return m_offset;
+}
+
+void PlaylistContentCallback::unsetOffset()
+{
+    m_offset = 0;
+    m_offset_set = false;
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/PlaylistContentCallback.h b/src/Content/PlaylistContentCallback.h
new file mode 100755 (executable)
index 0000000..7d2775e
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_PLAYLIST_CONTENT_CALLBACK_H__
+#define __TIZEN_CONTENT_PLAYLIST_CONTENT_CALLBACK_H__
+
+
+#include <memory>
+#include <JavaScriptCore/JavaScript.h>
+
+#include "BaseCallbackUserData.h"
+#include "Playlist.h"
+#include "PlaylistItem.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class PlaylistContentCallback;
+typedef std::shared_ptr<PlaylistContentCallback> PlaylistContentCallbackPtr;
+
+class PlaylistContentCallback : public BaseCallbackUserData
+{
+public:
+    PlaylistContentCallback(JSContextRef globalCtx, PlaylistPtr playlist_ptr);
+
+    PlaylistPtr getPlaylist() const;
+
+    void setPlaylistItems(std::shared_ptr<PlaylistItemPtrVec> items);
+    std::shared_ptr<PlaylistItemPtrVec> getPlaylistItems();
+
+    long getCount() const;
+    void setCount(long count);
+    bool isCountSet() const;
+    void unsetCount();
+
+    long getOffset() const;
+    void setOffset(long offset);
+    bool isOffsetSet() const;
+    void unsetOffset();
+
+private:
+    PlaylistPtr m_playlist_ptr;
+    std::shared_ptr<PlaylistItemPtrVec> m_playlist_items;
+
+    long m_count;
+    bool m_count_set;
+
+    long m_offset;
+    bool m_offset_set;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif //__TIZEN_CONTENT_PLAYLIST_CONTENT_CALLBACK_H__
diff --git a/src/Content/PlaylistCopyUtil.cpp b/src/Content/PlaylistCopyUtil.cpp
new file mode 100644 (file)
index 0000000..5cd8b09
--- /dev/null
@@ -0,0 +1,135 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PlaylistCopyUtil.h"
+#include "PlaylistUtils.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+
+#include "PlaylistUtils.h"
+#include "Playlist.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+PlaylistCopyUtil::PlaylistCopyUtil() :
+            m_dest_playlist_handle(NULL),
+            m_copy_failed(false)
+{
+}
+
+PlaylistCopyUtil::~PlaylistCopyUtil()
+{
+    destroyMediaPlaylistHandle(m_dest_playlist_handle);
+}
+
+void PlaylistCopyUtil::copyItems(PlaylistPtr source_playlist,
+        PlaylistPtr dest_playlist)
+{
+    LOGD("Entered");
+    std::unique_ptr<PlaylistCopyUtil> util(new PlaylistCopyUtil());
+    util->copyItemsPriv(source_playlist, dest_playlist);
+}
+
+bool PlaylistCopyUtil::receivedPlaylistMemberCB(int playlist_member_id, media_info_h media,
+        void *user_data)
+{
+    PlaylistCopyUtil* util = static_cast<PlaylistCopyUtil*>(user_data);
+    if(!util) {
+        LOGE("user_data is NULL, nothing to do!");
+        return false;
+    }
+    return util->process(playlist_member_id, media);
+}
+
+bool PlaylistCopyUtil::process(int playlist_member_id, media_info_h media)
+{
+    //LOGD("Entered member_id:%d", playlist_member_id);
+    char* media_id = NULL;
+    int ret_code = media_info_get_media_id(media, &media_id);
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                ret_code, "media_info_get_media_id()").c_str());
+        m_copy_failed = true;
+        return false;   //Do not continue
+    }
+
+    ret_code = media_playlist_add_media(m_dest_playlist_handle, media_id);
+    LOGD("cloned item:%s", media_id);
+    free(media_id);
+
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                ret_code, "media_playlist_add_media()").c_str());
+        m_copy_failed = true;
+        return false;   //Do not continue
+    }
+    return true;
+}
+
+void PlaylistCopyUtil::copyItemsPriv(PlaylistPtr source_playlist,
+        PlaylistPtr dest_playlist)
+{
+    LOGD("Entered");
+
+    if(!source_playlist) {
+        LOGE("source_playlist is NULL");
+        throw UnknownException("Source playlist is invalid!");
+    }
+
+    if(!dest_playlist) {
+        LOGE("dest_playlist is NULL");
+        throw UnknownException("Destination playlist is invalid!");
+    }
+
+    m_src_playlist = source_playlist;
+    const int src_playlist_id = m_src_playlist->getId();
+
+    m_dest_playlist = dest_playlist;
+    m_dest_playlist_handle = dest_playlist->getPlaylistHandle();
+
+    int ret_code = media_playlist_foreach_media_from_db(src_playlist_id, NULL,
+            receivedPlaylistMemberCB, this);
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("ret : %d", ret_code);
+        destroyMediaPlaylistHandle(m_dest_playlist_handle);
+        ContentUtility::throwMediaContentException(ret_code, "media_playlist_foreach_media_from_db()");
+    }
+
+    if(!m_copy_failed) {
+        LOGD("Updating DB with new playlist items");
+        ret_code = media_playlist_update_to_db(m_dest_playlist_handle);
+        if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+            LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                    ret_code, "media_playlist_update_to_db()").c_str());
+            m_copy_failed = true;
+        }
+    }
+
+    destroyMediaPlaylistHandle(m_dest_playlist_handle);
+
+    if(m_copy_failed) {
+        LOGE("Copy operation failed!");
+        throw UnknownException("Playlist clone failed");
+    }
+
+    LOGD("Success");
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/PlaylistCopyUtil.h b/src/Content/PlaylistCopyUtil.h
new file mode 100644 (file)
index 0000000..d0c0453
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_PLAYLIST_COPY_UTIL_H__
+#define __TIZEN_CONTENT_PLAYLIST_COPY_UTIL_H__
+
+#include <media_content.h>
+
+#include "Playlist.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class PlaylistCopyUtil
+{
+public:
+    ~PlaylistCopyUtil();
+    static void copyItems(PlaylistPtr source_playlist, PlaylistPtr dest_playlist);
+
+private:
+    PlaylistCopyUtil();
+
+    static bool receivedPlaylistMemberCB(int playlist_member_id, media_info_h media,
+            void *user_data);
+    bool process(int playlist_member_id, media_info_h media);
+
+    void copyItemsPriv(PlaylistPtr source_playlist, PlaylistPtr dest_playlist);
+
+    PlaylistPtr m_src_playlist;
+    PlaylistPtr m_dest_playlist;
+    media_playlist_h m_dest_playlist_handle;
+    bool m_copy_failed;
+};
+
+} //namespace Content
+} //namespace DeviceAPI
+
+#endif // __TIZEN_CONTENT_PLAYLIST_COPY_UTIL_H__
diff --git a/src/Content/PlaylistItem.cpp b/src/Content/PlaylistItem.cpp
new file mode 100644 (file)
index 0000000..6ec37d6
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PlaylistItem.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+PlaylistItem::PlaylistItem(const int playlist_id,
+        const int playlist_member_id,
+        media_info_h media) :
+                m_playlist_id(playlist_id),
+                m_playlist_member_id(playlist_member_id),
+                m_media_handle(NULL)
+{
+    LOGD("Entered");
+
+    if(media) {
+        media_info_clone(&m_media_handle, media);
+    }
+}
+
+PlaylistItem::~PlaylistItem()
+{
+    if(m_media_handle) {
+        media_info_destroy(m_media_handle);
+        m_media_handle = NULL;
+    }
+}
+
+int PlaylistItem::getPlaylistId() const
+{
+    return m_playlist_id;
+}
+
+int PlaylistItem::getPlaylistMemberId() const
+{
+    return m_playlist_member_id;
+}
+
+AudioContentPtr PlaylistItem::getAudioContent()
+{
+    return m_audio_content;
+}
+
+void PlaylistItem::setAudioContent(AudioContentPtr content)
+{
+    m_audio_content = content;
+}
+
+media_info_h PlaylistItem::getMediaInfoHandle()
+{
+    return m_media_handle;
+}
+
+void PlaylistItem::setMediaInfoHandle(media_info_h  media)
+{
+    if(m_media_handle) {
+        media_info_destroy(m_media_handle);
+        m_media_handle = NULL;
+    }
+
+    media_info_clone(&m_media_handle, media);
+}
+
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/PlaylistItem.h b/src/Content/PlaylistItem.h
new file mode 100644 (file)
index 0000000..42a98ef
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_PLAYLIST_ITEM_H__
+#define __TIZEN_CONTENT_PLAYLIST_ITEM_H__
+
+#include <media_content.h>
+#include <media_info.h>
+#include <media_playlist.h>
+#include <memory>
+#include <vector>
+
+#include <Security.h>
+
+#include "Content.h"
+#include "AudioContent.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class PlaylistItem;
+typedef std::shared_ptr<PlaylistItem> PlaylistItemPtr;
+typedef std::vector<PlaylistItemPtr> PlaylistItemPtrVec;
+
+struct PlaylistItemHolder {
+    PlaylistItemPtr ptr;
+};
+
+class PlaylistItem : public Common::SecurityAccessor
+{
+public:
+    PlaylistItem(const int playlist_id,
+            const int playlist_member_id,
+            media_info_h media = NULL);
+
+    virtual ~PlaylistItem();
+
+    int getPlaylistId() const;
+    int getPlaylistMemberId() const;
+
+    AudioContentPtr getAudioContent();
+    void setAudioContent(AudioContentPtr content);
+
+    media_info_h getMediaInfoHandle();
+    void setMediaInfoHandle(media_info_h media);
+
+private:
+    int m_playlist_id;
+    int m_playlist_member_id;
+    media_info_h m_media_handle;
+
+    AudioContentPtr m_audio_content;
+};
+
+} //namespace Content
+} //namespace DeviceAPI
+
+#endif // __TIZEN_CONTENT_PLAYLIST_ITEM_H__
diff --git a/src/Content/PlaylistUtils.cpp b/src/Content/PlaylistUtils.cpp
new file mode 100644 (file)
index 0000000..31808ce
--- /dev/null
@@ -0,0 +1,103 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PlaylistUtils.h"
+#include "ContentUtility.h"
+
+#include <Logger.h>
+#include <sstream>
+
+namespace DeviceAPI {
+namespace Content {
+
+int destroyMediaPlaylistHandle(media_playlist_h& playlist_handle)
+{
+    if(!playlist_handle) {
+        return MEDIA_CONTENT_ERROR_NONE;
+    }
+
+    int ret_code = media_playlist_destroy(playlist_handle);
+    playlist_handle = NULL;
+
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                ret_code, "media_playlist_destroy()").c_str());
+    }
+
+    return ret_code;
+}
+
+int destroyMediaFilterHandle(filter_h& filter_handle)
+{
+    int ret_code = media_filter_destroy(filter_handle);
+    filter_handle = NULL;
+
+    if(MEDIA_CONTENT_ERROR_NONE != ret_code) {
+        LOGE("%s", ContentUtility::getMediaContentLogMessage(
+                ret_code, "media_filter_destroy()").c_str());
+    }
+
+    return ret_code;
+}
+
+PlaylistItemPtr getPlaylistItemFromJSObjectRef(JSContextRef context,
+        JSObjectRef obj)
+{
+    LOGD("Entered");
+    if(JSPlaylistItem::isObjectOfClass(context, obj)) {
+        return JSPlaylistItem::getPrivateObject(context, obj);
+    } else {
+        LOGE("Wrong content type");
+        throw TypeMismatchException("Wrong content type");
+    }
+}
+
+AudioContentPtr getAudioContentPtrFromJSObjectRef(JSContextRef context,
+        JSObjectRef obj)
+{
+    LOGD("Entered");
+    if(JSAudioContent::isObjectOfClass(context, obj) ) {
+        return JSAudioContent::getPrivateObject(context, obj);
+    } else {
+        LOGE("Wrong content type");
+        throw TypeMismatchException("Wrong content type");
+    }
+}
+
+
+PlaylistUnknownException::PlaylistUnknownException(const char* message,
+        int core_api_error) :
+                Common::UnknownException(message),
+                m_core_api_error(core_api_error)
+{
+}
+
+PlaylistUnknownException::PlaylistUnknownException(JSContextRef ctx,
+        JSValueRef exception, int core_api_error) :
+                Common::UnknownException(ctx, exception),
+                m_core_api_error(core_api_error)
+{
+}
+
+int PlaylistUnknownException::getCoreAPIError() const
+{
+    return m_core_api_error;
+}
+
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/PlaylistUtils.h b/src/Content/PlaylistUtils.h
new file mode 100644 (file)
index 0000000..2a4c148
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_PLAYLIST_UTILS_H__
+#define __TIZEN_CONTENT_PLAYLIST_UTILS_H__
+
+#include <media_content.h>
+#include <media_filter.h>
+#include <string>
+
+#include <PlatformException.h>
+
+#include "AudioContent.h"
+#include "JSAudioContent.h"
+#include "JSPlaylistItem.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+/**
+ * \brief Invokes media_playlist_destroy, sets playlist_handle to NULL,
+ * reports errors with LOGS. This method do not throw exceptions.
+ *
+ * \param playlist_handle Playlist handle to be destroyed. If is NULL then nothing is done
+ *
+ * \returns error code from media_playlist_destroy function
+ */
+extern int destroyMediaPlaylistHandle(media_playlist_h& playlist_handle);
+
+
+extern PlaylistItemPtr getPlaylistItemFromJSObjectRef(JSContextRef context,
+        JSObjectRef obj);
+
+extern AudioContentPtr getAudioContentPtrFromJSObjectRef(JSContextRef context,
+        JSObjectRef obj);
+
+/**
+ * \brief Invokes media_filter_destroy, sets filter_handle to NULL,
+ * reports errors with LOGS. This method do not throw exceptions.
+ *
+ * \param filter_handle The handle to media filter to be destroyed
+ *
+ * \returns error code from media_filter_destroy function
+ */
+extern int destroyMediaFilterHandle(filter_h& filter_handle);
+
+
+class PlaylistUnknownException : public Common::UnknownException {
+public:
+    PlaylistUnknownException(const char* message,
+            int core_api_error = MEDIA_CONTENT_ERROR_NONE);
+
+    PlaylistUnknownException(JSContextRef ctx, JSValueRef exception,
+            int core_api_error = MEDIA_CONTENT_ERROR_NONE);
+
+    int getCoreAPIError() const;
+private:
+    int m_core_api_error;
+};
+
+
+} //namespace Content
+} //namespace DeviceAPI
+
+#endif // __TIZEN_CONTENT_PLAYLIST_UTILS_H__
diff --git a/src/Content/RemoveBatchCallbackUserData.cpp b/src/Content/RemoveBatchCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..1b6cd05
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "RemoveBatchCallbackUserData.h"
+
+#include <Logger.h>
+
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Content {
+
+RemoveBatchCallbackUserData::RemoveBatchCallbackUserData(JSContextRef global_ctx,
+        const std::vector<PlaylistItemPtr>& items,
+        PlaylistPtr playlist_ptr) :
+                BaseCallbackUserData(global_ctx),
+                m_items(items),
+                m_playlist_ptr(playlist_ptr)
+{
+    LOGD("Entered");
+}
+
+RemoveBatchCallbackUserData::~RemoveBatchCallbackUserData()
+{
+}
+
+const std::vector<PlaylistItemPtr>& RemoveBatchCallbackUserData::getItems() const
+{
+    LOGD("Entered");
+    return m_items;
+}
+
+PlaylistPtr RemoveBatchCallbackUserData::getPlaylist()
+{
+    LOGD("Entered");
+    return m_playlist_ptr;
+}
+
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/RemoveBatchCallbackUserData.h b/src/Content/RemoveBatchCallbackUserData.h
new file mode 100644 (file)
index 0000000..485c86d
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CONTENT_REMOVE_BATCH_CALLBACK_USER_DATA_H_
+#define _TIZEN_CONTENT_REMOVE_BATCH_CALLBACK_USER_DATA_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <memory>
+#include <vector>
+
+#include "BaseCallbackUserData.h"
+#include "PlaylistItem.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class Playlist;
+typedef std::shared_ptr<Playlist> PlaylistPtr;
+
+class RemoveBatchCallbackUserData: public BaseCallbackUserData {
+
+public:
+    RemoveBatchCallbackUserData(JSContextRef global_ctx,
+            const std::vector<PlaylistItemPtr>& items,
+            PlaylistPtr playlist_ptr);
+    virtual ~RemoveBatchCallbackUserData();
+
+    const std::vector<PlaylistItemPtr>& getItems() const;
+    PlaylistPtr getPlaylist();
+
+private:
+    std::vector<PlaylistItemPtr> m_items;
+    PlaylistPtr m_playlist_ptr;
+};
+
+} // DeviceAPI
+} // Calendar
+
+#endif /* _TIZEN_CONTENT_REMOVE_BATCH_CALLBACK_USER_DATA_H_ */
diff --git a/src/Content/RemovePlaylistCallbackUserData.cpp b/src/Content/RemovePlaylistCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..e832b04
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "RemovePlaylistCallbackUserData.h"
+
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Content {
+
+RemovePlaylistCallbackUserData::RemovePlaylistCallbackUserData(
+        JSContextRef global_ctx) :
+                BaseCallbackUserData(global_ctx)
+{
+}
+
+RemovePlaylistCallbackUserData::~RemovePlaylistCallbackUserData()
+{
+}
+
+const std::string& RemovePlaylistCallbackUserData::getPlaylistId() const
+{
+    return m_playlist_id;
+}
+
+void RemovePlaylistCallbackUserData::setPlaylistId(const std::string& playlist_id)
+{
+    m_playlist_id = playlist_id;
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/RemovePlaylistCallbackUserData.h b/src/Content/RemovePlaylistCallbackUserData.h
new file mode 100644 (file)
index 0000000..1d47d6e
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONTENT_REMOVE_PLAYLIST_CALLBACK_USER_DATA_H__
+#define __TIZEN_CONTENT_REMOVE_PLAYLIST_CALLBACK_USER_DATA_H__
+
+#include <string>
+#include <vector>
+
+#include "BaseCallbackUserData.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class RemovePlaylistCallbackUserData : public BaseCallbackUserData
+{
+public:
+    RemovePlaylistCallbackUserData(JSContextRef global_ctx);
+    virtual ~RemovePlaylistCallbackUserData();
+
+    const std::string& getPlaylistId() const;
+    void setPlaylistId(const std::string& playlist_id);
+
+private:
+    std::string m_playlist_id;
+};
+
+}//Content
+}//DeviceAPI
+
+#endif /* __TIZEN_CONTENT_REMOVE_PLAYLIST_CALLBACK_USER_DATA_H__ */
diff --git a/src/Content/SetItemsOrderCallbackUserData.cpp b/src/Content/SetItemsOrderCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..27868b4
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SetItemsOrderCallbackUserData.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+SetItemsOrderCallbackUserData::SetItemsOrderCallbackUserData(JSContextRef global_ctx,
+        PlaylistPtr playlist) :
+                BaseCallbackUserData(global_ctx),
+                m_playlist(playlist)
+{
+}
+
+SetItemsOrderCallbackUserData::~SetItemsOrderCallbackUserData()
+{
+}
+
+PlaylistPtr SetItemsOrderCallbackUserData::getPlaylist()
+{
+    return m_playlist;
+}
+
+PlaylistItemPtrVec& SetItemsOrderCallbackUserData::getItems()
+{
+    return m_items;
+}
+
+} //namespace Content
+} //namespace DeviceAPI
diff --git a/src/Content/SetItemsOrderCallbackUserData.h b/src/Content/SetItemsOrderCallbackUserData.h
new file mode 100644 (file)
index 0000000..f587a51
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CONTENT_SET_ITEMS_CALLBACK_USER_DATA_H_
+#define _TIZEN_CONTENT_SET_ITEMS_CALLBACK_USER_DATA_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <memory>
+
+#include "BaseCallbackUserData.h"
+#include "Playlist.h"
+#include "PlaylistItem.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+class SetItemsOrderCallbackUserData : public BaseCallbackUserData {
+
+public:
+    SetItemsOrderCallbackUserData(JSContextRef globalCtx, PlaylistPtr playlist);
+    virtual ~SetItemsOrderCallbackUserData();
+
+    PlaylistPtr getPlaylist();
+    PlaylistItemPtrVec& getItems();
+
+private:
+    PlaylistPtr m_playlist;
+    PlaylistItemPtrVec m_items;
+
+};
+
+} // Content
+} // DeviceAPI
+
+#endif /* _TIZEN_CONTENT_SET_ITEMS_CALLBACK_USER_DATA_H_ */
diff --git a/src/Content/VideoContent.cpp b/src/Content/VideoContent.cpp
new file mode 100755 (executable)
index 0000000..b73a91d
--- /dev/null
@@ -0,0 +1,141 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "VideoContent.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+VideoContent::VideoContent():
+            m_album(""),
+            m_duration(0),
+            m_width(0),
+            m_height(0),
+            m_is_geolocation_set(false)
+{
+    m_type = "VIDEO";
+    m_editableAttributes.push_back("geolocation");
+}
+
+VideoContent::~VideoContent()
+{
+}
+
+SimpleCoordinatesPtr VideoContent::getGeolocation() const
+{
+    return m_geolocation;
+}
+
+void VideoContent::setGeolocation(SimpleCoordinatesPtr geolocation)
+{
+    m_geolocation = geolocation;
+    m_is_geolocation_set = true;
+}
+
+bool VideoContent::isGeolocationSet() const
+{
+    return m_is_geolocation_set;
+}
+
+void VideoContent::unsetGeolocation()
+{
+    m_geolocation = SimpleCoordinatesPtr();
+    m_is_geolocation_set = false;
+}
+
+void VideoContent::setLatitude(double latitude)
+{
+    if(!isGeolocationSet()) {
+        setGeolocation(std::make_shared<SimpleCoordinates>(0.0, 0.0));
+    }
+    m_geolocation->setLatitude(latitude);
+}
+
+double VideoContent::getLatitude()
+{
+    return m_geolocation->getLatitude();
+}
+
+void VideoContent::setLongitude(double longitude)
+{
+    if(!isGeolocationSet()) {
+        setGeolocation(std::make_shared<SimpleCoordinates>(0.0, 0.0));
+    }
+    m_geolocation->setLongitude(longitude);
+}
+
+double VideoContent::getLongitude()
+{
+    return m_geolocation->getLongitude();
+}
+
+std::string VideoContent::getAlbum() const
+{
+    return m_album;
+}
+
+void VideoContent::setAlbum(std::string album)
+{
+    m_album = album;
+}
+
+std::vector<std::string> VideoContent::getArtists() const
+{
+    return m_artists;
+}
+
+void VideoContent::setArtists(std::vector<std::string> artists)
+{
+    m_artists = artists;
+}
+
+unsigned long VideoContent::getDuration() const
+{
+    return m_duration;
+}
+
+void VideoContent::setDuration(unsigned long duration)
+{
+    m_duration = duration;
+}
+
+unsigned long VideoContent::getWidth() const
+{
+    return m_width;
+}
+
+void VideoContent::setWidth(unsigned long width)
+{
+    m_width = width;
+}
+
+unsigned long VideoContent::getHeight() const
+{
+    return m_height;
+}
+
+void VideoContent::setHeight(unsigned long height)
+{
+    m_height = height;
+}
+
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/VideoContent.h b/src/Content/VideoContent.h
new file mode 100755 (executable)
index 0000000..1466557
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_VIDEO_CONTENT_H__
+#define __TIZEN_VIDEO_CONTENT_H__
+
+#include <MultiCallbackUserData.h>
+#include <SimpleCoordinates.h>
+
+#include "ContentTypes.h"
+#include "Content.h"
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Content {
+
+class VideoContent;
+typedef std::shared_ptr<VideoContent> VideoContentPtr;
+
+class VideoContent : public Content
+{
+public:
+    VideoContent();
+    virtual ~VideoContent();
+
+    SimpleCoordinatesPtr getGeolocation() const;
+    void setGeolocation(SimpleCoordinatesPtr geolocation);
+    bool isGeolocationSet() const;
+    void unsetGeolocation();
+
+    void setLatitude(double latitude);
+    double getLatitude();
+
+    void setLongitude(double longitude);
+    double getLongitude();
+
+    std::string getAlbum() const;
+    void setAlbum(std::string album);
+
+    std::vector<std::string> getArtists() const;
+    void setArtists(std::vector<std::string> artists);
+
+    unsigned long getDuration() const;
+    void setDuration(unsigned long duration);
+
+    unsigned long getWidth() const;
+    void setWidth(unsigned long width);
+
+    unsigned long getHeight() const;
+    void setHeight(unsigned long height);
+
+private:
+    std::string m_album;
+    std::vector<std::string> m_artists;
+    unsigned long m_duration;
+    unsigned long m_width;
+    unsigned long m_height;
+    SimpleCoordinatesPtr m_geolocation;
+    bool m_is_geolocation_set;
+};
+
+} // Content
+} // DeviceAPI
+
+#endif // __TIZEN_VIDEO_CONTENT_H__
diff --git a/src/Content/config.xml b/src/Content/config.xml
new file mode 100644 (file)
index 0000000..764de21
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-content.so</library-name>
+    <feature-install-uri>content.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/content.write</name>
+        <device-capability>content.write</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/content.read</name>
+        <device-capability>content.read</device-capability>
+    </api-feature>
+
+</plugin-properties>
\ No newline at end of file
diff --git a/src/Content/plugin_config.cpp b/src/Content/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..7a8aca0
--- /dev/null
@@ -0,0 +1,283 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+
+#define CONTENT_FEATURE_API_READ  "http://tizen.org/privilege/content.read"
+#define CONTENT_FEATURE_API_WRITE "http://tizen.org/privilege/content.write"
+
+#define CONTENT_DEVICE_CAP_READ "content.read"
+#define CONTENT_DEVICE_CAP_WRITE "content.write"
+
+namespace DeviceAPI {
+namespace Content {
+
+// Extern variables declared in plugin_config.h
+#pragma GCC visibility push(default)
+const int CONTENT_TIME_TRACER_SHOW = 0;
+const char* CONTENT_TT_UPDATE_BATCH_TOTAL = "updateBatchTotal";
+const char* CONTENT_TT_SCAN_FILE_TOTAL = "scanFileTotal";
+const char* CONTENT_TT_FIND_TOTAL = "findTotal";
+const char* CONTENT_TT_GET_DIR_TOTAL = "getDirectoriesTotal";
+#pragma GCC visibility pop(default)
+
+static FunctionMapping createContentFunctions();
+static FunctionMapping ContentFunctions = createContentFunctions();
+
+#pragma GCC visibility push(default)
+DEFINE_FUNCTION_GETTER(Content, ContentFunctions);
+#pragma GCC visibility pop(default)
+
+static FunctionMapping createContentFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_CONTENT_READ, CONTENT_DEVICE_CAP_READ);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_CONTENT_WRITE, CONTENT_DEVICE_CAP_WRITE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_CONTENT_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_CONTENT_READ, DEVICE_CAP_CONTENT_READ);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_CONTENT_WRITE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_CONTENT_WRITE, DEVICE_CAP_CONTENT_WRITE);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_CONTENT_READ, CONTENT_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_CONTENT_WRITE, CONTENT_FEATURE_API_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(CONTENT_FEATURES_CONTENT_READ);
+    ACE_ADD_API_FEATURE(CONTENT_FEATURES_CONTENT_READ, FEATURE_CONTENT_READ);
+
+    ACE_CREATE_FEATURE_LIST(CONTENT_FEATURES_CONTENT_WRITE);
+    ACE_ADD_API_FEATURE(CONTENT_FEATURES_CONTENT_WRITE, FEATURE_CONTENT_WRITE);
+
+    FunctionMapping contentMapping;
+
+    //find
+    AceFunction findFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_FIND,
+            CONTENT_MANAGER_API_FIND,
+            CONTENT_FEATURES_CONTENT_READ,
+            DEVICE_LIST_CONTENT_READ);
+
+    contentMapping.insert(std::make_pair(
+            CONTENT_MANAGER_API_FIND,
+            findFunc));
+
+    //update
+    AceFunction updateFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UPDATE,
+            CONTENT_MANAGER_API_UPDATE,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            CONTENT_MANAGER_API_UPDATE,
+            updateFunc));
+
+    //updateBatch
+    AceFunction updateBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UPDATE_BATCH,
+            CONTENT_MANAGER_API_UPDATE_BATCH,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            CONTENT_MANAGER_API_UPDATE_BATCH,
+            updateBatchFunc));
+
+    //scanFile
+    AceFunction scanFileFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SCAN_FILE,
+            CONTENT_MANAGER_API_SCAN_FILE,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            CONTENT_MANAGER_API_SCAN_FILE,
+            scanFileFunc));
+
+    //setChangeListener
+    AceFunction setListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_CHANGE_LISTENER,
+            CONTENT_MANAGER_API_SET_CHANGE_LISTENER,
+            CONTENT_FEATURES_CONTENT_READ,
+            DEVICE_LIST_CONTENT_READ);
+
+    contentMapping.insert(std::make_pair(
+            CONTENT_MANAGER_API_SET_CHANGE_LISTENER,
+            setListenerFunc));
+
+    //unsetChangeListener
+    AceFunction unsetListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UNSET_CHANGE_LISTENER,
+            CONTENT_MANAGER_API_UNSET_CHANGE_LISTENER,
+            CONTENT_FEATURES_CONTENT_READ,
+            DEVICE_LIST_CONTENT_READ);
+
+    contentMapping.insert(std::make_pair(
+            CONTENT_MANAGER_API_UNSET_CHANGE_LISTENER,
+            unsetListenerFunc));
+
+    //getPlaylists
+    AceFunction getPlaylistsFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_PLAYLISTS,
+            CONTENT_MANAGER_API_GET_PLAYLISTS,
+            CONTENT_FEATURES_CONTENT_READ,
+            DEVICE_LIST_CONTENT_READ);
+
+    contentMapping.insert(std::make_pair(
+            CONTENT_MANAGER_API_GET_PLAYLISTS,
+            getPlaylistsFunc));
+
+    //createPlaylist
+    AceFunction createPlaylistFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CREATE_PLAYLIST,
+            CONTENT_MANAGER_API_CREATE_PLAYLIST,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            CONTENT_MANAGER_API_CREATE_PLAYLIST,
+            createPlaylistFunc));
+
+    //removePlaylist
+    AceFunction removePlaylistFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_PLAYLIST,
+            CONTENT_MANAGER_API_REMOVE_PLAYLIST,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            CONTENT_MANAGER_API_REMOVE_PLAYLIST,
+            removePlaylistFunc));
+
+    // add
+    AceFunction addFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD,
+            PLAYLIST_FUNCTION_API_ADD,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            PLAYLIST_FUNCTION_API_ADD,
+            addFunc));
+
+    // addBatch
+    AceFunction addBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD_BATCH,
+            PLAYLIST_FUNCTION_API_ADD_BATCH,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            PLAYLIST_FUNCTION_API_ADD_BATCH,
+            addBatchFunc));
+
+    // remove
+    AceFunction removeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE,
+            PLAYLIST_FUNCTION_API_REMOVE,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            PLAYLIST_FUNCTION_API_REMOVE,
+            removeFunc));
+
+    // removeBatch
+    AceFunction removeBatchFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE_BATCH,
+            PLAYLIST_FUNCTION_API_REMOVE_BATCH,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            PLAYLIST_FUNCTION_API_REMOVE_BATCH,
+            removeBatchFunc));
+
+    // getItems
+    AceFunction getItemsFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_ITEMS,
+            PLAYLIST_FUNCTION_API_GET_ITEMS,
+            CONTENT_FEATURES_CONTENT_READ,
+            DEVICE_LIST_CONTENT_READ);
+
+    contentMapping.insert(std::make_pair(
+            PLAYLIST_FUNCTION_API_GET_ITEMS,
+            getItemsFunc));
+
+    // moveItem
+    AceFunction moveItemFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_ORDER,
+            PLAYLIST_FUNCTION_API_MOVE_ITEM,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            PLAYLIST_FUNCTION_API_MOVE_ITEM,
+            moveItemFunc));
+
+    // setItemsOrder
+    AceFunction setItemsOrderFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_ORDER,
+            PLAYLIST_FUNCTION_API_SET_ITEMS_ORDER,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            PLAYLIST_FUNCTION_API_SET_ITEMS_ORDER,
+            setItemsOrderFunc));
+
+    // setName
+    AceFunction setNameFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_NAME,
+            PLAYLIST_FUNCTION_API_SET_NAME,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            PLAYLIST_FUNCTION_API_SET_NAME,
+            setNameFunc));
+
+    // setThumbnailURI
+    AceFunction setThumbnailURIFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_THUMBNAIL_URI,
+            PLAYLIST_FUNCTION_API_SET_THUMBNAIL_URI,
+            CONTENT_FEATURES_CONTENT_WRITE,
+            DEVICE_LIST_CONTENT_WRITE);
+
+    contentMapping.insert(std::make_pair(
+            PLAYLIST_FUNCTION_API_SET_THUMBNAIL_URI,
+            setThumbnailURIFunc));
+
+    return contentMapping;
+}
+
+} // Content
+} // DeviceAPI
diff --git a/src/Content/plugin_config.h b/src/Content/plugin_config.h
new file mode 100644 (file)
index 0000000..b3c17d5
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _CONTENT_PLUGIN_CONFIG_H_
+#define _CONTENT_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+#include <Logger.h>
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Content {
+
+extern const int CONTENT_TIME_TRACER_SHOW;
+extern const char* CONTENT_TT_UPDATE_BATCH_TOTAL;
+extern const char* CONTENT_TT_SCAN_FILE_TOTAL;
+extern const char* CONTENT_TT_FIND_TOTAL;
+extern const char* CONTENT_TT_GET_DIR_TOTAL;
+
+DECLARE_FUNCTION_GETTER(Content);
+
+#define CONTENT_CHECK_ACCESS(functionName) \
+        aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+                getContentFunctionData, \
+                functionName)
+
+}
+}
+
+#endif // _CONTENT_PLUGIN_CONFIG_H_
diff --git a/src/Content/plugin_config_impl.h b/src/Content/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..77edc3d
--- /dev/null
@@ -0,0 +1,95 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _CONTENT_PLUGIN_CONFIG_IMPL_H_
+#define _CONTENT_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_CONTENT_CONTENT_MANAGER_CLASS "content"
+
+#define TIZEN_PLAYLIST_PLAYLIST_INTERFACE "Playlist"
+#define TIZEN_PLAYLIST_PLAYLIST_ITEM_INTERFACE "PlaylistItem"
+
+// attributes
+#define CONTENT_DIRECTORY_ID "id"
+#define CONTENT_DIRECTORY_DIRECTORY_URI "directoryURI"
+#define CONTENT_DIRECTORY_TITLE "title"
+#define CONTENT_DIRECTORY_STORAGE_TYPE "storageType"
+#define CONTENT_DIRECTORY_MODIFIED_DATE "modifiedDate"
+#define CONTENT_EDITABLE_ATTRIBUTES "editableAttributes"
+#define CONTENT_ID "id"
+#define CONTENT_NAME "name"
+#define CONTENT_TYPE "type"
+#define CONTENT_MIME_TYPE "mimeType"
+#define CONTENT_TITLE "title"
+#define CONTENT_CONTENT_URI "contentURI"
+#define CONTENT_THUMBNAIL_URIS "thumbnailURIs"
+#define CONTENT_RELEASE_DATE "releaseDate"
+#define CONTENT_MODIFIED_DATE "modifiedDate"
+#define CONTENT_SIZE "size"
+#define CONTENT_DESCRIPTION "description"
+#define CONTENT_RATING "rating"
+#define CONTENT_IS_FAVORITE "isFavorite"
+#define VIDEO_CONTENT_GEOLOCATION "geolocation"
+#define VIDEO_CONTENT_ALBUM "album"
+#define VIDEO_CONTENT_ARTISTS "artists"
+#define VIDEO_CONTENT_DURATION "duration"
+#define VIDEO_CONTENT_WIDTH "width"
+#define VIDEO_CONTENT_HEIGHT "height"
+#define AUDIO_CONTENT_LYRICS_TYPE "type"
+#define AUDIO_CONTENT_LYRICS_TIMESTAMPS "timestamps"
+#define AUDIO_CONTENT_LYRICS_TEXTS "texts"
+#define AUDIO_CONTENT_ALBUM "album"
+#define AUDIO_CONTENT_GENRES "genres"
+#define AUDIO_CONTENT_ARTISTS "artists"
+#define AUDIO_CONTENT_COMPOSERS "composers"
+#define AUDIO_CONTENT_LYRICS "lyrics"
+#define AUDIO_CONTENT_COPYRIGHT "copyright"
+#define AUDIO_CONTENT_BITRATE "bitrate"
+#define AUDIO_CONTENT_TRACK_NUMBER "trackNumber"
+#define AUDIO_CONTENT_DURATION "duration"
+#define IMAGE_CONTENT_GEOLOCATION "geolocation"
+#define IMAGE_CONTENT_WIDTH "width"
+#define IMAGE_CONTENT_HEIGHT "height"
+#define IMAGE_CONTENT_ORIENTATION "orientation"
+
+// functions
+#define CONTENT_FUNCTION_API_GET_LOCAL_MEDIASOURCE "getLocalMediaSource"
+#define CONTENT_MANAGER_API_UPDATE "update"
+#define CONTENT_MANAGER_API_UPDATE_BATCH "updateBatch"
+#define CONTENT_MANAGER_API_GET_DIRECTORIES "getDirectories"
+#define CONTENT_MANAGER_API_FIND "find"
+#define CONTENT_MANAGER_API_SCAN_FILE "scanFile"
+#define CONTENT_MANAGER_API_SET_CHANGE_LISTENER "setChangeListener"
+#define CONTENT_MANAGER_API_UNSET_CHANGE_LISTENER "unsetChangeListener"
+
+#define CONTENT_MANAGER_API_GET_PLAYLISTS "getPlaylists"
+#define CONTENT_MANAGER_API_CREATE_PLAYLIST "createPlaylist"
+#define CONTENT_MANAGER_API_REMOVE_PLAYLIST "removePlaylist"
+
+/* Playlist */
+#define PLAYLIST_FUNCTION_API_ADD "add"
+#define PLAYLIST_FUNCTION_API_ADD_BATCH "addBatch"
+#define PLAYLIST_FUNCTION_API_REMOVE "remove"
+#define PLAYLIST_FUNCTION_API_REMOVE_BATCH "removeBatch"
+#define PLAYLIST_FUNCTION_API_GET_ITEMS "get"
+#define PLAYLIST_FUNCTION_API_MOVE_ITEM "move"
+#define PLAYLIST_FUNCTION_API_SET_ITEMS_ORDER "setOrder"
+#define PLAYLIST_FUNCTION_API_SET_NAME "setName"
+#define PLAYLIST_FUNCTION_API_SET_THUMBNAIL_URI "setThumbnailURI"
+
+#endif // _CONTENT_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/Content/plugin_initializer.cpp b/src/Content/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..8d22f43
--- /dev/null
@@ -0,0 +1,124 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+
+#include "JSPlaylist.h"
+#include "JSContentManager.h"
+#include "ContentManager.h"
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Content {
+
+using namespace DeviceAPI::Common;
+
+AceSecurityStatus contentAceCheckAccessFunction(const char* functionName)
+{
+    return CONTENT_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerCalendarSetter, ContentManager, gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerContentSetter,
+        ContentManager,
+        gSecurityAccessor);
+
+class_definition_options_t ContentOption =
+{
+        JS_CLASS,
+        CREATE_INSTANCE,
+        ALWAYS_NOTICE,
+        USE_OVERLAYED, //ignored
+        AceCheckerCalendarSetter,
+        NULL,
+        NULL
+};
+
+class_definition_options_t ContentInterfaceOptions = {
+        JS_INTERFACE,
+        CREATE_INSTANCE,
+        NONE_NOTICE,
+        USE_OVERLAYED, //ignored
+        NULL, // JSWidget::acquireGlobalContext,
+        NULL,
+        NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Content] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch(...) {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, contentAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Content] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "Content";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch(...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Content] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Content] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_CONTENT_CONTENT_MANAGER_CLASS,
+        (js_class_template_getter)JSContentManager::getClassRef,
+        &ContentOption)
+PLUGIN_CLASS_MAP_END
+
+} // Content
+} // DeviceAPI
diff --git a/src/DataControl/CMakeLists.txt b/src/DataControl/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..b17747e
--- /dev/null
@@ -0,0 +1,62 @@
+SET(TARGET_NAME ${datacontrol_target})
+SET(DESTINATION_NAME ${datacontrol_dest})
+SET(TARGET_IMPL_NAME ${datacontrol_impl})
+
+IF(ENABLE_OPTIONAL_DATA_CONTROL)
+PKG_SEARCH_MODULE(datacontrol REQUIRED capi-data-control)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${datacontrol_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    DataControlCallback.cpp
+    DataControlConsumer.cpp
+    DataControlGetValueCallback.cpp
+    DataControlInsertCallback.cpp
+    DataControlMapCallback.cpp
+    DataControlSelectCallback.cpp
+    DataControlSQLCallback.cpp
+    MappedDataControlConsumer.cpp
+    SQLDataControlConsumer.cpp
+    JSDataControlManager.cpp
+    JSDataControlConsumer.cpp
+    JSSQLDataControlConsumer.cpp
+    JSMappedDataControlConsumer.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${datacontrol_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_DATA_CONTROL)
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/datacontrol
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/DataControl/DataControlCallback.cpp b/src/DataControl/DataControlCallback.cpp
new file mode 100755 (executable)
index 0000000..18fb680
--- /dev/null
@@ -0,0 +1,139 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "DataControlCallback.h"
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataControl {
+
+DataControlCallback::DataControlCallback(DataControlRequestType type,
+        JSContextRef global_ctx):
+        CallbackUserData(global_ctx),
+        m_request_id(0),
+        m_request_type(type),
+        m_is_error(false)
+{
+    LOGD("Entered");
+}
+
+DataControlCallback::~DataControlCallback()
+{
+    LOGD("Entered");
+}
+
+void DataControlCallback::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool DataControlCallback::isError() const
+{
+    return m_is_error;
+}
+
+std::string DataControlCallback::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string DataControlCallback::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void DataControlCallback::setRequestId(unsigned long req_id)
+{
+    m_request_id = req_id;
+}
+
+unsigned long DataControlCallback::getRequestId() const
+{
+    return m_request_id;
+}
+
+void DataControlCallback::setDataId(const std::string &data_id)
+{
+    m_data_id = data_id;
+}
+
+std::string DataControlCallback::getDataId() const
+{
+    return m_data_id;
+}
+
+void DataControlCallback::setProviderId(const std::string &provider_id)
+{
+    m_provider_id = provider_id;
+}
+
+std::string DataControlCallback::getProviderId() const
+{
+    return m_provider_id;
+}
+
+void DataControlCallback::setProvider(data_control_h provider)
+{
+    m_provider = provider;
+}
+
+data_control_h DataControlCallback::getProvider() const
+{
+    return m_provider;
+}
+
+void DataControlCallback::callErrorCallbackWithArguments()
+{
+    LOGD("Calling error callback");
+    if( !GlobalContextManager::getInstance()->isAliveGlobalContext(getContext())){
+        LOGE("context was closed");
+        return;
+    }
+    JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(getContext(),
+            getErrorName(),
+            getErrorMessage());
+    JSValueRef arguments[2];
+    arguments[0] = JSUtil::toJSValueRef(getContext(),
+            getRequestId());
+    arguments[1] = errobj;
+    callErrorCallback(2, arguments);
+}
+
+void DataControlCallback::callSuccessCallbackWithArguments()
+{
+    LOGD("Calling success callback");
+    callSuccessCallback(JSUtil::toJSValueRef(getContext(), getRequestId()));
+}
+
+DataControlRequestType DataControlCallback::getRequestType() const
+{
+    return m_request_type;
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/DataControlCallback.h b/src/DataControl/DataControlCallback.h
new file mode 100755 (executable)
index 0000000..3fa4ddf
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DATA_CONTROL_CALLBACK_H__
+#define __TIZEN_DATA_CONTROL_CALLBACK_H__
+
+#include <CallbackUserData.h>
+#include <data_control.h>
+#include <string>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+enum DataControlRequestType
+{
+    DATACONTROL_REQUEST_TYPE_UNDEFINED = 0,
+    DATACONTROL_REQUEST_TYPE_SQL_QUERY,
+    DATACONTROL_REQUEST_TYPE_SQL_INSERT,
+    DATACONTROL_REQUEST_TYPE_SQL_UPDATE,
+    DATACONTROL_REQUEST_TYPE_SQL_DELETE,
+    DATACONTROL_REQUEST_TYPE_MAP_QUERY,
+    DATACONTROL_REQUEST_TYPE_MAP_INSERT,
+    DATACONTROL_REQUEST_TYPE_MAP_UPDATE,
+    DATACONTROL_REQUEST_TYPE_MAP_DELETE
+};
+
+class DataControlCallback: public Common::CallbackUserData {
+public:
+    DataControlCallback(DataControlRequestType type, JSContextRef global_ctx);
+    virtual ~DataControlCallback();
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+    void setRequestId(unsigned long req_id);
+    unsigned long getRequestId() const;
+    void setDataId(const std::string &data_id);
+    std::string getDataId() const;
+    void setProviderId(const std::string &provider_id);
+    std::string getProviderId() const;
+    void setProvider(data_control_h provider);
+    data_control_h getProvider() const;
+    /**
+     * Calls error callback with arguments:
+     * 0: requestId
+     * 1: error object
+     */
+    void callErrorCallbackWithArguments();
+    virtual void callSuccessCallbackWithArguments();
+    DataControlRequestType getRequestType() const;
+private:
+    DataControlRequestType m_request_type;
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+    unsigned long m_request_id;
+    std::string m_provider_id;
+    std::string m_data_id;
+    data_control_h m_provider;
+};
+
+} //DataControl
+} //DeviceAPI
+
+#endif // __TIZEN_DATA_CONTROL_CALLBACK_H__
+
diff --git a/src/DataControl/DataControlConsumer.cpp b/src/DataControl/DataControlConsumer.cpp
new file mode 100755 (executable)
index 0000000..4bdc0ee
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "DataControlConsumer.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataControl {
+
+namespace {
+const char* MAP_DATA_CONTROL = "MAP";
+const char* SQL_DATA_CONTROL = "SQL";
+
+static const std::string ERR_DATA_CONTROL_OUT_OF_MEMORY = "Out of memory";
+static const std::string ERR_DATA_CONTROL_IO_ERROR = "I/O error";
+static const std::string ERR_DATA_CONTROL_INVALID_PARAMETER = "Invalid parameter";
+static const std::string ERR_DATA_CONTROL_PERMISSION_DENIED = "Permission denied";
+static const std::string ERR_DATA_CONTROL_MAX_EXCEEDED = "Too long argument";
+static const std::string ERR_DATA_CONTROL_UNKNOWN = "Unknown error";
+}
+
+const std::string& getDataControlErrorMessage(int errorCode)
+{
+    switch (errorCode) {
+        case DATA_CONTROL_ERROR_OUT_OF_MEMORY:
+            return ERR_DATA_CONTROL_OUT_OF_MEMORY;
+        case DATA_CONTROL_ERROR_IO_ERROR:
+            return ERR_DATA_CONTROL_IO_ERROR;
+        case DATA_CONTROL_ERROR_INVALID_PARAMETER:
+            return ERR_DATA_CONTROL_INVALID_PARAMETER;
+        case DATA_CONTROL_ERROR_PERMISSION_DENIED:
+            return ERR_DATA_CONTROL_PERMISSION_DENIED;
+        case DATA_CONTROL_ERROR_MAX_EXCEEDED:
+            return ERR_DATA_CONTROL_MAX_EXCEEDED;
+        default:
+            return ERR_DATA_CONTROL_UNKNOWN;
+    }
+}
+
+std::string getDataControlLogMessage(const int errorCode, const std::string &hint)
+{
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getDataControlErrorMessage(errorCode) << ", " << errorCode;
+    return ss.str();
+}
+
+DataControlConsumer::DataControlConsumer(DataControlType type,
+        const std::string &provider_id,
+        const std::string &data_id):
+        m_type(type), m_provider_id(provider_id), m_data_id(data_id),
+        m_data_control(NULL)
+{
+    LOGD("Enter");
+}
+
+DataControlConsumer::~DataControlConsumer()
+{
+    LOGD("Enter");
+}
+
+DataControlType DataControlConsumer::stringToType(const std::string &type)
+{
+    if (MAP_DATA_CONTROL == type) {
+        return DataControlType::Map;
+    }
+    if (SQL_DATA_CONTROL == type) {
+        return DataControlType::SQL;
+    }
+    LOGE("Invalid data control consumer type: %s", type.c_str());
+    throw TypeMismatchException("Invalid data control consumer type");
+}
+
+std::string DataControlConsumer::getTypeString() const
+{
+    switch (m_type) {
+        case DataControlType::Map:
+            return MAP_DATA_CONTROL;
+        case DataControlType::SQL:
+            return SQL_DATA_CONTROL;
+        default:
+            LOGE("Incorrect type: %d", m_type);
+            throw TypeMismatchException("Incorrect type");
+    }
+}
+
+std::string DataControlConsumer::getProviderId() const
+{
+    return m_provider_id;
+}
+
+std::string DataControlConsumer::getDataId() const
+{
+    return m_data_id;
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/DataControlConsumer.h b/src/DataControl/DataControlConsumer.h
new file mode 100755 (executable)
index 0000000..1f2bc44
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DATA_CONTROL_CONSUMER_H__
+#define __TIZEN_DATA_CONTROL_CONSUMER_H__
+
+#include "DataControlMapCallback.h"
+#include "DataControlGetValueCallback.h"
+#include "DataControlInsertCallback.h"
+#include "DataControlSelectCallback.h"
+
+#include <data_control.h>
+#include <string>
+#include <memory>
+
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+enum DataControlType {
+    Map,
+    SQL
+};
+
+class DataControlConsumer;//forward declaration
+// shared pointer with DataControlConsumer object
+typedef std::shared_ptr<DataControlConsumer> DataControlConsumerPtr;
+// struct for holding DataControlConsumer inside priv object
+struct DataControlConsumerHolder {
+    DataControlConsumerPtr ptr;
+};
+
+class DataControlConsumer {
+public:
+    DataControlConsumer(DataControlType type,
+            const std::string &provider_id,
+            const std::string &data_id);
+    virtual ~DataControlConsumer();
+    static DataControlType stringToType(const std::string &type);
+    virtual std::string getTypeString() const;
+    virtual std::string getProviderId() const;
+    virtual std::string getDataId() const;
+private:
+    DataControlType m_type;
+    std::string m_provider_id;
+    std::string m_data_id;
+protected:
+    data_control_h m_data_control;
+};
+
+const std::string& getDataControlErrorMessage(int errorCode);
+std::string getDataControlLogMessage(const int errorCode, const std::string &hint);
+
+template <class T = DeviceAPI::Common::UnknownException>
+void throwDataControlException(const int errorCode, const std::string &hint)
+{
+    std::string log = getDataControlLogMessage(errorCode, hint);
+    LOGE("%s", log.c_str());
+    throw T(log.c_str());
+}
+
+} //DataControl
+} //DeviceAPI
+
+#endif // __TIZEN_DATA_CONTROL_CONSUMER_H__
diff --git a/src/DataControl/DataControlGetValueCallback.cpp b/src/DataControl/DataControlGetValueCallback.cpp
new file mode 100755 (executable)
index 0000000..e2e6efb
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "DataControlGetValueCallback.h"
+#include <GlobalContextManager.h>
+#include <fstream>
+#include <JSUtil.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataControl {
+
+DataControlGetValueCallback::DataControlGetValueCallback(JSContextRef global_ctx):
+        DataControlMapCallback(DATACONTROL_REQUEST_TYPE_MAP_QUERY, global_ctx)
+{
+    LOGD("Entered");
+}
+
+DataControlGetValueCallback::~DataControlGetValueCallback()
+{
+    LOGD("Entered");
+}
+
+std::vector<std::string> DataControlGetValueCallback::getValues() const
+{
+    return m_values;
+}
+
+void DataControlGetValueCallback::setValues(std::vector<std::string> values) {
+    m_values = values;
+}
+
+void DataControlGetValueCallback::callSuccessCallbackWithArguments()
+{
+    JSValueRef arguments[2];
+    if( !GlobalContextManager::getInstance()->isAliveGlobalContext(getContext())){
+        LOGE("context was closed");
+        return;
+    }
+    arguments[0] = JSUtil::toJSValueRef(getContext(), m_values);
+    arguments[1] = JSUtil::toJSValueRef(getContext(), getRequestId());
+    callSuccessCallback(2, arguments);
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/DataControlGetValueCallback.h b/src/DataControl/DataControlGetValueCallback.h
new file mode 100755 (executable)
index 0000000..459c7af
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DATA_CONTROL_GET_VALUE_CALLBACK_H__
+#define __TIZEN_DATA_CONTROL_GET_VALUE_CALLBACK_H__
+
+#include "DataControlMapCallback.h"
+#include <vector>
+#include <string>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class DataControlGetValueCallback: public DataControlMapCallback {
+public:
+    DataControlGetValueCallback(JSContextRef global_ctx);
+    virtual ~DataControlGetValueCallback();
+    std::vector<std::string> getValues() const;
+    void setValues(std::vector<std::string> values);
+    void callSuccessCallbackWithArguments();
+private:
+    std::vector<std::string> m_values;
+};
+
+} //DataControl
+} //DeviceAPI
+
+#endif //__TIZEN_DATA_CONTROL_GET_VALUE_CALLBACK_H__
+
diff --git a/src/DataControl/DataControlInsertCallback.cpp b/src/DataControl/DataControlInsertCallback.cpp
new file mode 100755 (executable)
index 0000000..ce51baa
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "DataControlInsertCallback.h"
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataControl {
+
+DataControlInsertCallback::DataControlInsertCallback(JSContextRef global_ctx):
+        DataControlSQLCallback(DATACONTROL_REQUEST_TYPE_SQL_INSERT, global_ctx)
+{
+    LOGD("Entered");
+}
+
+DataControlInsertCallback::~DataControlInsertCallback()
+{
+    LOGD("Entered");
+}
+
+void DataControlInsertCallback::setInsertRowId(long row_id)
+{
+    m_insert_row_id = row_id;
+}
+
+long DataControlInsertCallback::getInsertRowId() const
+{
+    return m_insert_row_id;
+}
+
+void DataControlInsertCallback::callSuccessCallbackWithArguments()
+{
+    LOGD("Calling success callback");
+    if( !GlobalContextManager::getInstance()->isAliveGlobalContext(getContext())){
+        LOGE("context was closed");
+        return;
+    }
+    JSValueRef arguments[2];
+    arguments[0] = JSUtil::toJSValueRef(getContext(), getRequestId());
+    arguments[1] = JSUtil::toJSValueRef(getContext(), getInsertRowId());
+    callSuccessCallback(2, arguments);
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/DataControlInsertCallback.h b/src/DataControl/DataControlInsertCallback.h
new file mode 100755 (executable)
index 0000000..5fe39c9
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DATA_CONTROL_INSERT_CALLBACK_H__
+#define __TIZEN_DATA_CONTROL_INSERT_CALLBACK_H__
+
+#include "DataControlSQLCallback.h"
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class DataControlInsertCallback: public DataControlSQLCallback {
+public:
+    DataControlInsertCallback(JSContextRef global_ctx);
+    virtual ~DataControlInsertCallback();
+    void setInsertRowId(long row_id);
+    long getInsertRowId() const;
+    void callSuccessCallbackWithArguments();
+private:
+    long m_insert_row_id;
+};
+
+} //DataControl
+} //DeviceAPI
+
+#endif //__TIZEN_DATA_CONTROL_INSERT_CALLBACK_H__
+
diff --git a/src/DataControl/DataControlMapCallback.cpp b/src/DataControl/DataControlMapCallback.cpp
new file mode 100755 (executable)
index 0000000..afc012b
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "DataControlMapCallback.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+DataControlMapCallback::DataControlMapCallback(DataControlRequestType type,
+        JSContextRef global_ctx):
+        DataControlCallback(type, global_ctx)
+{
+    LOGD("Entered");
+}
+
+DataControlMapCallback::~DataControlMapCallback()
+{
+    LOGD("Entered");
+}
+
+void DataControlMapCallback::setNewValue(const std::string &new_value)
+{
+    m_new_value = new_value;
+}
+
+std::string DataControlMapCallback::getNewValue() const
+{
+    return m_new_value;
+}
+
+void DataControlMapCallback::setValue(const std::string &value)
+{
+    m_value = value;
+}
+
+std::string DataControlMapCallback::getValue() const
+{
+    return m_value;
+}
+
+void DataControlMapCallback::setKey(const std::string &key)
+{
+    m_key = key;
+}
+
+std::string DataControlMapCallback::getKey() const
+{
+    return m_key;
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/DataControlMapCallback.h b/src/DataControl/DataControlMapCallback.h
new file mode 100755 (executable)
index 0000000..87513ab
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DATA_CONTROL_MAP_CALLBACK_H__
+#define __TIZEN_DATA_CONTROL_MAP_CALLBACK_H__
+
+#include "DataControlCallback.h"
+#include <string>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class DataControlMapCallback: public DataControlCallback {
+public:
+    DataControlMapCallback(DataControlRequestType type, JSContextRef global_ctx);
+    virtual ~DataControlMapCallback();
+    void setNewValue(const std::string &new_value);
+    std::string getNewValue() const;
+    void setValue(const std::string &value);
+    std::string getValue() const;
+    void setKey(const std::string &key);
+    std::string getKey() const;
+private:
+    std::string m_key;
+    std::string m_value;
+    //only for updateValue
+    std::string m_new_value;
+};
+
+} //DataControl
+} //DeviceAPI
+
+#endif //__TIZEN_DATA_CONTROL_MAP_CALLBACK_H__
+
diff --git a/src/DataControl/DataControlSQLCallback.cpp b/src/DataControl/DataControlSQLCallback.cpp
new file mode 100755 (executable)
index 0000000..26e46ea
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "DataControlSQLCallback.h"
+#include <GlobalContextManager.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+const char* RowDataPropertyColumns = "columns";
+const char* RowDataPropertyValues = "values";
+
+DataControlSQLCallback::DataControlSQLCallback(DataControlRequestType type,
+        JSContextRef global_ctx):
+        DataControlCallback(type, global_ctx)
+{
+    LOGD("Entered");
+}
+
+DataControlSQLCallback::~DataControlSQLCallback()
+{
+    LOGD("Entered");
+}
+
+void DataControlSQLCallback::setRowData(RowDataPtr row_data)
+{
+    m_row_data = row_data;
+}
+
+RowDataPtr DataControlSQLCallback::getRowData() const
+{
+    return m_row_data;
+}
+
+void DataControlSQLCallback::setWhere(const std::string &where)
+{
+    m_where = where;
+}
+
+std::string DataControlSQLCallback::getWhere() const
+{
+    return m_where;
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/DataControlSQLCallback.h b/src/DataControl/DataControlSQLCallback.h
new file mode 100755 (executable)
index 0000000..59be985
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DATA_CONTROL_SQL_CALLBACK_H__
+#define __TIZEN_DATA_CONTROL_SQL_CALLBACK_H__
+
+#include "DataControlCallback.h"
+#include <string>
+#include <memory>
+#include <map>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+typedef std::map<std::string, std::string> RowData;
+typedef std::shared_ptr<RowData> RowDataPtr;
+extern const char* RowDataPropertyColumns;
+extern const char* RowDataPropertyValues;
+
+class DataControlSQLCallback: public DataControlCallback {
+public:
+    DataControlSQLCallback(DataControlRequestType type, JSContextRef global_ctx);
+    virtual ~DataControlSQLCallback();
+    void setRowData(RowDataPtr row_data);
+    RowDataPtr getRowData() const;
+    void setWhere(const std::string &where);
+    std::string getWhere() const;
+private:
+    //for insert, update operations
+    RowDataPtr m_row_data;
+    //for select, update, remove operations
+    std::string m_where;
+};
+
+} //DataControl
+} //DeviceAPI
+
+#endif //__TIZEN_DATA_CONTROL_SQL_CALLBACK_H__
+
diff --git a/src/DataControl/DataControlSelectCallback.cpp b/src/DataControl/DataControlSelectCallback.cpp
new file mode 100755 (executable)
index 0000000..d0cd138
--- /dev/null
@@ -0,0 +1,160 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "DataControlSelectCallback.h"
+#include <GlobalContextManager.h>
+#include <fstream>
+#include <JSUtil.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataControl {
+
+DataControlSelectCallback::DataControlSelectCallback(JSContextRef global_ctx):
+        DataControlSQLCallback(DATACONTROL_REQUEST_TYPE_SQL_QUERY, global_ctx),
+        m_page_is_set(false),
+        m_page(0),
+        m_max_number_is_set(false),
+        m_max_number_per_page(0)
+{
+    LOGD("Entered");
+}
+
+DataControlSelectCallback::~DataControlSelectCallback()
+{
+    LOGD("Entered");
+}
+
+void DataControlSelectCallback::setMaxNumberPerPage(unsigned long max_number_per_page)
+{
+    m_max_number_is_set = true;
+    m_max_number_per_page = max_number_per_page;
+}
+
+unsigned long DataControlSelectCallback::getMaxNumberPerPage() const
+{
+    return m_max_number_per_page;
+}
+
+bool DataControlSelectCallback::isMaxNumberPageSet() const
+{
+    return m_max_number_is_set;
+}
+
+void DataControlSelectCallback::setPage(unsigned long page)
+{
+    m_page_is_set = true;
+    m_page = page;
+}
+
+unsigned long DataControlSelectCallback::getPage() const
+{
+    return m_page;
+}
+
+bool DataControlSelectCallback::isPageSet() const
+{
+    return m_page_is_set;
+}
+
+void DataControlSelectCallback::setColumns(const std::vector<std::string> &columns)
+{
+    m_columns = columns;
+}
+
+const std::vector<std::string>& DataControlSelectCallback::getColumns() const
+{
+    return m_columns;
+}
+
+bool DataControlSelectCallback::isEmptyColumns() const
+{
+    return m_columns.empty();
+}
+
+void DataControlSelectCallback::setColumnsNames(std::vector<std::string> columns_names)
+{
+    m_columns = columns_names;
+}
+
+std::vector<std::string> DataControlSelectCallback::getColumnsNames() const
+{
+    return m_columns;
+}
+
+void DataControlSelectCallback::setResultRows(std::vector<std::vector<std::string>> rows)
+{
+    m_result_rows = rows;
+}
+
+std::vector<std::vector<std::string>> DataControlSelectCallback::getResultRows() const
+{
+    return m_result_rows;
+}
+
+JSValueRef DataControlSelectCallback::resultArrayToJs()
+{
+    LOGD("Enter");
+    const unsigned int size = m_result_rows.size();
+    JSValueRef rows[size];
+    if (size > 0) {
+        //cache columns array, it's the same in all rows
+        JSValueRef jsColumns = JSUtil::toJSValueRef(getContext(), m_columns);
+
+        for (unsigned int i = 0; i < size; ++i) {
+            JSObjectRef row = JSObjectMake(getContext(), NULL, NULL);
+            //create object with properties: columns and values
+            JSUtil::setProperty(getContext(),
+                    row,
+                    RowDataPropertyColumns,
+                    jsColumns,
+                    kJSPropertyAttributeNone);
+            JSUtil::setProperty(getContext(),
+                    row,
+                    RowDataPropertyValues,
+                    JSUtil::toJSValueRef(getContext(), m_result_rows[i]),
+                    kJSPropertyAttributeNone);
+            rows[i] = row;
+        }
+    }
+    JSValueRef exception = NULL;
+    JSObjectRef resultArray = JSObjectMakeArray(getContext(), size, rows, &exception);
+    if (exception != NULL) {
+        LOGE("Failed to create result array");
+        throw UnknownException(getContext(), exception);
+    }
+    return resultArray;
+}
+
+void DataControlSelectCallback::callSuccessCallbackWithArguments()
+{
+    LOGD("Enter");
+    if( !GlobalContextManager::getInstance()->isAliveGlobalContext(getContext())){
+        LOGE("context was closed");
+        return;
+    }
+    JSValueRef arguments[2];
+    arguments[0] = resultArrayToJs();
+    arguments[1] = JSUtil::toJSValueRef(getContext(), getRequestId());
+    callSuccessCallback(2, arguments);
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/DataControlSelectCallback.h b/src/DataControl/DataControlSelectCallback.h
new file mode 100755 (executable)
index 0000000..07aad01
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DATA_CONTROL_SELECT_CALLBACK_H__
+#define __TIZEN_DATA_CONTROL_SELECT_CALLBACK_H__
+
+#include "DataControlSQLCallback.h"
+#include <JavaScriptCore/JavaScript.h>
+#include <vector>
+#include <string>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class DataControlSelectCallback: public DataControlSQLCallback {
+public:
+    DataControlSelectCallback(JSContextRef global_ctx);
+    virtual ~DataControlSelectCallback();
+    void setMaxNumberPerPage(unsigned long max_number_per_page);
+    unsigned long getMaxNumberPerPage() const;
+    bool isMaxNumberPageSet() const;
+    void setPage(unsigned long page);
+    unsigned long getPage() const;
+    bool isPageSet() const;
+    void setColumns(const std::vector<std::string> &columns);
+    const std::vector<std::string>& getColumns() const;
+    bool isEmptyColumns() const;
+    void callSuccessCallbackWithArguments();
+
+    void setColumnsNames(std::vector<std::string> columns_names);
+    std::vector<std::string> getColumnsNames() const;
+    void setResultRows(std::vector<std::vector<std::string>> rows);
+    std::vector<std::vector<std::string>> getResultRows() const;
+private:
+    /**
+     * Converts m_resultColumns and m_resultRows to RowData array.
+     * RowData is an object and has two properties: columns (array) and
+     * values (array)
+     * @return
+     */
+    JSValueRef resultArrayToJs();
+    bool m_page_is_set;
+    unsigned long m_page;
+    bool m_max_number_is_set;
+    unsigned long m_max_number_per_page;
+    std::vector<std::string> m_columns;
+    typedef std::vector<std::string> valuesVector;
+    std::vector<valuesVector> m_result_rows;
+};
+
+} //DataControl
+} //DeviceAPI
+
+#endif //__TIZEN_DATA_CONTROL_SELECT_CALLBACK_H__
+
diff --git a/src/DataControl/JSDataControlConsumer.cpp b/src/DataControl/JSDataControlConsumer.cpp
new file mode 100755 (executable)
index 0000000..ed52aeb
--- /dev/null
@@ -0,0 +1,172 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSDataControlConsumer.h"
+#include "plugin_config.h"
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataControl {
+
+namespace {
+const char* DATA_CONTROL_CONSUMER = "DataControlConsumer";
+const char* DATA_CONTROL_CONSUMER_TYPE = "type";
+const char* DATA_CONTROL_CONSUMER_PROVIDER_ID = "providerId";
+const char* DATA_CONTROL_CONSUMER_DATA_ID = "dataId";
+}
+
+JSClassRef JSDataControlConsumer::m_jsClassRef = NULL;
+
+JSClassDefinition JSDataControlConsumer::m_classInfo ={
+    0,
+    kJSClassAttributeNone,
+    DATA_CONTROL_CONSUMER,
+    NULL,
+    m_property,
+    NULL,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+JSStaticValue JSDataControlConsumer::m_property[] = {
+    {DATA_CONTROL_CONSUMER_TYPE,
+            getTypeProperty,
+            NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {DATA_CONTROL_CONSUMER_PROVIDER_ID,
+            getProviderIdProperty,
+            NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {DATA_CONTROL_CONSUMER_DATA_ID,
+            getDataIdProperty,
+            NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {0, 0, 0, 0}
+};
+
+const JSClassRef JSDataControlConsumer::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSDataControlConsumer::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSDataControlConsumer::initialize(JSContextRef context, JSObjectRef object)
+{
+}
+
+void JSDataControlConsumer::finalize(JSObjectRef object)
+{
+
+}
+
+DataControlConsumerPtr JSDataControlConsumer::getPrivateObject(
+        JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not SQLDataControlConsumer");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    DataControlConsumerHolder* priv = static_cast<DataControlConsumerHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+JSValueRef JSDataControlConsumer::getTypeProperty(JSContextRef context,
+    JSObjectRef object,
+    JSStringRef propertyName,
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        return JSUtil::toJSValueRef(context,
+                getPrivateObject(context, object)->getTypeString());
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSDataControlConsumer::getProviderIdProperty(JSContextRef context,
+    JSObjectRef object,
+    JSStringRef propertyName,
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        return JSUtil::toJSValueRef(context,
+                getPrivateObject(context, object)->getProviderId());
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSDataControlConsumer::getDataIdProperty(JSContextRef context,
+    JSObjectRef object,
+    JSStringRef propertyName,
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        return JSUtil::toJSValueRef(context,
+                getPrivateObject(context, object)->getDataId());
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} //DataControl
+} //DeviceAPI
\ No newline at end of file
diff --git a/src/DataControl/JSDataControlConsumer.h b/src/DataControl/JSDataControlConsumer.h
new file mode 100755 (executable)
index 0000000..0f2fb9c
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_DATACONTROL_CONSUMER_H__
+#define __TIZEN_JS_DATACONTROL_CONSUMER_H__
+
+#include "DataControlConsumer.h"
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class JSDataControlConsumer {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static DataControlConsumerPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+    static JSValueRef getTypeProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+    static JSValueRef getProviderIdProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+    static JSValueRef getDataIdProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+    static JSClassDefinition m_classInfo;
+    static JSStaticValue m_property[];
+    static JSClassRef m_jsClassRef;
+};
+
+} //DataControl
+} //DeviceAPI
+
+#endif //__TIZEN_JS_DATACONTROL_CONSUMER_H__
diff --git a/src/DataControl/JSDataControlManager.cpp b/src/DataControl/JSDataControlManager.cpp
new file mode 100755 (executable)
index 0000000..18366aa
--- /dev/null
@@ -0,0 +1,141 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSDataControlManager.h"
+#include "plugin_config.h"
+#include "JSMappedDataControlConsumer.h"
+#include "JSSQLDataControlConsumer.h"
+
+#include <ArgumentValidator.h>
+#include <SecurityExceptions.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <Logger.h>
+
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+
+namespace DeviceAPI {
+namespace DataControl {
+
+namespace {
+const char* DATA_CONTROL_MANAGER = "DataControlManager";
+const char* DATA_CONTROL_MANAGER_GET_DATA_CONTROL_CONSUMER =
+        "getDataControlConsumer";
+}
+
+JSClassRef JSDataControlManager::m_jsClassRef = NULL;
+
+JSClassDefinition JSDataControlManager::m_classInfo ={
+    0,
+    kJSClassAttributeNone,
+    DATA_CONTROL_MANAGER,
+    NULL,
+    NULL,
+    m_function,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+JSStaticFunction JSDataControlManager::m_function[] = {
+    {DATA_CONTROL_MANAGER_GET_DATA_CONTROL_CONSUMER,
+            getDataControlConsumer, kJSPropertyAttributeNone},
+    {0, 0, 0}
+};
+
+const JSClassRef DLL_EXPORT JSDataControlManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSDataControlManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSDataControlManager::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSDataControlManager::finalize(JSObjectRef object)
+{
+}
+
+JSValueRef JSDataControlManager::getDataControlConsumer(
+        JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = DATACONTROL_CHECK_ACCESS(DATACONTROL_FUNC_CONSUMER);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    JSValueRef ret;
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string provider_id = validator.toString(0);
+        std::string data_id = validator.toString(1);
+        std::string type = validator.toString(2);
+
+        DataControlType type_enum = DataControlConsumer::stringToType(type);
+        switch (type_enum) {
+            case DataControlType::Map:
+                ret = JSMappedDataControlConsumer::makeJSObject(
+                        context, provider_id, data_id, type);
+                break;
+            case DataControlType::SQL:
+                ret = JSSQLDataControlConsumer::makeJSObject(
+                        context, provider_id, data_id, type);
+                break;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown error, get data consumer");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return ret;
+}
+
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/JSDataControlManager.h b/src/DataControl/JSDataControlManager.h
new file mode 100755 (executable)
index 0000000..f059a72
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_JS_DATACONTROL_MANAGER_H__
+#define __TIZEN_JS_DATACONTROL_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class JSDataControlManager {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getDataControlConsumer(
+            JSContextRef context, JSObjectRef object,
+            JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+            JSValueRef* exception);
+
+
+    static JSClassDefinition m_classInfo;
+    static JSStaticFunction m_function[];
+    static JSClassRef m_jsClassRef;
+
+};
+
+}
+}
+
+#endif //__TIZEN_JS_DATACONTROL_MANAGER_H__
diff --git a/src/DataControl/JSMappedDataControlConsumer.cpp b/src/DataControl/JSMappedDataControlConsumer.cpp
new file mode 100755 (executable)
index 0000000..9dae513
--- /dev/null
@@ -0,0 +1,401 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "JSMappedDataControlConsumer.h"
+#include "JSDataControlConsumer.h"
+#include "plugin_config.h"
+
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <SecurityExceptions.h>
+#include <TimeTracer.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+using namespace DeviceAPI::Common;
+
+
+namespace DeviceAPI {
+namespace DataControl {
+
+namespace {
+const char* MAPPED_DATA_CONTROL_CONSUMER = "MappedDataControlConsumer";
+const char* MAPPED_DATA_CONTROL_CONSUMER_ADD_VALUE = "addValue";
+const char* MAPPED_DATA_CONTROL_CONSUMER_UPDATE_VALUE = "updateValue";
+const char* MAPPED_DATA_CONTROL_CONSUMER_REMOVE_VALUE = "removeValue";
+const char* MAPPED_DATA_CONTROL_CONSUMER_GET_VALUE = "getValue";
+
+const unsigned long PROTOCOL_DATA_MAX = 16 * 1024;
+}
+
+JSClassRef JSMappedDataControlConsumer::m_jsClassRef = NULL;
+
+JSClassDefinition JSMappedDataControlConsumer::m_classInfo ={
+    0,
+    kJSClassAttributeNone,
+    MAPPED_DATA_CONTROL_CONSUMER,
+    JSDataControlConsumer::getClassRef(),
+    NULL,
+    m_function,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+JSStaticFunction JSMappedDataControlConsumer::m_function[] ={
+    { MAPPED_DATA_CONTROL_CONSUMER_ADD_VALUE,
+        JSMappedDataControlConsumer::addValue, kJSPropertyAttributeNone},
+    { MAPPED_DATA_CONTROL_CONSUMER_UPDATE_VALUE,
+        JSMappedDataControlConsumer::updateValue, kJSPropertyAttributeNone},
+    { MAPPED_DATA_CONTROL_CONSUMER_REMOVE_VALUE,
+        JSMappedDataControlConsumer::removeValue, kJSPropertyAttributeNone},
+    { MAPPED_DATA_CONTROL_CONSUMER_GET_VALUE,
+        JSMappedDataControlConsumer::getValue, kJSPropertyAttributeNone},
+    { 0, 0, 0}
+};
+
+const JSClassRef JSMappedDataControlConsumer::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSMappedDataControlConsumer::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSMappedDataControlConsumer::initialize(JSContextRef context, JSObjectRef object)
+{
+}
+
+void JSMappedDataControlConsumer::finalize(JSObjectRef object)
+{
+    LOGD("Enter");
+    DataControlConsumerHolder *priv = static_cast<DataControlConsumerHolder*> (
+            JSObjectGetPrivate(object));
+
+    if (!priv) {
+        LOGE("Private object is null");
+        return;
+    }
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+
+}
+
+JSObjectRef JSMappedDataControlConsumer::makeJSObject(JSContextRef context,
+        std::string provId,
+        std::string dataId,
+        std::string type)
+{
+    LOGD("Enter");
+    DataControlConsumerPtr consumer =
+            std::make_shared<MappedDataControlConsumer>(provId, dataId);
+    DataControlConsumerHolder* priv = new DataControlConsumerHolder();
+    if (!priv) {
+        LOGE("Memory allocation failed");
+        throw Common::UnknownException("Memory allocation failed");
+    }
+    priv->ptr = consumer;
+    return JSObjectMake(context, getClassRef(), priv);
+}
+
+MappedDataControlConsumerPtr JSMappedDataControlConsumer::getPrivateObject(
+        JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not MappedDataControlConsumer");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    DataControlConsumerHolder* priv = static_cast<DataControlConsumerHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw Common::UnknownException("Private data holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw Common::UnknownException("Private data is null");
+    }
+
+    MappedDataControlConsumerPtr ptr = std::dynamic_pointer_cast
+            <MappedDataControlConsumer>(priv->ptr);
+    //If the result of the dynamic_cast is 0, the returned shared_ptr will be empty
+    if (!ptr) {
+        LOGE("Failed to cast");
+        throw Common::UnknownException("Private data is null");
+    }
+    return ptr;
+}
+
+void dataSizeValidCheck(unsigned long data_size)
+{
+    LOGD("Entered");
+    if(data_size > PROTOCOL_DATA_MAX)
+    {
+        LOGE("Data is too big");
+        throw InvalidValuesException("Data is too big");
+    }
+}
+
+JSValueRef JSMappedDataControlConsumer::addValue(
+        JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = DATACONTROL_CHECK_ACCESS(DATACONTROL_FUNC_CONSUMER);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    DataControlMapCallback* callback = NULL;
+    try {
+        callback = new(std::nothrow) DataControlMapCallback(
+                DATACONTROL_REQUEST_TYPE_MAP_INSERT,
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        ArgumentValidator validator(context, argumentCount, arguments);
+        /** void addValue(unsigned long reqId,
+         *      DOMString key,
+         *      DOMString value,
+         *      optional DataControlSuccessCallback? successCallback,
+         *      optional DataControlErrorCallback? errorCallback);
+         */
+        callback->setRequestId(validator.toULong(0));
+
+        std::string key = validator.toString(1);
+        std::string value = validator.toString(2);
+
+        unsigned long data_size = key.size() + value.size();
+        dataSizeValidCheck(data_size);
+
+        callback->setKey(key);
+        callback->setValue(value);
+        callback->setSuccessCallback(validator.toFunction(3, true));
+        callback->setErrorCallback(validator.toFunction(4, true));
+
+        getPrivateObject(context, thisObject)->addValue(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown error");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMappedDataControlConsumer::updateValue(
+        JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = DATACONTROL_CHECK_ACCESS(DATACONTROL_FUNC_CONSUMER);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    DataControlMapCallback* callback = NULL;
+    try {
+        callback = new(std::nothrow) DataControlMapCallback(
+                DATACONTROL_REQUEST_TYPE_MAP_UPDATE,
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        ArgumentValidator validator(context, argumentCount, arguments);
+        /** void updateValue(unsigned long reqId,
+         *        DOMString key, DOMString oldValue,
+         *        DOMString newValue,
+         *        DataControlSuccessCallback successCallback,
+         *        optional DataControlErrorCallback? errorCallback);
+         */
+        callback->setRequestId(validator.toULong(0));
+
+        std::string key = validator.toString(1);
+        std::string old_value = validator.toString(2);
+        std::string new_value = validator.toString(3);
+
+        unsigned long data_size = key.size() + old_value.size() + new_value.size();
+        dataSizeValidCheck(data_size);
+
+        callback->setKey(key);
+        callback->setValue(old_value);
+        callback->setNewValue(new_value);
+        callback->setSuccessCallback(validator.toFunction(4));
+        callback->setErrorCallback(validator.toFunction(5, true));
+
+        getPrivateObject(context, thisObject)->updateValue(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown error");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMappedDataControlConsumer::getValue(
+        JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception)
+
+{
+    LOGD("Entered");
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = DATACONTROL_CHECK_ACCESS(DATACONTROL_FUNC_CONSUMER);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    DataControlGetValueCallback* callback = NULL;
+    try {
+        callback = new(std::nothrow) DataControlGetValueCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        ArgumentValidator validator(context, argumentCount, arguments);
+        /** void getValue(unsigned long reqId,
+         *      DOMString key,
+         *      DataControlGetValueSuccessCallback successCallback,
+         *      optional DataControlErrorCallback? errorCallback);
+         */
+        callback->setRequestId(validator.toULong(0));
+
+        std::string key = validator.toString(1);
+
+        unsigned long data_size = key.size();
+        dataSizeValidCheck(data_size);
+
+        callback->setKey(key);
+        callback->setSuccessCallback(validator.toFunction(2));
+        callback->setErrorCallback(validator.toFunction(3, true));
+
+        getPrivateObject(context, thisObject)->getValue(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown error");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMappedDataControlConsumer::removeValue(
+        JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = DATACONTROL_CHECK_ACCESS(DATACONTROL_FUNC_CONSUMER);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    DataControlMapCallback* callback = NULL;
+    try {
+        callback = new(std::nothrow) DataControlMapCallback(
+                DATACONTROL_REQUEST_TYPE_MAP_DELETE,
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        ArgumentValidator validator(context, argumentCount, arguments);
+        /**  void removeValue(unsigned long reqId,
+         *       DOMString key,
+         *       DOMString value,
+         *       DataControlSuccessCallback successCallback,
+         *       optional DataControlErrorCallback? errorCallback);
+         */
+        callback->setRequestId(validator.toULong(0));
+
+        std::string key = validator.toString(1);
+        std::string value = validator.toString(2);
+
+        unsigned long data_size = key.size() + value.size();
+        dataSizeValidCheck(data_size);
+
+        callback->setKey(key);
+        callback->setValue(value);
+        callback->setSuccessCallback(validator.toFunction(3));
+        callback->setErrorCallback(validator.toFunction(4, true));
+
+        getPrivateObject(context, thisObject)->removeValue(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown error");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/JSMappedDataControlConsumer.h b/src/DataControl/JSMappedDataControlConsumer.h
new file mode 100755 (executable)
index 0000000..a1e6cf0
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_JS_MAPPED_DATACONTROL_CONSUMER_H__
+#define __TIZEN_JS_MAPPED_DATACONTROL_CONSUMER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <string>
+#include "MappedDataControlConsumer.h"
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class JSMappedDataControlConsumer {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef makeJSObject(JSContextRef context,
+            std::string provId,
+            std::string dataId,
+            std::string type);
+private:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static MappedDataControlConsumerPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static JSValueRef addValue(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef updateValue(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+
+    static JSValueRef removeValue(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getValue(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+
+    static JSClassDefinition m_classInfo;
+    static JSStaticFunction m_function[];
+    static JSClassRef m_jsClassRef;
+
+};
+
+}
+}
+#endif //__TIZEN_JS_MAPPED_DATACONTROL_CONSUMER_H__
diff --git a/src/DataControl/JSSQLDataControlConsumer.cpp b/src/DataControl/JSSQLDataControlConsumer.cpp
new file mode 100755 (executable)
index 0000000..01c4faa
--- /dev/null
@@ -0,0 +1,470 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSQLDataControlConsumer.h"
+#include "JSDataControlConsumer.h"
+#include "plugin_config.h"
+#include "DataControlSQLCallback.h"
+
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <SecurityExceptions.h>
+#include <string>
+#include <vector>
+#include <TimeTracer.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+using namespace DeviceAPI::Common;
+
+
+namespace DeviceAPI {
+namespace DataControl {
+
+namespace {
+const char* SQL_DATA_CONTROL_CONSUMER = "SQLDataControlConsumer";
+const char* SQL_DATA_CONTROL_CONSUMER_INSERT = "insert";
+const char* SQL_DATA_CONTROL_CONSUMER_UPDATE = "update";
+const char* SQL_DATA_CONTROL_CONSUMER_REMOVE = "remove";
+const char* SQL_DATA_CONTROL_CONSUMER_SELECT = "select";
+
+const unsigned long PROTOCOL_DATA_MAX = 16 * 1024;
+const unsigned long ROW_DATA_MAX = 1024 * 1024;
+}
+
+JSClassRef JSSQLDataControlConsumer::m_jsClassRef = NULL;
+
+JSClassDefinition JSSQLDataControlConsumer::m_classInfo ={
+    0,
+    kJSClassAttributeNone,
+    SQL_DATA_CONTROL_CONSUMER,
+    JSDataControlConsumer::getClassRef(),
+    NULL,
+    m_function,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+JSStaticFunction JSSQLDataControlConsumer::m_function[] ={
+    { SQL_DATA_CONTROL_CONSUMER_INSERT,
+            JSSQLDataControlConsumer::insert, kJSPropertyAttributeNone},
+    { SQL_DATA_CONTROL_CONSUMER_UPDATE,
+            JSSQLDataControlConsumer::update, kJSPropertyAttributeNone},
+    { SQL_DATA_CONTROL_CONSUMER_REMOVE,
+            JSSQLDataControlConsumer::remove, kJSPropertyAttributeNone},
+    { SQL_DATA_CONTROL_CONSUMER_SELECT,
+            JSSQLDataControlConsumer::select, kJSPropertyAttributeNone},
+    { 0, 0, 0}
+};
+
+const JSClassRef JSSQLDataControlConsumer::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSSQLDataControlConsumer::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSSQLDataControlConsumer::initialize(JSContextRef context, JSObjectRef object)
+{
+}
+
+void JSSQLDataControlConsumer::finalize(JSObjectRef object)
+{
+    LOGD("Enter");
+    DataControlConsumerHolder *priv = static_cast<DataControlConsumerHolder*> (
+            JSObjectGetPrivate(object));
+
+    if (!priv) {
+        LOGE("Private object is null");
+        return;
+    }
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+JSObjectRef JSSQLDataControlConsumer::makeJSObject(JSContextRef context,
+        std::string provId,
+        std::string dataId,
+        std::string type)
+{
+    LOGD("Enter");
+    DataControlConsumerPtr consumer = std::make_shared<SQLDataControlConsumer>(
+            provId, dataId);
+    DataControlConsumerHolder* priv = new DataControlConsumerHolder();
+    if (!priv) {
+        LOGE("Memory allocation failed");
+        throw Common::UnknownException("Memory allocation failed");
+    }
+    priv->ptr = consumer;
+    return JSObjectMake(context, getClassRef(), priv);
+}
+
+SQLDataControlConsumerPtr JSSQLDataControlConsumer::getPrivateObject(
+        JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not SQLDataControlConsumer");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    DataControlConsumerHolder* priv = static_cast<DataControlConsumerHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw Common::UnknownException("Private data holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw Common::UnknownException("Private data is null");
+    }
+
+    SQLDataControlConsumerPtr ptr = std::dynamic_pointer_cast
+            <SQLDataControlConsumer>(priv->ptr);
+    //If the result of the dynamic_cast is 0, the returned shared_ptr will be empty
+    if (!ptr) {
+        LOGE("Failed to cast");
+        throw Common::UnknownException("Private data is null");
+    }
+    return ptr;
+}
+
+
+RowDataPtr objectToRowData(JSContextRef context, JSObjectRef js_row_data)
+{
+    LOGD("Enter");
+    if(NULL == js_row_data) {
+        LOGE("Row data is null");
+        throw  Common::UnknownException("Row data is null");
+    }
+    JSValueRef exception = NULL;
+    JSValueRef js_columns = JSUtil::getProperty(context,
+            js_row_data, RowDataPropertyColumns, &exception);
+    if (NULL != exception || !JSIsArrayValue(context, js_columns)) {
+        throw TypeMismatchException("RowData.columns property is not an array");
+    }
+    JSValueRef js_values = JSUtil::getProperty(context,
+        js_row_data, RowDataPropertyValues, &exception);
+    if (NULL != exception || !JSIsArrayValue(context, js_values)) {
+        throw TypeMismatchException("RowData.values property is not an array");
+    }
+    std::vector<std::string> columns =
+            JSUtil::JSArrayToStringVector(context, js_columns);
+    std::vector<std::string> values =
+            JSUtil::JSArrayToStringVector(context, js_values);
+    RowDataPtr row_data = std::make_shared<RowData>();
+    const int size = columns.size() > values.size() ? values.size() : columns.size();
+    for (int i = 0; i < size; ++i) {
+        row_data->insert(std::pair<std::string, std::string>(columns[i], values[i]));
+    }
+    return row_data;
+}
+
+void dataSizeValidCheck(unsigned long data_size, const unsigned long max)
+{
+    if(data_size > max) {
+        LOGE("Data is too big");
+        throw InvalidValuesException("Data is too big");
+    }
+}
+
+JSValueRef JSSQLDataControlConsumer::insert(
+    JSContextRef context, JSObjectRef object,
+    JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = DATACONTROL_CHECK_ACCESS(DATACONTROL_FUNC_CONSUMER);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    DataControlInsertCallback* callback = NULL;
+    try {
+        callback = new(std::nothrow) DataControlInsertCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        ArgumentValidator validator(context, argumentCount, arguments);
+        /** void insert(unsigned long reqId,
+         *        RowData insertionData,
+         *        optional DataControlInsertSuccessCallback? successCallback,
+         *        optional DataControlErrorCallback? errorCallback);
+         */
+        callback->setRequestId(validator.toULong(0));
+
+        RowDataPtr row_data = objectToRowData(context, validator.toObject(1));
+
+        unsigned long data_size = 0;
+        RowData::iterator iter;
+        for(iter = row_data->begin(); iter != row_data->end(); ++iter)
+        {
+            data_size += (unsigned long)iter->first.size();
+            data_size += (unsigned long)iter->second.size();
+        }
+
+        dataSizeValidCheck(data_size,ROW_DATA_MAX);
+
+        callback->setRowData(row_data);
+        callback->setSuccessCallback(validator.toFunction(2, true));
+        callback->setErrorCallback(validator.toFunction(3, true));
+
+        getPrivateObject(context, thisObject)->insert(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown error");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSQLDataControlConsumer::update(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = DATACONTROL_CHECK_ACCESS(DATACONTROL_FUNC_CONSUMER);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    DataControlSQLCallback* callback = NULL;
+    try {
+        callback = new(std::nothrow) DataControlSQLCallback(
+                DATACONTROL_REQUEST_TYPE_SQL_UPDATE,
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        ArgumentValidator validator(context, argumentCount, arguments);
+        /** void update(unsigned long reqId,
+         *      RowData updateData,
+         *      DOMString where,
+         *      optional DataControlSuccessCallback? successCallback,
+         *      optional DataControlErrorCallback? errorCallback);
+         */
+        callback->setRequestId(validator.toULong(0));
+
+        RowDataPtr row_data = objectToRowData(context, validator.toObject(1));
+
+        unsigned long data_size = 0;
+        RowData::iterator iter;
+        for(iter = row_data->begin(); iter != row_data->end(); ++iter)
+        {
+            data_size += (unsigned long)iter->first.size();
+            data_size += (unsigned long)iter->second.size();
+        }
+
+        std::string where = validator.toString(2);
+        data_size += where.size();
+
+        dataSizeValidCheck(data_size,ROW_DATA_MAX);
+
+        callback->setRowData(row_data);
+        callback->setWhere(where);
+        callback->setSuccessCallback(validator.toFunction(3, true));
+        callback->setErrorCallback(validator.toFunction(4, true));
+
+        getPrivateObject(context, thisObject)->update(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown error");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSQLDataControlConsumer::select(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+
+{
+    LOGD("Enter");
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = DATACONTROL_CHECK_ACCESS(DATACONTROL_FUNC_CONSUMER);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    DataControlSelectCallback* callback = NULL;
+    try {
+        callback = new(std::nothrow) DataControlSelectCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        ArgumentValidator validator(context, argumentCount, arguments);
+        /** void select(unsigned long reqId,
+         *      DOMString[] columns,
+         *      DOMString where,
+         *      DataControlSelectSuccessCallback successCallback,
+         *      optional DataControlErrorCallback? errorCallback,
+         *      optional unsigned long? page,
+         *      optional unsigned long? maxNumberPerPage);
+         */
+        callback->setRequestId(validator.toULong(0));
+
+        std::vector<std::string> columns = validator.toStringVector(1);
+        if(columns.empty()) {
+            LOGE("Columns array is empty");
+            throw TypeMismatchException("Columns array is empty");
+        }
+
+        unsigned long data_size = 0;
+        size_t size = columns.size();
+        for(size_t index = 0; index < size; index++)
+        {
+            data_size += columns[index].size();
+        }
+
+        std::string where = validator.toString(2);
+        data_size += where.size();
+
+        dataSizeValidCheck(data_size,PROTOCOL_DATA_MAX);
+
+        callback->setColumns(columns);
+        callback->setWhere(where);
+        callback->setSuccessCallback(validator.toFunction(3));
+        callback->setErrorCallback(validator.toFunction(4, true));
+        if (!validator.isOmitted(5)) {
+            LOGD("Page argument is given");
+            callback->setPage(validator.toULong(5));
+        }
+        if (!validator.isOmitted(6)) {
+            LOGD("Max number per page argument is given");
+            callback->setMaxNumberPerPage(validator.toULong(6));
+        }
+
+        getPrivateObject(context, thisObject)->select(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown error");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSQLDataControlConsumer::remove(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Enter");
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = DATACONTROL_CHECK_ACCESS(DATACONTROL_FUNC_CONSUMER);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    DataControlSQLCallback* callback = NULL;
+    try {
+        callback = new(std::nothrow) DataControlSQLCallback(
+                DATACONTROL_REQUEST_TYPE_SQL_DELETE,
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        ArgumentValidator validator(context, argumentCount, arguments);
+        /** void remove(unsigned long reqId,
+         *      DOMString where,
+         *      optional DataControlSuccessCallback? successCallback,
+         *      optional DataControlErrorCallback? errorCallback);
+         */
+        callback->setRequestId(validator.toULong(0));
+
+        std::string where = validator.toString(1);
+        unsigned long data_size = where.size();
+
+        dataSizeValidCheck(data_size,PROTOCOL_DATA_MAX);
+
+        callback->setWhere(where);
+        callback->setSuccessCallback(validator.toFunction(2, true));
+        callback->setErrorCallback(validator.toFunction(3, true));
+
+        getPrivateObject(context, thisObject)->remove(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Unknown error");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/JSSQLDataControlConsumer.h b/src/DataControl/JSSQLDataControlConsumer.h
new file mode 100755 (executable)
index 0000000..ac6abee
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_JS_SQL_DATACONTROL_CONSUMER_H__
+#define __TIZEN_JS_SQL_DATACONTROL_CONSUMER_H__
+
+#include "SQLDataControlConsumer.h"
+#include <JavaScriptCore/JavaScript.h>
+#include <string>
+
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class JSSQLDataControlConsumer {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef makeJSObject(JSContextRef context,
+            std::string provId,
+            std::string dataId,
+            std::string type);
+private:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static SQLDataControlConsumerPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+    static JSValueRef insert(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef update(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+
+    static JSValueRef remove(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef select(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+
+    static JSClassDefinition m_classInfo;
+    static JSStaticFunction m_function[];
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //DataControl
+} //DeviceAPI
+#endif //__TIZEN_JS_SQL_DATACONTROL_CONSUMER_H__
diff --git a/src/DataControl/MappedDataControlConsumer.cpp b/src/DataControl/MappedDataControlConsumer.cpp
new file mode 100755 (executable)
index 0000000..b9dd5e5
--- /dev/null
@@ -0,0 +1,533 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MappedDataControlConsumer.h"
+
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+static std::string notfoundStr("BUNDLE_ERROR_KEY_NOT_AVAILABLE");
+static std::string invalidStr("BUNDLE_ERROR_INVALID_PARAMETER");
+
+namespace DeviceAPI {
+namespace DataControl {
+
+using namespace Common;
+
+std::map<int, DataControlMapCallback*> MappedDataControlConsumer::s_callbacks;
+std::mutex MappedDataControlConsumer::s_mutex;
+
+void MappedDataControlConsumer::valueOperationResponse(int req_id,
+        data_control_h provider, bool success, const char* error, void *user_data) {
+    LOGD("Entered with req_id = %d", req_id);
+
+    std::map<int, DataControlMapCallback*>::iterator callback_pair;
+    {
+        std::lock_guard<std::mutex> lock(s_mutex);
+        callback_pair = s_callbacks.find(req_id);
+    }
+
+    if (s_callbacks.end() == callback_pair) {
+        LOGE("Cannot find callback with id: %d", req_id);
+        return;
+    }
+    auto callback = callback_pair->second;
+
+    if (!success) {
+        LOGE("Add/update/remove operation error: %s", error);
+        std::string errorStr(error);
+
+        if (errorStr.find(notfoundStr) != std::string::npos) {
+            callback->setError("NotFoundError", error);
+        } else if (errorStr.find(invalidStr) != std::string::npos){
+            callback->setError("InvalidValuesError", error);
+        } else { 
+            callback->setError("UnknownError", error);
+        }
+    }
+
+    guint id = g_idle_add(operationCallback, callback);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    s_callbacks.erase(req_id);
+}
+
+void MappedDataControlConsumer::getValueResponse(int req_id,
+        data_control_h provider, char** values, int count, bool success,
+        const char* error, void *user_data) {
+    LOGD("Entered with req_id = %d", req_id);
+
+    std::map<int, DataControlMapCallback*>::iterator callback_pair;
+    {
+        std::lock_guard<std::mutex> lock(s_mutex);
+        callback_pair = s_callbacks.find(req_id);
+    }
+
+    if (s_callbacks.end() == callback_pair) {
+        LOGE("Cannot find callback with id: %d", req_id);
+        return;
+    }
+    auto gen_callback = callback_pair->second;
+
+    auto callback = static_cast<DataControlGetValueCallback*>(gen_callback);
+    if (NULL == callback) {
+        LOGE("Wrong type of callback");
+        s_callbacks.erase(req_id);
+        return;
+    }
+
+    if (!success) {
+        LOGE("Get operation error: %s", error);
+        std::string errorStr(error);
+
+        if (errorStr.find(notfoundStr) != std::string::npos) {
+            callback->setError("NotFoundError", error);
+        } else if (errorStr.find(invalidStr) != std::string::npos){
+            callback->setError("InvalidValuesError", error);
+        } else { 
+            callback->setError("UnknownError", error);
+        }
+    } else {
+        std::vector<std::string> vec;
+        for(int i = 0; i < count; i++) {
+            vec.push_back(values[i]);
+            free(values[i]);
+        }
+        callback->setValues(vec);
+        free(values);
+    }
+
+    guint id = g_idle_add(getValueCallback, callback);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    s_callbacks.erase(req_id);
+}
+
+MappedDataControlConsumer::MappedDataControlConsumer(
+        const std::string &provider_id,
+        const std::string &data_id):
+        DataControlConsumer(DataControlType::Map, provider_id, data_id)
+{
+    LOGD("Entered");
+
+    int result = data_control_map_create(&m_data_control);
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGE("Creating data control failed, code: %d", result);
+        throwDataControlException(result, "data_control_map_create()");
+    }
+
+    result = data_control_map_set_provider_id(m_data_control, provider_id.c_str());
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGE("Setting provider id to data control failed, code: %d", result);
+        destroyDataControl();
+        throwDataControlException(result, "data_control_map_set_provider_id()");
+    }
+
+    result = data_control_map_set_data_id(m_data_control, data_id.c_str());
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGE("Setting data id to data control failed, code: %d", result);
+        destroyDataControl();
+        throwDataControlException(result, "data_control_map_set_data_id()");
+    }
+
+    m_response.add_cb = valueOperationResponse;
+    m_response.get_cb = getValueResponse;
+    m_response.set_cb = valueOperationResponse;
+    m_response.remove_cb = valueOperationResponse;
+
+    result = data_control_map_register_response_cb(
+        m_data_control, &m_response, NULL);
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGE("Cannot register response cb, code: %d", result);
+        destroyDataControl();
+        throwDataControlException(result, "data_control_map_register_response_cb()");
+    }
+}
+
+MappedDataControlConsumer::~MappedDataControlConsumer()
+{
+    LOGD("Entered");
+    destroyDataControl();
+}
+
+void MappedDataControlConsumer::destroyDataControl() {
+    int result = data_control_map_destroy(m_data_control);
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGW("%s", getDataControlLogMessage(result, "data_control_map_destroy()").c_str());
+    }
+    m_data_control = NULL;
+}
+
+void MappedDataControlConsumer::addValue(DataControlMapCallback* callback)
+{
+    LOGD("Entered");
+    callback->setProviderId(getProviderId());
+    callback->setDataId(getDataId());
+    callback->setProvider(m_data_control);
+
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, addValueThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* MappedDataControlConsumer::addValueThread(void *data)
+{
+    auto callback = static_cast<DataControlMapCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        int req_id = 0;
+        data_control_h provider = callback->getProvider();
+
+        {
+            std::lock_guard<std::mutex> lock(s_mutex);
+            int result = data_control_map_add(provider, callback->getKey().c_str(),
+                    callback->getValue().c_str(), &req_id);
+            if (DATA_CONTROL_ERROR_NONE != result) {
+                LOGE("Cannot add value to map provider, code: %d", result);
+                throwDataControlException(result, "data_control_map_add()");
+            }
+
+            LOGD("Request id: %d", req_id);
+
+            s_callbacks.insert(std::make_pair(req_id, callback));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+    catch (...) {
+        LOGE("addValueThread fails");
+        callback->setError("UnknownError", "addValueThread fails");
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+
+    return NULL;
+}
+
+gboolean MappedDataControlConsumer::operationCallback(void *data)
+{
+    auto callback = static_cast<DataControlCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            callback->callErrorCallbackWithArguments();
+        }
+        else {
+            callback->callSuccessCallback(
+                    JSUtil::toJSValueRef(context, callback->getRequestId()));
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void MappedDataControlConsumer::getValue(DataControlGetValueCallback* callback)
+{
+    LOGD("Entered");
+    callback->setProviderId(getProviderId());
+    callback->setDataId(getDataId());
+    callback->setProvider(m_data_control);
+
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, getValueThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* MappedDataControlConsumer::getValueThread(void *data)
+{
+    auto callback = static_cast<DataControlGetValueCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        int req_id = 0;
+        data_control_h provider = callback->getProvider();
+
+        {
+            std::lock_guard<std::mutex> lock(s_mutex);
+            int result = data_control_map_get(provider, callback->getKey().c_str(),
+                    &req_id);
+            if (DATA_CONTROL_ERROR_NONE != result) {
+                LOGE("Cannot get value from map provider, code: %d", result);
+                throwDataControlException(result, "data_control_map_get()");
+            }
+
+            LOGD("Request id: %d", req_id);
+
+            s_callbacks.insert(std::make_pair(req_id, callback));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+        guint id = g_idle_add(getValueCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+    catch (...) {
+        LOGE("getValueThread fails");
+        callback->setError("UnknownError", "getValueThread fails");
+        guint id = g_idle_add(getValueCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+
+    return NULL;
+}
+
+gboolean MappedDataControlConsumer::getValueCallback(void *data)
+{
+    auto callback = static_cast<DataControlGetValueCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            callback->callErrorCallbackWithArguments();
+        }
+        else {
+            callback->callSuccessCallbackWithArguments();
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void MappedDataControlConsumer::removeValue(DataControlMapCallback* callback)
+{
+    LOGD("Entered");
+    callback->setProviderId(getProviderId());
+    callback->setDataId(getDataId());
+    callback->setProvider(m_data_control);
+
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, removeValueThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* MappedDataControlConsumer::removeValueThread(void *data)
+{
+    auto callback = static_cast<DataControlMapCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        int req_id = 0;
+        data_control_h provider = callback->getProvider();
+
+        {
+            std::lock_guard<std::mutex> lock(s_mutex);
+            int result = data_control_map_remove(provider, callback->getKey().c_str(),
+                    callback->getValue().c_str(), &req_id);
+
+            if (DATA_CONTROL_ERROR_NONE != result) {
+                LOGE("Cannot remove value from map provider, code: %d", result);
+                throwDataControlException(result, "data_control_map_remove()");
+            }
+
+            LOGD("Request id: %d", req_id);
+
+            s_callbacks.insert(std::make_pair(req_id, callback));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+    catch (...) {
+        LOGE("removeValueThread fails");
+        callback->setError("UnknownError", "removeValueThread fails");
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+
+    return NULL;
+}
+
+void MappedDataControlConsumer::updateValue(DataControlMapCallback* callback)
+{
+    LOGD("Entered");
+    callback->setProviderId(getProviderId());
+    callback->setDataId(getDataId());
+    callback->setProvider(m_data_control);
+
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, updateValueThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* MappedDataControlConsumer::updateValueThread(void *data)
+{
+    auto callback = static_cast<DataControlMapCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        int req_id = 0;
+        data_control_h provider = callback->getProvider();
+
+        {
+            std::lock_guard<std::mutex> lock(s_mutex);
+            int result = data_control_map_set(provider, callback->getKey().c_str(),
+                    callback->getValue().c_str(), callback->getNewValue().c_str(),
+                    &req_id);
+            if (DATA_CONTROL_ERROR_NONE != result) {
+                LOGE("Cannot update value in map provider, code: %d", result);
+                throwDataControlException(result, "data_control_map_set()");
+            }
+
+            LOGD("Request id: %d", req_id);
+
+            s_callbacks.insert(std::make_pair(req_id, callback));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+    catch (...) {
+        LOGE("updateValueThread fails");
+        callback->setError("UnknownError", "updateValueThread fails");
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+
+    return NULL;
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/MappedDataControlConsumer.h b/src/DataControl/MappedDataControlConsumer.h
new file mode 100755 (executable)
index 0000000..e20bc33
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MAPPED_DATA_CONTROL_CONSUMER_H__
+#define __TIZEN_MAPPED_DATA_CONTROL_CONSUMER_H__
+
+#include <string>
+#include <map>
+#include <glib.h>
+#include <mutex>
+
+#include "DataControlConsumer.h"
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class MappedDataControlConsumer;//forward declaration
+// shared pointer with MappedDataControlConsumer object
+typedef std::shared_ptr<MappedDataControlConsumer> MappedDataControlConsumerPtr;
+
+class MappedDataControlConsumer: public DataControlConsumer {
+public:
+    MappedDataControlConsumer(const std::string &provider_id,
+            const std::string &data_id);
+    virtual ~MappedDataControlConsumer();
+    void addValue(DataControlMapCallback* callback);
+    void getValue(DataControlGetValueCallback* callback);
+    void removeValue(DataControlMapCallback* callback);
+    void updateValue(DataControlMapCallback* callback);
+private:
+    data_control_map_response_cb m_response;
+
+    void destroyDataControl();
+
+    static void* addValueThread(void *data);
+    static void* getValueThread(void *data);
+    static void* updateValueThread(void *data);
+    static void* removeValueThread(void *data);
+    static gboolean operationCallback(void *data);
+    static gboolean getValueCallback(void* data);
+
+    static std::map<int, DataControlMapCallback*> s_callbacks;
+    static std::mutex s_mutex;
+
+    static void getValueResponse(int req_id, data_control_h provider,
+        char** result_list, int count, bool success, const char* error, void *user_data);
+    static void valueOperationResponse(int req_id, data_control_h provider,
+        bool success, const char* error, void *user_data);
+};
+
+} //DataControl
+} //DeviceAPI
+
+#endif // __TIZEN_MAPPED_DATA_CONTROL_CONSUMER_H__
diff --git a/src/DataControl/SQLDataControlConsumer.cpp b/src/DataControl/SQLDataControlConsumer.cpp
new file mode 100755 (executable)
index 0000000..1dabb7e
--- /dev/null
@@ -0,0 +1,700 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SQLDataControlConsumer.h"
+
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <string>
+
+namespace DeviceAPI {
+namespace DataControl {
+
+using namespace Common;
+
+std::map<int, DataControlSQLCallback*> SQLDataControlConsumer::s_callbacks;
+std::mutex SQLDataControlConsumer::s_mutex;
+
+static std::string nosuchStr("no such column");
+
+void SQLDataControlConsumer::operationResponse(int req_id,
+        data_control_h provider, bool success, const char* error, void* user_data) {
+    LOGD("Entered with req_id = %d", req_id);
+
+    std::map<int, DataControlSQLCallback*>::iterator callback_pair;
+    {
+        std::lock_guard<std::mutex> lock(s_mutex);
+        callback_pair = s_callbacks.find(req_id);
+    }
+
+    if (s_callbacks.end() == callback_pair) {
+        LOGE("Cannot find callback with id: %d", req_id);
+        return;
+    }
+    auto callback = callback_pair->second;
+
+    if (!success) {
+        LOGE("Update/delete operation error: %s", error);
+        std::string errorStr(error);
+        if (errorStr.find(nosuchStr) != std::string::npos) {
+            callback->setError("InvalidValuesError", error);
+        } else {
+            callback->setError("UnknownError", error);
+        }
+    }
+
+    guint id = g_idle_add(operationCallback, callback);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    s_callbacks.erase(req_id);
+}
+
+void SQLDataControlConsumer::insertResponse(int req_id, data_control_h provider,
+        long long row_id, bool success, const char* error, void* user_data) {
+    LOGD("Entered with req_id = %d", req_id);
+
+    std::map<int, DataControlSQLCallback*>::iterator callback_pair;
+    {
+        std::lock_guard<std::mutex> lock(s_mutex);
+        callback_pair = s_callbacks.find(req_id);
+    }
+
+    if (s_callbacks.end() == callback_pair) {
+        LOGE("Cannot find callback with id: %d", req_id);
+        return;
+    }
+
+    auto gen_callback = callback_pair->second;
+
+    auto callback = static_cast<DataControlInsertCallback*>(gen_callback);
+    if (NULL == callback) {
+        LOGE("Wrong type of callback");
+        s_callbacks.erase(req_id);
+        return;
+    }
+
+    if (!success) {
+        LOGE("Insert operation error: %s", error);
+        std::string errorStr(error);
+        if (errorStr.find(nosuchStr) != std::string::npos) {
+            callback->setError("InvalidValuesError", error);
+        } else {
+            callback->setError("UnknownError", error);
+        }
+    }
+    else {
+        callback->setInsertRowId(row_id);
+    }
+
+    guint id = g_idle_add(insertCallback, callback);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    s_callbacks.erase(req_id);
+}
+
+void SQLDataControlConsumer::selectResponse(int req_id, data_control_h provider,
+        result_set_cursor cursor, bool success, const char* error, void* user_data) {
+    LOGD("Entered with req_id = %d", req_id);
+
+    std::map<int, DataControlSQLCallback*>::iterator callback_pair;
+    {
+        std::lock_guard<std::mutex> lock(s_mutex);
+        callback_pair = s_callbacks.find(req_id);
+    }
+
+    if (s_callbacks.end() == callback_pair) {
+        LOGE("Cannot find callback with id: %d", req_id);
+        return;
+    }
+
+    auto gen_callback = callback_pair->second;
+
+    auto callback = static_cast<DataControlSelectCallback*>(gen_callback);
+    if (NULL == callback) {
+        LOGE("Wrong type of callback");
+        s_callbacks.erase(req_id);
+        return;
+    }
+
+    if (!success) {
+        LOGE("Select operation error: %s", error);
+        std::string errorStr(error);
+        if (errorStr.find(nosuchStr) != std::string::npos) {
+            callback->setError("InvalidValuesError", error);
+        } else {
+            callback->setError("UnknownError", error);
+        }
+    }
+    else {
+        try {
+            int err = 0;
+
+            std::vector<std::string> col_names;
+            std::vector<std::vector<std::string>> values_vector;
+
+            err = data_control_sql_step_first(cursor);
+            if (DATA_CONTROL_ERROR_NONE != err) {
+                LOGE("Cannot get to first element, code: %d", err);
+                throwDataControlException(err, "data_control_sql_step_first()");
+            }
+
+            int col_count = data_control_sql_get_column_count(cursor);
+            LOGD("Column count: %d", col_count);
+
+            char data[1024];
+
+            for(int i = 0; i < col_count; i++) {
+                err = data_control_sql_get_column_name(cursor, i, data);
+                if (DATA_CONTROL_ERROR_NONE != err) {
+                    LOGE("Cannot get column name, code: %d", err);
+                    throwDataControlException(err, "data_control_sql_get_column_name()");
+                }
+                LOGD("Column name: %s", data);
+                col_names.push_back(std::string(data));
+            }
+
+            do {
+                std::vector<std::string> col_vals;
+
+                for(int i = 0; i < col_count; i++) {
+                    err = data_control_sql_get_text_data(cursor, i, data);
+                    if (DATA_CONTROL_ERROR_NONE != err) {
+                        LOGE("Cannot get text from column, code %d", err);
+                        throwDataControlException(err, "data_control_sql_get_text_data()");
+                    }
+                    LOGD("Column data: %s", data);
+                    col_vals.push_back(std::string(data));
+                }
+                values_vector.push_back(col_vals);
+            }
+            while (data_control_sql_step_next(cursor) == DATA_CONTROL_ERROR_NONE);
+
+            callback->setColumnsNames(col_names);
+            callback->setResultRows(values_vector);
+        }
+        catch (const BasePlatformException &error) {
+            LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                    error.getMessage().c_str());
+            callback->setError(error.getName(), error.getMessage());
+        }
+    }
+
+    guint id = g_idle_add(selectCallback, callback);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    s_callbacks.erase(req_id);
+}
+
+SQLDataControlConsumer::SQLDataControlConsumer(
+        const std::string &provider_id,
+        const std::string &data_id):
+        DataControlConsumer(DataControlType::SQL, provider_id, data_id)
+{
+    LOGD("Entered");
+
+    int result = data_control_sql_create(&m_data_control);
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGE("Creating data control failed, code: %d", result);
+        throwDataControlException(result, "data_control_sql_create()");
+    }
+
+    result = data_control_sql_set_provider_id(m_data_control, provider_id.c_str());
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGE("Setting provider id to data control failed, code: %d", result);
+        destroyDataControl();
+        throwDataControlException(result, "data_control_sql_set_provider_id()");
+    }
+
+    result = data_control_sql_set_data_id(m_data_control, data_id.c_str());
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGE("Setting data id to data control failed, code: %d", result);
+        destroyDataControl();
+        throwDataControlException(result, "data_control_sql_set_data_id()");
+    }
+
+    m_response.insert_cb = insertResponse;
+    m_response.select_cb = selectResponse;
+    m_response.update_cb = operationResponse;
+    m_response.delete_cb = operationResponse;
+
+    result = data_control_sql_register_response_cb(
+        m_data_control, &m_response, NULL);
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGE("Cannot register response cb, code: %d", result);
+        destroyDataControl();
+        throwDataControlException(result, "data_control_sql_register_response_cb()");
+    }
+}
+
+SQLDataControlConsumer::~SQLDataControlConsumer()
+{
+    LOGD("Entered");
+    destroyDataControl();
+}
+
+void SQLDataControlConsumer::destroyDataControl() {
+    int result = data_control_sql_destroy(m_data_control);
+    if (DATA_CONTROL_ERROR_NONE != result) {
+        LOGW("%s", getDataControlLogMessage(result, "data_control_sql_destroy()").c_str());
+    }
+    m_data_control = NULL;
+}
+
+void SQLDataControlConsumer::insert(DataControlInsertCallback* callback)
+{
+    LOGD("Entered");
+    callback->setProviderId(getProviderId());
+    callback->setDataId(getDataId());
+    callback->setProvider(m_data_control);
+       
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, insertThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* SQLDataControlConsumer::insertThread(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<DataControlInsertCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        int req_id = 0;
+        data_control_h provider = callback->getProvider();
+
+        bundle *b = bundle_create();
+
+        auto row_data = callback->getRowData();
+        for(auto it = row_data->begin(); it != row_data->end(); it++) {
+            LOGD("[%d] KEY[%s] VALUE[%s]", it, it->first.c_str(), it->second.c_str());
+            bundle_add(b, it->first.c_str(), it->second.c_str());
+        }
+
+        {
+            std::lock_guard<std::mutex> lock(s_mutex);
+
+            int result = data_control_sql_insert(provider, b, &req_id);
+            if (DATA_CONTROL_ERROR_NONE != result) {
+                LOGE("Inserting data failed, code: %d", result);
+                throwDataControlException(result, "data_control_sql_insert()");
+            }
+            LOGD("Request id: %d", req_id);
+
+            s_callbacks.insert(std::make_pair(req_id, callback));
+        }
+
+        bundle_free(b);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+        guint id = g_idle_add(insertCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+    catch (...) {
+        LOGE("insertThread fails");
+        callback->setError("UnknownError", "insertThread fails");
+        guint id = g_idle_add(insertCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+
+    return NULL;
+}
+
+gboolean SQLDataControlConsumer::insertCallback(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<DataControlInsertCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            callback->callErrorCallbackWithArguments();
+        }
+        else {
+            callback->callSuccessCallbackWithArguments();
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void SQLDataControlConsumer::update(DataControlSQLCallback* callback)
+{
+    LOGD("Entered");
+    callback->setProvider(m_data_control);
+    callback->setProviderId(getProviderId());
+    callback->setDataId(getDataId());
+
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, updateThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* SQLDataControlConsumer::updateThread(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<DataControlSQLCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        int req_id = 0;
+        data_control_h provider = callback->getProvider();
+
+        auto row_data = callback->getRowData();
+
+        bundle *b = bundle_create();
+
+        for(auto it = row_data->begin(); it != row_data->end(); it++) {
+            bundle_add(b, it->first.c_str(), it->second.c_str());
+        }
+
+        {
+            std::lock_guard<std::mutex> lock(s_mutex);
+
+            int result = data_control_sql_update(provider, b,
+                    callback->getWhere().c_str(), &req_id);
+            if (DATA_CONTROL_ERROR_NONE != result) {
+                LOGE("Updating data failed, code: %d", result);
+                throwDataControlException(result, "data_control_sql_update()");
+            }
+
+            LOGD("Request id: %d", req_id);
+
+            s_callbacks.insert(std::make_pair(req_id, callback));
+        }
+
+        bundle_free(b);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+    catch (...) {
+        LOGE("updateThread fails");
+        callback->setError("UnknownError", "updateThread fails");
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+
+    return NULL;
+}
+
+gboolean SQLDataControlConsumer::operationCallback(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<DataControlSQLCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            callback->callErrorCallbackWithArguments();
+        }
+        else {
+            callback->callSuccessCallback(
+                    JSUtil::toJSValueRef(context, callback->getRequestId()));
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void SQLDataControlConsumer::remove(DataControlSQLCallback* callback)
+{
+    LOGD("Entered");
+    callback->setProvider(m_data_control);
+    callback->setProviderId(getProviderId());
+    callback->setDataId(getDataId());
+
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, removeThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* SQLDataControlConsumer::removeThread(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<DataControlSQLCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        int req_id = 0;
+        data_control_h provider = callback->getProvider();
+
+        {
+            std::lock_guard<std::mutex> lock(s_mutex);
+
+            int result = data_control_sql_delete(provider, callback->getWhere().c_str(),
+                    &req_id);
+            if (DATA_CONTROL_ERROR_NONE != result) {
+                LOGE("Deleting data failed, code: %d", result);
+                throwDataControlException(result, "data_control_sql_delete()");
+            }
+
+            LOGD("Request id: %d", req_id);
+
+            s_callbacks.insert(std::make_pair(req_id, callback));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+    catch (...) {
+        LOGE("removeThread fails");
+        callback->setError("UnknownError", "removeThread fails");
+        guint id = g_idle_add(operationCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+
+    return NULL;
+}
+
+void SQLDataControlConsumer::select(DataControlSelectCallback* callback)
+{
+    LOGD("Enter");
+    callback->setProvider(m_data_control);
+    callback->setProviderId(getProviderId());
+    callback->setDataId(getDataId());
+
+    pthread_t thread;
+
+    if (pthread_create(&thread, NULL, selectThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* SQLDataControlConsumer::selectThread(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<DataControlSelectCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    try {
+        int req_id = 0;
+        data_control_h provider = callback->getProvider();
+
+        std::vector<std::string> vec = callback->getColumns();
+        int len = vec.size();
+        char* column_list[len];
+
+        for(int i = 0; i < len; ++i) {
+            column_list[i] = (char*)malloc(vec[i].length() + 1);
+            strcpy(column_list[i], vec[i].c_str());
+        }
+
+        {
+            std::lock_guard<std::mutex> lock(s_mutex);
+
+            int result = data_control_sql_select(provider, column_list, len,
+                    callback->getWhere().c_str(), NULL, &req_id);
+            if (DATA_CONTROL_ERROR_NONE != result) {
+                LOGE("Selecting data failed, code %d", result);
+                throwDataControlException(result, "data_control_sql_select()");
+            }
+
+            LOGD("Request id: %d", req_id);
+
+            s_callbacks.insert(std::make_pair(req_id, callback));
+        }
+
+        for(int i = 0; i < len; ++i) {
+            free(column_list[i]);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Error %s, with msg: %s", error.getName().c_str(),
+                error.getMessage().c_str());
+        callback->setError(error.getName(), error.getMessage());
+        guint id = g_idle_add(selectCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+    catch (...) {
+        LOGE("selectThread fails");
+        callback->setError("UnknownError", "selectThread fails");
+        guint id = g_idle_add(selectCallback, data);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete callback;
+        }
+    }
+
+    return NULL;
+}
+
+gboolean SQLDataControlConsumer::selectCallback(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<DataControlSelectCallback*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            callback->callErrorCallbackWithArguments();
+        }
+        else {
+            callback->callSuccessCallbackWithArguments();
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s (%s)", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occurs");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+} //DataControl
+} //DeviceAPI
diff --git a/src/DataControl/SQLDataControlConsumer.h b/src/DataControl/SQLDataControlConsumer.h
new file mode 100755 (executable)
index 0000000..af712b6
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SQL_DATA_CONTROL_CONSUMER_H__
+#define __TIZEN_SQL_DATA_CONTROL_CONSUMER_H__
+
+#include <string>
+#include <map>
+#include <glib.h>
+#include <mutex>
+
+#include "DataControlConsumer.h"
+
+namespace DeviceAPI {
+namespace DataControl {
+
+class SQLDataControlConsumer;//forward declaration
+// shared pointer with SQLDataControlConsumer object
+typedef std::shared_ptr<SQLDataControlConsumer> SQLDataControlConsumerPtr;
+
+class SQLDataControlConsumer: public DataControlConsumer {
+public:
+    SQLDataControlConsumer(const std::string &provider_id,
+            const std::string &data_id);
+    virtual ~SQLDataControlConsumer();
+    void insert(DataControlInsertCallback* callback);
+    void update(DataControlSQLCallback* callback);
+    void remove(DataControlSQLCallback* callback);
+    void select(DataControlSelectCallback* callback);
+private:
+    data_control_sql_response_cb m_response;
+
+    void destroyDataControl();
+
+    static void* insertThread(void *data);
+    static void* selectThread(void *data);
+    static void* updateThread(void *data);
+    static void* removeThread(void *data);
+    static gboolean operationCallback(void *data);
+    static gboolean insertCallback(void* data);
+    static gboolean selectCallback(void* data);
+
+    static std::map<int, DataControlSQLCallback*> s_callbacks;
+    static std::mutex s_mutex;
+
+    static void operationResponse(int req_id, data_control_h provider,
+        bool success, const char* error, void *user_data);
+    static void insertResponse(int req_id, data_control_h provider,
+        long long row_id, bool success, const char* error, void* user_data);
+    static void selectResponse(int req_id, data_control_h provider,
+        result_set_cursor results, bool success, const char* error, void* user_data);
+};
+
+} //DataControl
+} //DeviceAPI
+
+#endif // __TIZEN_SQL_DATA_CONTROL_CONSUMER_H__
diff --git a/src/DataControl/config.xml b/src/DataControl/config.xml
new file mode 100755 (executable)
index 0000000..44c51b3
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+<library-name>libwrt-plugins-tizen-datacontrol.so</library-name>
+<feature-install-uri>datacontrol.install.uri</feature-install-uri>
+<api-feature>
+<name>http://tizen.org/privilege/datacontrol.consumer</name>
+<device-capability>datacontrol.consumer</device-capability>
+</api-feature>
+</plugin-properties>
+
diff --git a/src/DataControl/plugin_config.cpp b/src/DataControl/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..2e97a5d
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <map>
+#include <utility>
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include "plugin_config.h"
+
+#define DATACONTROL_FEATURE_API_CONSUMER "http://tizen.org/privilege/datacontrol.consumer"
+#define DATACONTROL_DEVICE_CAP_CONSUMER "datacontrol.consumer"
+
+
+namespace DeviceAPI {
+namespace DataControl {
+
+static WrtDeviceApis::Commons::FunctionMapping createDataConrolFunctions();
+static WrtDeviceApis::Commons::FunctionMapping DataConrolFunctions =
+        createDataConrolFunctions();
+
+#pragma GCC visibility push(default)
+DEFINE_FUNCTION_GETTER(DataControl, DataConrolFunctions);
+#pragma GCC visibility pop
+
+static WrtDeviceApis::Commons::FunctionMapping createDataConrolFunctions()
+{
+    using namespace WrtDeviceApis::Commons;
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_DATACONTROL_CONSUMER, DATACONTROL_DEVICE_CAP_CONSUMER);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_DATACONTROL_CONSUMER);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_DATACONTROL_CONSUMER, DEVICE_CAP_DATACONTROL_CONSUMER);
+
+
+    ACE_CREATE_FEATURE(FEATURE_CONSUMER, DATACONTROL_FEATURE_API_CONSUMER);
+
+
+    ACE_CREATE_FEATURE_LIST(FEATURES_CONSUMER_CREATOR);
+
+    ACE_CREATE_FEATURE_LIST(FEATURES_CONSUMER);
+    ACE_ADD_API_FEATURE(FEATURES_CONSUMER, FEATURE_CONSUMER);
+
+
+    FunctionMapping DataConrolMapping;
+
+    AceFunction DataControlConsumer = ACE_CREATE_FUNCTION(
+            FUNCTION_DATACONTROL_CONSUMER, DATACONTROL_FUNC_CONSUMER,
+            FEATURES_CONSUMER, DEVICE_LIST_DATACONTROL_CONSUMER);
+    DataConrolMapping.insert(std::make_pair(DATACONTROL_FUNC_CONSUMER, DataControlConsumer));
+
+    return DataConrolMapping;
+}
+
+
+} //DataControl
+} //DeviceAPI
+
+#undef DATACONTROL_FEATURE_API_CONSUMER
+#undef DATACONTROL_DEVICE_CAP_CONSUMER
diff --git a/src/DataControl/plugin_config.h b/src/DataControl/plugin_config.h
new file mode 100755 (executable)
index 0000000..9895b55
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_DATACONTROL_PLUGIN_CONFIG_H__
+#define __TIZEN_JS_DATACONTROL_PLUGIN_CONFIG_H__
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace DataControl {
+
+#define DATACONTROL_FUNC_CONSUMER "DataControlConsumer"
+
+DECLARE_FUNCTION_GETTER(DataControl);
+
+#define DATACONTROL_CHECK_ACCESS(functionName)                       \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(                \
+        getDataControlFunctionData,             \
+        functionName)
+} //DataControl
+} //DeviceAPI
+
+#endif
diff --git a/src/DataControl/plugin_config_impl.h b/src/DataControl/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..682893b
--- /dev/null
@@ -0,0 +1,23 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_DATACONTROL_PLUGIN_CONFIG_IMPL_H__
+#define __TIZEN_JS_DATACONTROL_PLUGIN_CONFIG_IMPL_H__
+
+#define TIZEN_DATACONTROL_DATACONTROL_MANAGER_CLASS "datacontrol"
+
+#endif //__TIZEN_JS_DATACONTROL_PLUGIN_CONFIG_IMPL_H__
diff --git a/src/DataControl/plugin_initializer.cpp b/src/DataControl/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..e167d2f
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSDataControlManager.h"
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace DataControl {
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\DataControl] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (Commons::Exception exception) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\DataControl] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "DataControl";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch(Commons::Exception exception)
+    {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\DataControl] on_frame_load_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->addGlobalContext(
+            static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\DataControl] on_frame_unload_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->removeGlobalContext(
+            static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+    TIZEN_DATACONTROL_DATACONTROL_MANAGER_CLASS,
+    (js_class_template_getter)DeviceAPI::DataControl::JSDataControlManager::getClassRef,
+    NULL)
+PLUGIN_CLASS_MAP_END
+
+} // DataControl
+} // DeviceAPI
diff --git a/src/DataSync/CMakeLists.txt b/src/DataSync/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..30ca5ee
--- /dev/null
@@ -0,0 +1,61 @@
+SET(TARGET_NAME ${datasync_target})
+SET(DESTINATION_NAME ${datasync_dest})
+SET(TARGET_IMPL_NAME ${datasync_impl})
+
+IF(ENABLE_OPTIONAL_DATA_SYNC)
+PKG_CHECK_MODULES(platform_pkgs_datasync REQUIRED sync-agent)
+
+INCLUDE_DIRECTORIES(
+    ${TOP}/Tizen
+    ${TOP}/Common
+    ${platform_pkgs_datasync_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    SyncInfo.cpp
+    SyncStatistics.cpp
+    SyncProfileInfo.cpp
+    SyncServiceInfo.cpp
+    DataSyncManager.cpp
+    DataSyncConverter.cpp
+    DataSyncResponseDispatcher.cpp
+    JSSyncInfo.cpp
+    JSSyncStatistics.cpp
+    JSSyncProfileInfo.cpp
+    JSDataSyncManager.cpp
+    JSSyncServiceInfo.cpp
+    IDataSyncManager.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${platform_pkgs_datasync_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_DATA_SYNC)
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/datasync
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/DataSync/DataSyncConverter.cpp b/src/DataSync/DataSyncConverter.cpp
new file mode 100755 (executable)
index 0000000..bf472cd
--- /dev/null
@@ -0,0 +1,274 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSUtils.h>
+
+#include "DataSyncConverter.h"
+#include "JSDataSyncManager.h"
+#include "JSSyncServiceInfo.h"
+#include "JSSyncProfileInfo.h"
+#include "JSSyncStatistics.h"
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+DataSyncConverter::DataSyncConverter(JSContextRef context) : Converter(context)
+{
+}
+
+DataSyncConverter::~DataSyncConverter()
+{
+}
+
+SyncInfo::SyncMode DataSyncConverter::toSyncMode(std::string tizenValue) const
+{
+    if(!tizenValue.compare(TIZEN_DATA_SYNC_MODE_MANUAL)) {
+        return SyncInfo::MANUAL_MODE;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_MODE_PERIODIC)) {
+        return SyncInfo::PERIODIC_MODE;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_MODE_PUSH)) {
+        return SyncInfo::PUSH_MODE;
+    } else {
+        ThrowMsg(ConversionException, "Invalid sync mode.");
+    }
+
+    return SyncInfo::UNDEFINED_MODE;
+}
+
+std::string DataSyncConverter::toTizenValue(SyncInfo::SyncMode abstractValue) const
+{
+    switch (abstractValue) {
+        case SyncInfo::MANUAL_MODE:
+            return TIZEN_DATA_SYNC_MODE_MANUAL;
+        case SyncInfo::PERIODIC_MODE:
+            return TIZEN_DATA_SYNC_MODE_PERIODIC;
+        case SyncInfo::PUSH_MODE:
+            return TIZEN_DATA_SYNC_MODE_PUSH;
+        default:
+        {
+            LOGW("Invalid sync mode.");
+            return "";
+        }
+    }
+}
+
+SyncInfo::SyncType DataSyncConverter::toSyncType(std::string tizenValue) const
+{
+    if(!tizenValue.compare(TIZEN_DATA_SYNC_TYPE_TWO_WAY)) {
+        return SyncInfo::TWO_WAY_TYPE;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_TYPE_SLOW)) {
+        return SyncInfo::SLOW_TYPE;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_TYPE_ONE_WAY_FROM_CLIENT)) {
+        return SyncInfo::ONE_WAY_FROM_CLIENT_TYPE;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_TYPE_REFRESH_FROM_CLIENT)) {
+        return SyncInfo::REFRESH_FROM_CLIENT_TYPE;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_TYPE_ONE_WAY_FROM_SERVER)) {
+        return SyncInfo::ONE_WAY_FROM_SERVER_TYPE;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_TYPE_REFRESH_FROM_SERVER)) {
+        return SyncInfo::REFRESH_FROM_SERVER_TYPE;
+    } else {
+        ThrowMsg(ConversionException, "Invalid sync type.");
+    }
+
+    return SyncInfo::UNDEFINED_TYPE;
+}
+
+std::string DataSyncConverter::toTizenValue(SyncInfo::SyncType abstractValue) const
+{
+    switch (abstractValue) {
+        case SyncInfo::TWO_WAY_TYPE:
+            return TIZEN_DATA_SYNC_TYPE_TWO_WAY;
+        case SyncInfo::SLOW_TYPE:
+            return TIZEN_DATA_SYNC_TYPE_SLOW;
+        case SyncInfo::ONE_WAY_FROM_CLIENT_TYPE:
+            return TIZEN_DATA_SYNC_TYPE_ONE_WAY_FROM_CLIENT;
+        case SyncInfo::REFRESH_FROM_CLIENT_TYPE:
+            return TIZEN_DATA_SYNC_TYPE_REFRESH_FROM_CLIENT;
+        case SyncInfo::ONE_WAY_FROM_SERVER_TYPE:
+            return TIZEN_DATA_SYNC_TYPE_ONE_WAY_FROM_SERVER;
+        case SyncInfo::REFRESH_FROM_SERVER_TYPE:
+            return TIZEN_DATA_SYNC_TYPE_REFRESH_FROM_SERVER;
+        default:
+        {
+            LOGW("Invalid sync type.");
+            return "";
+        }
+    }
+}
+
+SyncInfo::SyncInterval DataSyncConverter::toSyncInterval(std::string tizenValue) const
+{
+    if(!tizenValue.compare(TIZEN_DATA_SYNC_INTERVAL_5_MINUTES)) {
+        return SyncInfo::INTERVAL_5_MINUTES;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_INTERVAL_15_MINUTES)) {
+        return SyncInfo::INTERVAL_15_MINUTES;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_INTERVAL_1_HOUR)) {
+        return SyncInfo::INTERVAL_1_HOUR;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_INTERVAL_4_HOURS)) {
+        return SyncInfo::INTERVAL_4_HOURS;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_INTERVAL_12_HOURS)) {
+        return SyncInfo::INTERVAL_12_HOURS;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_INTERVAL_1_DAY)) {
+        return SyncInfo::INTERVAL_1_DAY;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_INTERVAL_1_WEEK)) {
+        return SyncInfo::INTERVAL_1_WEEK;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_INTERVAL_1_MONTH)) {
+        return SyncInfo::INTERVAL_1_MONTH;
+    } else {
+        ThrowMsg(ConversionException, "Invalid sync interval.");
+    }
+
+    return SyncInfo::INTERVAL_UNDEFINED;
+}
+
+std::string DataSyncConverter::toTizenValue(SyncInfo::SyncInterval abstractValue) const
+{
+    switch (abstractValue) {
+        case SyncInfo::INTERVAL_5_MINUTES:
+            return TIZEN_DATA_SYNC_INTERVAL_5_MINUTES;
+        case SyncInfo::INTERVAL_15_MINUTES:
+            return TIZEN_DATA_SYNC_INTERVAL_15_MINUTES;
+        case SyncInfo::INTERVAL_1_HOUR:
+            return TIZEN_DATA_SYNC_INTERVAL_1_HOUR;
+        case SyncInfo::INTERVAL_4_HOURS:
+            return TIZEN_DATA_SYNC_INTERVAL_4_HOURS;
+        case SyncInfo::INTERVAL_12_HOURS:
+            return TIZEN_DATA_SYNC_INTERVAL_12_HOURS;
+        case SyncInfo::INTERVAL_1_DAY:
+            return TIZEN_DATA_SYNC_INTERVAL_1_DAY;
+        case SyncInfo::INTERVAL_1_WEEK:
+            return TIZEN_DATA_SYNC_INTERVAL_1_WEEK;
+        case SyncInfo::INTERVAL_1_MONTH:
+            return TIZEN_DATA_SYNC_INTERVAL_1_MONTH;
+        default:
+        {
+            LOGW("Invalid sync interval.");
+            return "";
+        }
+    }
+}
+
+SyncServiceInfo::SyncServiceType DataSyncConverter::toSyncServiceType(std::string tizenValue) const
+{
+    if(!tizenValue.compare(TIZEN_DATA_SYNC_SERVICE_TYPE_CONTACT)) {
+        return SyncServiceInfo::CONTACT_SERVICE_TYPE;
+    } else if (!tizenValue.compare(TIZEN_DATA_SYNC_SERVICE_TYPE_EVENT)) {
+        return SyncServiceInfo::EVENT_SERVICE_TYPE;
+    } else {
+        ThrowMsg(ConversionException, "Invalid sync service type.");
+    }
+
+    return SyncServiceInfo::UNDEFINED_SERVICE_TYPE;
+}
+
+std::string DataSyncConverter::toTizenValue(SyncServiceInfo::SyncServiceType abstractValue) const
+{
+    switch (abstractValue) {
+        case SyncServiceInfo::CONTACT_SERVICE_TYPE:
+            return TIZEN_DATA_SYNC_SERVICE_TYPE_CONTACT;
+        case SyncServiceInfo::EVENT_SERVICE_TYPE:
+            return TIZEN_DATA_SYNC_SERVICE_TYPE_EVENT;
+        default:
+        {
+            LOGW("Invalid sync service type.");
+            return "";
+        }
+    }
+}
+
+std::string DataSyncConverter::toTizenValue(SyncStatistics::SyncStatus abstractValue) const
+{
+    switch (abstractValue) {
+        case SyncStatistics::SUCCESS_STATUS:
+            return TIZEN_DATA_SYNC_STATUS_SUCCESS;
+        case SyncStatistics::FAIL_STATUS:
+            return TIZEN_DATA_SYNC_STATUS_FAIL;
+        case SyncStatistics::STOP_STATUS:
+            return TIZEN_DATA_SYNC_STATUS_STOP;
+        case SyncStatistics::NONE_STATUS:
+            return TIZEN_DATA_SYNC_STATUS_NONE;
+        default:
+        {
+            LOGW("Invalid sync status type.");
+            return "";
+        }
+    }
+}
+
+SyncServiceInfoPtr DataSyncConverter::toServiceInfo(JSValueRef serviceInfo)
+{
+    return JSSyncServiceInfo::getPrivateObject(toJSObjectRef(serviceInfo));
+}
+
+SyncServiceInfoListPtr DataSyncConverter::toServiceInfoList(JSValueRef serviceInfoList)
+{
+    SyncServiceInfoListPtr result(new SyncServiceInfoList());
+
+    std::vector<SyncServiceInfoPtr> resultVector;
+    JSObjectRef objArg = toJSObjectRef(serviceInfoList);
+    LOGD("Array length %u",JSGetArrayLength(m_context, objArg));
+    for (std::size_t i = 0; i < JSGetArrayLength(m_context, objArg); i++) {
+        JSValueRef element = JSGetArrayElement(m_context, objArg, i);
+        if (!JSValueIsObjectOfClass(m_context, element, JSSyncServiceInfo::getClassRef())) {
+            ThrowMsg(ConversionException, "Wrong array element type.");
+        } else {
+            SyncServiceInfoPtr serviceInfo = JSSyncServiceInfo::getPrivateObject(toJSObjectRef(element));
+            resultVector.push_back(serviceInfo);
+        }
+    }
+
+    *result = resultVector;
+    return result;
+}
+
+JSValueRef DataSyncConverter::toJSValueRefServiceInfo(const SyncServiceInfoPtr& arg)
+{
+    return JSUtils::makeObject(m_context, JSSyncServiceInfo::getClassRef(), arg);
+}
+
+JSValueRef DataSyncConverter::toJSValueRefServiceInfoList(const SyncServiceInfoListPtr &arg)
+{
+    return toJSValueRef_(*arg, &DataSyncConverter::toJSValueRefServiceInfo, this);
+}
+
+JSValueRef DataSyncConverter::toJSValueRefProfileInfo(const SyncProfileInfoPtr& arg)
+{
+    return JSUtils::makeObject(m_context, JSSyncProfileInfo::getClassRef(), arg);
+}
+
+JSValueRef DataSyncConverter::toJSValueRefProfileInfoList(const SyncProfileInfoListPtr &arg)
+{
+    return toJSValueRef_(*arg, &DataSyncConverter::toJSValueRefProfileInfo, this);
+}
+
+JSValueRef DataSyncConverter::toJSValueRefSyncStatistics(const SyncStatisticsPtr& arg)
+{
+    return JSUtils::makeObject(m_context, JSSyncStatistics::getClassRef(), arg);
+}
+
+JSValueRef DataSyncConverter::toJSValueRefSyncStatisticsList(const SyncStatisticsListPtr &arg)
+{
+    return toJSValueRef_(*arg, &DataSyncConverter::toJSValueRefSyncStatistics, this);
+}
+
+}
+}
diff --git a/src/DataSync/DataSyncConverter.h b/src/DataSync/DataSyncConverter.h
new file mode 100755 (executable)
index 0000000..e425d39
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_TIZEN_DATA_SYNC_CONVERTER_H_
+#define _JS_TIZEN_DATA_SYNC_CONVERTER_H_
+
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+
+#include <string>
+
+#include "SyncInfo.h"
+#include "SyncServiceInfo.h"
+#include "SyncProfileInfo.h"
+#include "SyncStatistics.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class DataSyncConverter : public WrtDeviceApis::CommonsJavaScript::Converter
+{
+public:
+    explicit DataSyncConverter(JSContextRef context);
+    virtual ~DataSyncConverter();
+
+    SyncInfo::SyncMode toSyncMode(std::string tizenValue) const;
+    std::string toTizenValue(SyncInfo::SyncMode abstractValue) const;
+
+    SyncInfo::SyncType toSyncType(std::string tizenValue) const;
+    std::string toTizenValue(SyncInfo::SyncType abstractValue) const;
+
+    SyncInfo::SyncInterval toSyncInterval(std::string tizenValue) const;
+    std::string toTizenValue(SyncInfo::SyncInterval abstractValue) const;
+
+    SyncServiceInfo::SyncServiceType toSyncServiceType(std::string tizenValue) const;
+    std::string toTizenValue(SyncServiceInfo::SyncServiceType abstractValue) const;
+
+    std::string toTizenValue(SyncStatistics::SyncStatus abstractValue) const;
+
+    SyncServiceInfoPtr toServiceInfo(JSValueRef serviceInfo);
+    SyncServiceInfoListPtr toServiceInfoList(JSValueRef serviceInfoList);
+    JSValueRef toJSValueRefServiceInfo(const SyncServiceInfoPtr &arg);
+    JSValueRef toJSValueRefServiceInfoList(const SyncServiceInfoListPtr &arg);
+
+    JSValueRef toJSValueRefProfileInfo(const SyncProfileInfoPtr &arg);
+    JSValueRef toJSValueRefProfileInfoList(const SyncProfileInfoListPtr &arg);
+
+    JSValueRef toJSValueRefSyncStatistics(const SyncStatisticsPtr &arg);
+    JSValueRef toJSValueRefSyncStatisticsList(const SyncStatisticsListPtr &arg);
+};
+
+}
+}
+
+#endif /* _JS_TIZEN_DATA_SYNC_CONVERTER_H_ */
diff --git a/src/DataSync/DataSyncManager.cpp b/src/DataSync/DataSyncManager.cpp
new file mode 100755 (executable)
index 0000000..9695fd5
--- /dev/null
@@ -0,0 +1,1197 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "DataSyncManager.h"
+#include "SyncInfo.h"
+#include "SyncServiceInfo.h"
+#include "SyncProfileInfo.h"
+
+#include <sync_agent.h>
+#include <sstream>
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+namespace{
+static std::string SYNC_AGENT_PERMISSION_DENIED = "Permission Denied";
+static std::string SYNC_AGENT_FAIL = "Sync Fail";
+static std::string SYNC_AGENT_SYNCHRONISING = "Synchronising";
+static std::string SYNC_AGENT_UNKNOWN_ERROR = "Unknown Error";
+
+const std::string& getDataSyncErrorMessage(int errorCode)
+{
+    switch (errorCode) {
+        case SYNC_AGENT_DS_PERMISSION_DENIED:
+            return SYNC_AGENT_PERMISSION_DENIED;
+        case SYNC_AGENT_DS_FAIL:
+            return SYNC_AGENT_FAIL;
+        case SYNC_AGENT_DS_SYNCHRONISING:
+            return SYNC_AGENT_SYNCHRONISING;
+        default:
+            return SYNC_AGENT_UNKNOWN_ERROR;
+    }
+}
+}
+
+std::string DataSyncManager::getDataSyncLogMessage(const int errorCode, const std::string &hint)
+{
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getDataSyncErrorMessage(errorCode) << ", " << errorCode;
+    return ss.str();
+}
+
+int DataSyncManager::m_instanceCount = 0;
+
+DataSyncManager::DataSyncManager()
+{
+    LOGI("Initialize the datasync manager with count: %d",m_instanceCount);
+
+    if (0==m_instanceCount) {
+        sync_agent_ds_error_e ds_err = sync_agent_ds_init();
+        if (SYNC_AGENT_DS_SUCCESS!=ds_err) {
+            LOGW("%s",getDataSyncLogMessage(ds_err, "sync_agent_ds_init()").c_str());
+        }
+    }
+    m_instanceCount++;
+}
+
+DataSyncManager::~DataSyncManager()
+{
+    LOGI("Deinitialize the datasync manager with count: %d",m_instanceCount);
+
+    m_instanceCount--;
+    if (0==m_instanceCount) {
+        sync_agent_ds_error_e ds_err = sync_agent_ds_deinit();
+        if (SYNC_AGENT_DS_SUCCESS!=ds_err) {
+            LOGW("%s",getDataSyncLogMessage(ds_err, "sync_agent_ds_deinit()").c_str());
+        }
+    }
+}
+
+static int datasync_state_changed_cb(sync_agent_event_data_s* request, void *user_data)
+{
+    LOGD("DataSync session state changed.");
+
+    char *profileDirName = NULL;
+    int sync_type = 0;
+    char *progress = NULL;
+    char *error = NULL;
+
+    Try
+    {
+        OnDataSyncStateChangedPtr eventPtr(new OnDataSyncStateChanged());
+        DataSyncManager* thisDataSyncManager = (DataSyncManager*) user_data;
+
+        LOGD("Get state info.");
+        sync_agent_get_event_data_param(request, &profileDirName);
+        sync_agent_get_event_data_param(request, &sync_type);
+        sync_agent_get_event_data_param(request, &progress);
+        sync_agent_get_event_data_param(request, &error);
+
+        LOGI("profileDirName: %s, sync_type: %d, progress: %s, error: %s",profileDirName,sync_type,progress,error);
+
+        if(profileDirName) {
+            eventPtr->setProfileId(profileDirName);
+            if(4<strnlen(profileDirName, 5)) {
+                eventPtr->setProfileId(eventPtr->getProfileId().substr(4));
+            }
+        }
+
+        if(NULL==progress) {
+            LOGW("Null status.");
+            eventPtr->setSessionStatus(OnDataSyncStateChanged::UNDEFINED_STATUS);
+        } else if(0==strncmp(progress, "DONE", 4)) {
+            eventPtr->setSessionStatus(OnDataSyncStateChanged::COMPLETE_STATUS);
+        } else if(0==strncmp(progress, "CANCEL", 6)) {
+            eventPtr->setSessionStatus(OnDataSyncStateChanged::STOP_STATUS);
+        } else if(0==strncmp(progress, "ERROR", 5)) {
+            // Error cases should be redefined and transferred based on the error value.
+            eventPtr->setSessionStatus(OnDataSyncStateChanged::FAIL_STATUS);
+        } else {
+            LOGI("Undefined status: %s",progress);
+            eventPtr->setSessionStatus(OnDataSyncStateChanged::UNDEFINED_STATUS);
+        }
+
+        eventPtr->setResult(true);
+
+        if(profileDirName) {
+            if (thisDataSyncManager->m_changeEmitters[profileDirName]) {
+                thisDataSyncManager->m_changeEmitters[profileDirName]->emit(eventPtr);
+            }
+        }
+    }
+    Catch (Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+    }
+
+    if(profileDirName) {
+        g_free(profileDirName);
+    }
+    if(progress) {
+        g_free(progress);
+    }
+    if(error) {
+        g_free(error);
+    }
+
+    if (request != NULL) {
+        if (request->size != NULL) {
+            g_free(request->size);
+        }
+        g_free(request);
+    }
+
+    return 0;
+}
+
+static int datasync_progress_cb(sync_agent_event_data_s* request, void *user_data)
+{
+    LOGD("DataSync progress called.");
+
+    char *profileDirName = NULL;
+    int syncType = 0;
+    int uri;
+    char *progressStatus = NULL;
+    char *operationType = NULL;
+
+    Try
+    {
+        OnDataSyncStateChangedPtr eventPtr(new OnDataSyncStateChanged());
+        DataSyncManager* thisDataSyncManager = (DataSyncManager*) user_data;
+
+        int isFromServer, totalPerOperation, syncedPerOperation, totalPerDb, syncedPerDb;
+
+        LOGD("Get progress info.");
+        sync_agent_get_event_data_param(request, &profileDirName);
+        sync_agent_get_event_data_param(request, &syncType);
+        sync_agent_get_event_data_param(request, &uri);
+        sync_agent_get_event_data_param(request, &progressStatus);
+        sync_agent_get_event_data_param(request, &operationType);
+
+        LOGI("profileDirName: %s, syncType: %d, uri: %d, progressStatus: %s, operationType %s",profileDirName,syncType,uri,progressStatus,operationType);
+
+        sync_agent_get_event_data_param(request, &isFromServer);
+        sync_agent_get_event_data_param(request, &totalPerOperation);
+        sync_agent_get_event_data_param(request, &syncedPerOperation);
+        sync_agent_get_event_data_param(request, &totalPerDb);
+        sync_agent_get_event_data_param(request, &syncedPerDb);
+
+        LOGI("isFromServer: %d, totalPerOperation: %d, syncedPerOperation: %d, totalPerDb: %d, syncedPerDb %d",isFromServer,totalPerOperation,syncedPerOperation,totalPerDb,syncedPerDb);
+
+        if(profileDirName) {
+            eventPtr->setProfileId(profileDirName);
+            if(4<strnlen(profileDirName, 5)) {
+                eventPtr->setProfileId(eventPtr->getProfileId().substr(4));
+            }
+        }
+
+        eventPtr->setSessionStatus(OnDataSyncStateChanged::PROGRESS_STATUS);
+
+        if(SYNC_AGENT_SRC_URI_CONTACT==uri) {
+            eventPtr->setServiceType(SyncServiceInfo::CONTACT_SERVICE_TYPE);
+        } else if(SYNC_AGENT_SRC_URI_CALENDAR==uri) {
+            eventPtr->setServiceType(SyncServiceInfo::EVENT_SERVICE_TYPE);
+        } else {
+            LOGW("Wrong service type.");
+            eventPtr->setServiceType(SyncServiceInfo::UNDEFINED_SERVICE_TYPE);
+        }
+
+        eventPtr->setIsFromServer(isFromServer);
+        eventPtr->setSynedPerService(syncedPerDb);
+        eventPtr->setTotalPerService(totalPerDb);
+
+        eventPtr->setResult(true);
+
+        if(profileDirName) {
+            if (thisDataSyncManager->m_changeEmitters[profileDirName]) {
+                thisDataSyncManager->m_changeEmitters[profileDirName]->emit(eventPtr);
+            }
+        }
+    }
+    Catch (Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+    }
+
+    if(profileDirName) {
+        g_free(profileDirName);
+    }
+    if(progressStatus) {
+        g_free(progressStatus);
+    }
+    if(operationType) {
+        g_free(operationType);
+    }
+
+    if (request != NULL) {
+        if (request->size != NULL) {
+            g_free(request->size);
+        }
+        g_free(request);
+    }
+
+    return 0;
+}
+
+static sync_agent_ds_sync_mode_e convertToPlatformSyncMode(SyncInfo::SyncMode syncMode)
+{
+    if(SyncInfo::MANUAL_MODE==syncMode) {
+        return SYNC_AGENT_SYNC_MODE_MANUAL;
+    } else if(SyncInfo::PERIODIC_MODE==syncMode) {
+        return SYNC_AGENT_SYNC_MODE_PERIODIC;
+    } else if(SyncInfo::PUSH_MODE==syncMode) {
+        return SYNC_AGENT_SYNC_MODE_PUSH;
+    } else {
+        LOGW("Error while converting a sync mode.");
+    }
+
+    return SYNC_AGENT_SYNC_MODE_MANUAL;
+}
+
+static SyncInfo::SyncMode convertToSyncMode(sync_agent_ds_sync_mode_e syncMode)
+{
+    if(SYNC_AGENT_SYNC_MODE_MANUAL==syncMode) {
+        return SyncInfo::MANUAL_MODE;
+    } else if(SYNC_AGENT_SYNC_MODE_PERIODIC==syncMode) {
+        return SyncInfo::PERIODIC_MODE;
+    } else if(SYNC_AGENT_SYNC_MODE_PUSH==syncMode) {
+        return SyncInfo::PUSH_MODE;
+    } else {
+        LOGW("Error while converting a sync mode.");
+    }
+
+    return SyncInfo::UNDEFINED_MODE;
+}
+
+static sync_agent_ds_sync_type_e convertToPlatformSyncType(SyncInfo::SyncType syncType)
+{
+    if(SyncInfo::TWO_WAY_TYPE==syncType) {
+        return SYNC_AGENT_SYNC_TYPE_UPDATE_BOTH;
+    } else if(SyncInfo::SLOW_TYPE==syncType) {
+        return SYNC_AGENT_SYNC_TYPE_FULL_SYNC;
+    } else if(SyncInfo::ONE_WAY_FROM_CLIENT_TYPE==syncType) {
+        return SYNC_AGENT_SYNC_TYPE_UPDATE_TO_SERVER;
+    } else if(SyncInfo::REFRESH_FROM_CLIENT_TYPE==syncType) {
+        return SYNC_AGENT_SYNC_TYPE_REFRESH_FROM_PHONE;
+    } else if(SyncInfo::ONE_WAY_FROM_SERVER_TYPE==syncType) {
+        return SYNC_AGENT_SYNC_TYPE_UPDATE_TO_PHONE;
+    } else if(SyncInfo::REFRESH_FROM_SERVER_TYPE==syncType) {
+        return SYNC_AGENT_SYNC_TYPE_REFRESH_FROM_SERVER;
+    } else {
+        LOGW("Error while converting a sync type.");
+    }
+
+    return SYNC_AGENT_SYNC_TYPE_UPDATE_BOTH;
+}
+
+static SyncInfo::SyncType convertToSyncType(sync_agent_ds_sync_type_e syncType)
+{
+    if(SYNC_AGENT_SYNC_TYPE_UPDATE_BOTH==syncType) {
+        return SyncInfo::TWO_WAY_TYPE;
+    } else if(SYNC_AGENT_SYNC_TYPE_FULL_SYNC==syncType) {
+        return SyncInfo::SLOW_TYPE;
+    } else if(SYNC_AGENT_SYNC_TYPE_UPDATE_TO_SERVER==syncType) {
+        return SyncInfo::ONE_WAY_FROM_CLIENT_TYPE;
+    } else if(SYNC_AGENT_SYNC_TYPE_REFRESH_FROM_PHONE==syncType) {
+        return SyncInfo::REFRESH_FROM_CLIENT_TYPE;
+    } else if(SYNC_AGENT_SYNC_TYPE_UPDATE_TO_PHONE==syncType) {
+        return SyncInfo::ONE_WAY_FROM_SERVER_TYPE;
+    } else if(SYNC_AGENT_SYNC_TYPE_REFRESH_FROM_SERVER==syncType) {
+        return SyncInfo::REFRESH_FROM_SERVER_TYPE;
+    } else {
+        LOGW("Error while converting a sync type.");
+    }
+
+    return SyncInfo::UNDEFINED_TYPE;
+}
+
+static sync_agent_ds_sync_interval_e convertToPlatformSyncInterval(SyncInfo::SyncInterval syncInterval)
+{
+    if(SyncInfo::INTERVAL_5_MINUTES==syncInterval) {
+        return SYNC_AGENT_SYNC_INTERVAL_5_MINUTES;
+    } else if(SyncInfo::INTERVAL_15_MINUTES==syncInterval) {
+        return SYNC_AGENT_SYNC_INTERVAL_15_MINUTES;
+    } else if(SyncInfo::INTERVAL_1_HOUR==syncInterval) {
+        return SYNC_AGENT_SYNC_INTERVAL_1_HOUR;
+    } else if(SyncInfo::INTERVAL_4_HOURS==syncInterval) {
+        return SYNC_AGENT_SYNC_INTERVAL_4_HOURS;
+    } else if(SyncInfo::INTERVAL_12_HOURS==syncInterval) {
+        return SYNC_AGENT_SYNC_INTERVAL_12_HOURS;
+    } else if(SyncInfo::INTERVAL_1_DAY==syncInterval) {
+        return SYNC_AGENT_SYNC_INTERVAL_1_DAY;
+    } else if(SyncInfo::INTERVAL_1_WEEK==syncInterval) {
+        return SYNC_AGENT_SYNC_INTERVAL_1_WEEK;
+    } else if(SyncInfo::INTERVAL_1_MONTH==syncInterval) {
+        return SYNC_AGENT_SYNC_INTERVAL_1_MONTH;
+    } else if(SyncInfo::INTERVAL_UNDEFINED==syncInterval) {
+        return SYNC_AGENT_SYNC_INTERVAL_NONE;
+    } else {
+        LOGW("Error while converting a JS sync interval.");
+    }
+
+    return SYNC_AGENT_SYNC_INTERVAL_1_WEEK;
+}
+
+static SyncInfo::SyncInterval convertToSyncInterval(sync_agent_ds_sync_interval_e syncInterval)
+{
+    if(SYNC_AGENT_SYNC_INTERVAL_5_MINUTES==syncInterval) {
+        return SyncInfo::INTERVAL_5_MINUTES;
+    } else if(SYNC_AGENT_SYNC_INTERVAL_15_MINUTES==syncInterval) {
+        return SyncInfo::INTERVAL_15_MINUTES;
+    } else if(SYNC_AGENT_SYNC_INTERVAL_1_HOUR==syncInterval) {
+        return SyncInfo::INTERVAL_1_HOUR;
+    } else if(SYNC_AGENT_SYNC_INTERVAL_4_HOURS==syncInterval) {
+        return SyncInfo::INTERVAL_4_HOURS;
+    } else if(SYNC_AGENT_SYNC_INTERVAL_12_HOURS==syncInterval) {
+        return SyncInfo::INTERVAL_12_HOURS;
+    } else if(SYNC_AGENT_SYNC_INTERVAL_1_DAY==syncInterval) {
+        return SyncInfo::INTERVAL_1_DAY;
+    } else if(SYNC_AGENT_SYNC_INTERVAL_1_WEEK==syncInterval) {
+        return SyncInfo::INTERVAL_1_WEEK;
+    } else if(SYNC_AGENT_SYNC_INTERVAL_1_MONTH==syncInterval) {
+        return SyncInfo::INTERVAL_1_MONTH;
+    } else if(SYNC_AGENT_SYNC_INTERVAL_NONE==syncInterval) {
+        return SyncInfo::INTERVAL_UNDEFINED;
+    } else {
+        LOGW("Error while converting a platform sync interval.");
+    }
+
+    return SyncInfo::INTERVAL_UNDEFINED;
+}
+
+static sync_agent_ds_service_type_e convertToPlatformSyncServiceType(SyncServiceInfo::SyncServiceType serviceType)
+{
+    if(SyncServiceInfo::CONTACT_SERVICE_TYPE==serviceType) {
+        return SYNC_AGENT_CONTACT;
+    } else if(SyncServiceInfo::EVENT_SERVICE_TYPE==serviceType) {
+        return SYNC_AGENT_CALENDAR;
+    } else {
+        LOGW("Error while converting a sync service type.");
+    }
+
+    return SYNC_AGENT_CONTACT;
+}
+
+static SyncServiceInfo::SyncServiceType convertToSyncServiceType(sync_agent_ds_service_type_e serviceType)
+{
+    if(SYNC_AGENT_CONTACT==serviceType) {
+        return SyncServiceInfo::CONTACT_SERVICE_TYPE;
+    } else if(SYNC_AGENT_CALENDAR==serviceType) {
+        return SyncServiceInfo::EVENT_SERVICE_TYPE;
+    } else {
+        LOGW("Error while converting a sync service type.");
+    }
+
+    return SyncServiceInfo::UNDEFINED_SERVICE_TYPE;
+}
+
+static sync_agent_ds_src_uri_e convertToPlatformSourceUri(SyncServiceInfo::SyncServiceType serviceType)
+{
+    if(SyncServiceInfo::CONTACT_SERVICE_TYPE==serviceType) {
+        return SYNC_AGENT_SRC_URI_CONTACT;
+    } else if(SyncServiceInfo::EVENT_SERVICE_TYPE==serviceType) {
+        return SYNC_AGENT_SRC_URI_CALENDAR;
+    } else {
+        LOGW("Error while converting a sync service.");
+    }
+
+    return SYNC_AGENT_SRC_URI_CONTACT;
+}
+
+static SyncStatistics::SyncStatus convertToSyncStatus(char* status)
+{
+    if(0==strncmp(status, "success", 7)) {
+        return SyncStatistics::SUCCESS_STATUS;
+    } else if(0==strncmp(status, "stop", 4)) {
+        return SyncStatistics::STOP_STATUS;
+    } else if(0==strncmp(status, "fail", 4)) {
+        return SyncStatistics::FAIL_STATUS;
+    } else if(0==strncmp(status, "No", 2)) {
+        return SyncStatistics::NONE_STATUS;
+    } else {
+        LOGW("Error while converting a sync status.");
+    }
+
+    return SyncStatistics::NONE_STATUS;
+}
+
+void DataSyncManager::OnRequestReceived(const IEventAddProfilePtr &event)
+{
+    ds_profile_h profile_h = NULL;
+
+    Try
+    {
+        // Check if the quota is full first.
+        GList *profile_list = NULL;
+        GList *iter = NULL;
+
+        sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+        ret = sync_agent_ds_get_all_profile(&profile_list);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_get_all_profile()");
+        }
+
+        int numProfiles = g_list_length(profile_list);
+        for (iter = profile_list; iter != NULL; iter = g_list_next(iter)) {
+           sync_agent_ds_free_profile_info((ds_profile_h) iter->data);
+        }
+        if(profile_list) {
+            g_list_free(profile_list);
+        }
+        LOGD("numProfiles: %d",numProfiles);
+        if(MAX_PROFILES_NUM==numProfiles) {
+            ThrowMsg(OutOfRangeException, "There are already maximum number of profiles!");
+        }
+
+        SyncProfileInfoPtr profile;
+        profile = event->getProfile();
+        if (!profile) {
+            ThrowMsg(NullPointerException, "SyncProfileInfo is NULL.");
+        }
+
+        ret = sync_agent_ds_create_profile_info(&profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_create_profile_info()");
+        }
+
+        ret = sync_agent_ds_set_profile_name(profile_h, (char*)(profile->getProfileName().c_str()));
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_set_profile_name()");
+        }
+
+        ret = sync_agent_ds_set_server_info(profile_h, (char*)(profile->getSyncInfo()->getUrl().c_str()),  (char*)(profile->getSyncInfo()->getId().c_str()),  (char*)(profile->getSyncInfo()->getPassword().c_str()));
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_set_server_info()");
+        }
+
+        sync_agent_ds_sync_mode_e syncMode = convertToPlatformSyncMode(profile->getSyncInfo()->getSyncMode());
+        sync_agent_ds_sync_type_e syncType = convertToPlatformSyncType(profile->getSyncInfo()->getSyncType());
+        sync_agent_ds_sync_interval_e syncInterval = convertToPlatformSyncInterval(profile->getSyncInfo()->getSyncInterval());
+        LOGD("syncMode: %d, syncType: %d, syncInterval: %d",syncMode,syncType,syncInterval);
+
+        ret = sync_agent_ds_set_sync_info(profile_h, syncMode, syncType, syncInterval);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_set_sync_info()");
+        }
+
+        // Set the sync categories.
+        SyncServiceInfoListPtr categories = profile->getServiceInfo();
+        sync_agent_ds_service_type_e serviceType;
+        sync_agent_ds_src_uri_e srcURI;
+        std::string tgtURI, id, password;
+        bool enable;
+        for(unsigned int i=0; categories->size()>i; i++) {
+            serviceType = convertToPlatformSyncServiceType(categories->at(i)->getSyncServiceType());
+            tgtURI = categories->at(i)->getServerDatabaseUri();
+            srcURI = convertToPlatformSourceUri(categories->at(i)->getSyncServiceType());
+            id = categories->at(i)->getId();
+            password = categories->at(i)->getPassword();
+            enable = categories->at(i)->getEnable();
+
+            LOGI("serviceType: %d, tgtURI: %s, enable: %d for index: %d",serviceType,tgtURI.c_str(),enable,i);
+
+            ret = sync_agent_ds_set_sync_service_info(profile_h, serviceType, enable, srcURI, (char*)(tgtURI.c_str()),
+                    0==id.size() ? NULL : (char*)(id.c_str()), 0==password.size() ? NULL : (char*)(password.c_str()));
+            if (SYNC_AGENT_DS_SUCCESS!=ret) {
+                LOGE("ret : %d",ret);
+                throwDataSyncException(ret, "sync_agent_ds_set_sync_service_info()");
+            }
+        }
+
+        int profileId;
+        ret = sync_agent_ds_add_profile(profile_h, &profileId);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_add_profile()");
+        }
+
+        LOGD("profileId from platform: %d",profileId);
+
+        char* profileName = NULL;
+        ret = sync_agent_ds_get_profile_name(profile_h, &profileName);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_get_profile_name()");
+        }
+
+        LOGD("profileName: %s, profileId: %d",profileName,profileId);
+
+        std::stringstream ss;
+        ss<<profileId;
+        profile->setProfileId(ss.str());
+
+        if(profileName) {
+            free(profileName);
+        }
+
+        event->setResult(true);
+    }
+    Catch(OutOfRangeException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::OutOfRangeException);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+
+    if(profile_h) {
+        sync_agent_ds_free_profile_info(profile_h);
+    }
+}
+
+void DataSyncManager::OnRequestReceived(const IEventUpdateProfilePtr &event)
+{
+    ds_profile_h profile_h = NULL;
+
+    Try
+    {
+        SyncProfileInfoPtr profile;
+        profile = event->getProfile();
+        if (!profile) {
+            ThrowMsg(NullPointerException, "SyncProfileInfo is NULL.");
+        }
+
+        sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+        int profileId = -1;
+        std::stringstream ss(profile->getProfileId());
+        ss>>profileId;
+        LOGD("profileId: %d",profileId);
+        ret = sync_agent_ds_get_profile(profileId, &profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException<NotFoundException>(ret, "sync_agent_ds_get_profile()");
+        }
+
+        ret = sync_agent_ds_set_profile_name(profile_h, (char*)(profile->getProfileName().c_str()));
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_set_profile_name()");
+        }
+
+        ret = sync_agent_ds_set_server_info(profile_h, (char*)(profile->getSyncInfo()->getUrl().c_str()),  (char*)(profile->getSyncInfo()->getId().c_str()),  (char*)(profile->getSyncInfo()->getPassword().c_str()));
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_set_server_info()");
+        }
+
+        sync_agent_ds_sync_mode_e syncMode = convertToPlatformSyncMode(profile->getSyncInfo()->getSyncMode());
+        sync_agent_ds_sync_type_e syncType = convertToPlatformSyncType(profile->getSyncInfo()->getSyncType());
+        sync_agent_ds_sync_interval_e syncInterval = convertToPlatformSyncInterval(profile->getSyncInfo()->getSyncInterval());
+        LOGD("syncMode: %d, syncType: %d, syncInterval: %d",syncMode,syncType,syncInterval);
+
+        ret = sync_agent_ds_set_sync_info(profile_h, syncMode, syncType, syncInterval);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_set_sync_info()");
+        }
+
+        // Set the sync categories.
+        SyncServiceInfoListPtr categories = profile->getServiceInfo();
+        sync_agent_ds_service_type_e serviceType;
+        sync_agent_ds_src_uri_e srcURI;
+        std::string tgtURI, id, password;
+        bool enable;
+        for(unsigned int i=0; categories->size()<i; i++) {
+            serviceType = convertToPlatformSyncServiceType(categories->at(i)->getSyncServiceType());
+            tgtURI = categories->at(i)->getServerDatabaseUri();
+            srcURI = convertToPlatformSourceUri(categories->at(i)->getSyncServiceType());
+            id = categories->at(i)->getId();
+            password = categories->at(i)->getPassword();
+            enable = categories->at(i)->getEnable();
+
+            LOGD("serviceType: %d, tgtURI: %s for index: %d",serviceType,tgtURI.c_str(),i);
+
+            ret = sync_agent_ds_set_sync_service_info(profile_h, serviceType, enable, srcURI, (char*)(tgtURI.c_str()),
+                    0==id.size() ? NULL : (char*)(id.c_str()), 0==password.size() ? NULL : (char*)(password.c_str()));
+            if (SYNC_AGENT_DS_SUCCESS!=ret) {
+                LOGE("ret : %d",ret);
+                throwDataSyncException(ret, "sync_agent_ds_set_sync_service_info()");
+            }
+        }
+
+        ret = sync_agent_ds_update_profile(profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret && SYNC_AGENT_DS_SYNCHRONISING !=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException<NotFoundException>(ret, "sync_agent_ds_update_profile()");
+        }
+
+        event->setResult(true);
+    }
+    Catch(NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+
+    if(profile_h) {
+        sync_agent_ds_free_profile_info(profile_h);
+    }
+}
+
+void DataSyncManager::OnRequestReceived(const IEventRemoveProfilePtr &event)
+{
+    ds_profile_h profile_h = NULL;
+
+    Try
+    {
+        sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+        int profileId = -1;
+        std::stringstream ss(event->getProfileId());
+        ss>>profileId;
+        LOGD("profileId: %d",profileId);
+        ret = sync_agent_ds_get_profile(profileId, &profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException<NotFoundException>(ret, "sync_agent_ds_get_profile()");
+        }
+
+        ret = sync_agent_ds_delete_profile(profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret && SYNC_AGENT_DS_SYNCHRONISING !=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_delete_profile()");
+        }
+
+        event->setResult(true);
+    }
+    Catch(NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+
+    if(profile_h) {
+        sync_agent_ds_free_profile_info(profile_h);
+    }
+}
+
+void DataSyncManager::OnRequestReceived(const IEventGetMaxProfilesNumPtr &event)
+{
+    Try
+    {
+        LOGD("Return maximum number of supported profiles: %d",MAX_PROFILES_NUM);
+
+        event->setNumMaxProfiles(MAX_PROFILES_NUM);
+
+        event->setResult(true);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+}
+
+void DataSyncManager::OnRequestReceived(const IEventGetProfilesNumPtr &event)
+{
+    GList *profile_list = NULL;
+    GList *iter = NULL;
+
+    Try
+    {
+        sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+        ret = sync_agent_ds_get_all_profile(&profile_list);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_get_all_profile()");
+        }
+
+        int numProfiles=0;
+        for (iter = profile_list; iter != NULL; iter = g_list_next(iter)) {
+           sync_agent_ds_free_profile_info((ds_profile_h) iter->data);
+           numProfiles++;
+           LOGD("Free sync_agent_ds_profile_info for index: %d",numProfiles);
+        }
+
+        LOGD("numProfiles: %d",numProfiles);
+
+        event->setNumProfiles(numProfiles);
+
+        event->setResult(true);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+}
+
+void DataSyncManager::OnRequestReceived(const IEventGetProfilePtr &event)
+{
+    ds_profile_h profile_h = NULL;
+
+    Try
+    {
+        sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+        int profileId = -1;
+        std::stringstream ss(event->getProfileId());
+        ss>>profileId;
+        LOGD("profileId: %d",profileId);
+        ret = sync_agent_ds_get_profile(profileId, &profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException<NotFoundException>(ret, "sync_agent_ds_get_profile()");
+        }
+
+        SyncProfileInfoPtr profile( new SyncProfileInfo() );
+
+        profile->setProfileId(event->getProfileId());
+
+        char *profileName = NULL;
+        ret = sync_agent_ds_get_profile_name(profile_h, &profileName);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_get_profile_name()");
+        }
+        profile->setProfileName(profileName);
+
+        sync_agent_ds_server_info server_info = { NULL };
+        ret = sync_agent_ds_get_server_info(profile_h, &server_info);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_get_server_info()");
+        }
+        profile->getSyncInfo()->setUrl(server_info.addr);
+        profile->getSyncInfo()->setId(server_info.id);
+        profile->getSyncInfo()->setPassword(server_info.password);
+
+        sync_agent_ds_sync_info sync_info;
+        ret = sync_agent_ds_get_sync_info(profile_h, &sync_info);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_get_sync_info()");
+        }
+        profile->getSyncInfo()->setSyncMode(convertToSyncMode(sync_info.sync_mode));
+        profile->getSyncInfo()->setSyncType(convertToSyncType(sync_info.sync_type));
+        profile->getSyncInfo()->setSyncInterval(convertToSyncInterval(sync_info.interval));
+
+        LOGD("Sync mode: %d, type: %d, interval: %d",sync_info.sync_mode,sync_info.sync_type,sync_info.interval);
+
+        GList *category_list = NULL;
+        sync_agent_ds_service_info *category_info = NULL;
+        ret = sync_agent_ds_get_sync_service_info(profile_h, &category_list);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_get_sync_service_info()");
+        }
+        int category_count = g_list_length(category_list);
+        LOGD("category_count: %d",category_count);
+        while(category_count--) {
+            category_info = (sync_agent_ds_service_info *) g_list_nth_data(category_list, category_count);
+            if(SYNC_AGENT_CALENDAR<category_info->service_type) {
+                LOGD("Skip unsupported sync service type: %d",category_info->service_type);
+                continue;
+            }
+
+            SyncServiceInfoPtr serviceInfo( new SyncServiceInfo() );
+            serviceInfo->setEnable(category_info->enabled);
+            if(category_info->id) {
+                serviceInfo->setId(category_info->id);
+            }
+            if(category_info->password) {
+                serviceInfo->setPassword(category_info->password);
+            }
+            serviceInfo->setSyncServiceType(convertToSyncServiceType(category_info->service_type));
+            if(category_info->tgt_uri) {
+                serviceInfo->setServerDatabaseUri(category_info->tgt_uri);
+            }
+
+            LOGD("Service type: %d",serviceInfo->getSyncServiceType());
+            profile->getServiceInfo()->push_back(serviceInfo);
+        }
+        if(category_list) {
+            g_list_free(category_list);
+        }
+
+        event->setProfile(profile);
+
+        event->setResult(true);
+    }
+    Catch(NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+
+    if(profile_h) {
+        sync_agent_ds_free_profile_info(profile_h);
+    }
+}
+
+void DataSyncManager::OnRequestReceived(const IEventGetAllProfilesPtr &event)
+{
+    GList *profile_list = NULL;
+    GList *iter = NULL;
+
+    Try
+    {
+        ds_profile_h profile_h = NULL;
+        sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+        ret = sync_agent_ds_get_all_profile(&profile_list);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_get_all_profile()");
+        }
+
+        LOGD("Number of profiles: %d", g_list_length(profile_list));
+        for (iter = profile_list; iter != NULL; iter = g_list_next(iter)) {
+            profile_h = (ds_profile_h) iter->data;
+            SyncProfileInfoPtr profile( new SyncProfileInfo() );
+
+            int profileId;
+            ret = sync_agent_ds_get_profile_id(profile_h, &profileId);
+            if (SYNC_AGENT_DS_SUCCESS!=ret) {
+                LOGE("ret : %d",ret);
+                throwDataSyncException(ret, "sync_agent_ds_get_profile_id()");
+            }
+
+            std::stringstream ss;
+            ss<<profileId;
+            profile->setProfileId(ss.str());
+
+            LOGD("Processing a profile with id: %s",profile->getProfileId().c_str());
+
+            char *profileName = NULL;
+            ret = sync_agent_ds_get_profile_name(profile_h, &profileName);
+            if (SYNC_AGENT_DS_SUCCESS!=ret) {
+                LOGE("ret : %d",ret);
+                throwDataSyncException(ret, "sync_agent_ds_get_profile_name()");
+            }
+            profile->setProfileName(profileName);
+
+            sync_agent_ds_server_info server_info = { NULL };
+            ret = sync_agent_ds_get_server_info(profile_h, &server_info);
+            if (SYNC_AGENT_DS_SUCCESS!=ret) {
+                LOGE("ret : %d",ret);
+                throwDataSyncException(ret, "sync_agent_ds_get_server_info()");
+            }
+            profile->getSyncInfo()->setUrl(server_info.addr);
+            profile->getSyncInfo()->setId(server_info.id);
+            profile->getSyncInfo()->setPassword(server_info.password);
+
+            sync_agent_ds_sync_info sync_info;
+            ret = sync_agent_ds_get_sync_info(profile_h, &sync_info);
+            if (SYNC_AGENT_DS_SUCCESS!=ret) {
+                LOGE("ret : %d",ret);
+                throwDataSyncException(ret, "sync_agent_ds_get_sync_info()");
+            }
+            profile->getSyncInfo()->setSyncMode(convertToSyncMode(sync_info.sync_mode));
+            profile->getSyncInfo()->setSyncType(convertToSyncType(sync_info.sync_type));
+            profile->getSyncInfo()->setSyncInterval(convertToSyncInterval(sync_info.interval));
+
+            LOGD("Sync mode: %d, type: %d, interval: %d",sync_info.sync_mode,sync_info.sync_type,sync_info.interval);
+
+            GList *category_list = NULL;
+            sync_agent_ds_service_info *category_info = NULL;
+            ret = sync_agent_ds_get_sync_service_info(profile_h, &category_list);
+            if (SYNC_AGENT_DS_SUCCESS!=ret) {
+                LOGE("ret : %d",ret);
+                throwDataSyncException(ret, "sync_agent_ds_get_sync_service_info()");
+            }
+            int category_count = g_list_length(category_list);
+            LOGD("category_count: %d",category_count);
+            while(category_count--) {
+                category_info = (sync_agent_ds_service_info *) g_list_nth_data(category_list, category_count);
+                if(SYNC_AGENT_CALENDAR<category_info->service_type) {
+                    LOGD("Skip unsupported sync service type: %d",category_info->service_type);
+                    continue;
+                }
+
+                SyncServiceInfoPtr serviceInfo( new SyncServiceInfo() );
+                serviceInfo->setEnable(category_info->enabled);
+                if(category_info->id) {
+                    serviceInfo->setId(category_info->id);
+                }
+                if(category_info->password) {
+                    serviceInfo->setPassword(category_info->password);
+                }
+                serviceInfo->setSyncServiceType(convertToSyncServiceType(category_info->service_type));
+                if(category_info->tgt_uri) {
+                    serviceInfo->setServerDatabaseUri(category_info->tgt_uri);
+                }
+
+                LOGD("Service type: %d",serviceInfo->getSyncServiceType());
+                profile->getServiceInfo()->push_back(serviceInfo);
+            }
+            if(category_list) {
+                g_list_free(category_list);
+            }
+
+            LOGD("Adding a profile to the list.");
+            event->getProfiles()->push_back(profile);
+        }
+
+        event->setResult(true);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+
+    LOGD("Free profiles list.");
+    for (iter = profile_list; iter != NULL; iter = g_list_next(iter)) {
+        sync_agent_ds_free_profile_info((ds_profile_h) iter->data);
+    }
+    if(profile_list) {
+        g_list_free(profile_list);
+    }
+}
+
+void DataSyncManager::OnRequestReceived(const IEventStartSyncPtr &event)
+{
+    ds_profile_h profile_h = NULL;
+
+    Try
+    {
+        sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+        sync_agent_event_error_e err= SYNC_AGENT_EVENT_FAIL;
+
+        int profileId = -1;
+        std::stringstream ss(event->getProfileId());
+        ss>>profileId;
+        LOGD("profileId: %d",profileId);
+        ret = sync_agent_ds_get_profile(profileId, &profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException<NotFoundException>(ret, "sync_agent_ds_get_profile()");
+        }
+
+        err = sync_agent_set_noti_callback(1, datasync_state_changed_cb, this);
+        if (SYNC_AGENT_EVENT_SUCCESS != err) {
+            LOGE("ret : %d",err);
+            throwDataSyncException(err, "sync_agent_set_noti_callback()");
+        }
+
+        err = sync_agent_set_noti_callback(2, datasync_progress_cb, this);
+        if (SYNC_AGENT_EVENT_SUCCESS != err) {
+            LOGE("ret : %d",err);
+            throwDataSyncException(err, "sync_agent_set_noti_callback()");
+        }
+
+        ret = sync_agent_ds_start_sync(profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret && SYNC_AGENT_DS_SYNCHRONISING !=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_start_sync()");
+        }
+
+        if(event->getEmitter()) {
+            LOGD("Attaching the emitter with profileId: %s",event->getProfileId().c_str());
+            m_changeEmitters[std::string("Sync") + event->getProfileId()] = event->getEmitter();
+        }
+
+        event->setResult(true);
+    }
+    Catch(NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+
+    if(profile_h) {
+        sync_agent_ds_free_profile_info(profile_h);
+    }
+}
+
+void DataSyncManager::OnRequestReceived(const IEventStopSyncPtr &event)
+{
+    ds_profile_h profile_h = NULL;
+
+    Try
+    {
+        sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+        int profileId = -1;
+        std::stringstream ss(event->getProfileId());
+        ss>>profileId;
+        LOGD("profileId: %d",profileId);
+        ret = sync_agent_ds_get_profile(profileId, &profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException<NotFoundException>(ret, "sync_agent_ds_get_profile()");
+        }
+
+         ret = sync_agent_ds_stop_sync(profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_stop_sync()");
+        }
+
+        event->setResult(true);
+    }
+    Catch(NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+
+    if(profile_h) {
+        sync_agent_ds_free_profile_info(profile_h);
+    }
+
+}
+
+void DataSyncManager::OnRequestReceived(const IEventGetLastSyncStatisticsPtr &event)
+{
+    ds_profile_h profile_h = NULL;
+
+    Try
+    {
+        sync_agent_ds_error_e ret = SYNC_AGENT_DS_FAIL;
+
+        int profileId = -1;
+        std::stringstream ss(event->getProfileId());
+        ss>>profileId;
+        LOGD("profileId: %d",profileId);
+        ret = sync_agent_ds_get_profile(profileId, &profile_h);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException<NotFoundException>(ret, "sync_agent_ds_get_profile()");
+        }
+
+        SyncStatisticsListPtr statisticsList( new SyncStatisticsList() );
+
+        GList *statistics_list = NULL;
+        ret = sync_agent_ds_get_sync_statistics(profile_h, &statistics_list);
+        if (SYNC_AGENT_DS_SUCCESS!=ret) {
+            LOGE("ret : %d",ret);
+            throwDataSyncException(ret, "sync_agent_ds_get_sync_statistics()");
+        }
+
+        int statistics_count = g_list_length(statistics_list);
+        LOGD("statistics_count: %d",statistics_count);
+        sync_agent_ds_statistics_info *statistics = NULL;
+        for (int i = 0; i < statistics_count; i++) {
+            statistics = (sync_agent_ds_statistics_info *) g_list_nth_data(statistics_list, i);
+
+            SyncStatisticsPtr statisticsPtr( new SyncStatistics() );
+
+            if(0==i) {
+                LOGD("Statistics for contact.");
+                statisticsPtr->setServiceType(convertToSyncServiceType(SYNC_AGENT_CONTACT));
+            } else if(1==i) {
+                LOGD("Statistics for event.");
+                statisticsPtr->setServiceType(convertToSyncServiceType(SYNC_AGENT_CALENDAR));
+            } else {
+                LOGW("Unsupported category for statistics: %d",i);
+                continue;
+            }
+
+            LOGD("dbsynced: %s",statistics->dbsynced);
+            if (statistics->dbsynced) {
+                statisticsPtr->setSyncStatus(convertToSyncStatus(statistics->dbsynced));
+                statisticsPtr->setClientToServerTotal(statistics->client2server_total);
+                statisticsPtr->setClientToServerAdded(statistics->client2server_nrofadd);
+                statisticsPtr->setClientToServerUpdated(statistics->client2server_nrofreplace);
+                statisticsPtr->setClientToServerRemoved(statistics->client2server_nrofdelete);
+                statisticsPtr->setServerToClientTotal(statistics->server2client_total);
+                statisticsPtr->setServerToClientAdded(statistics->server2client_nrofadd);
+                statisticsPtr->setServerToClientUpdated(statistics->server2client_nrofreplace);
+                statisticsPtr->setServerToClientRemoved(statistics->server2client_nrofdelete);
+
+                statisticsPtr->setLastSyncTime((long long int) (statistics->last_session_time));
+            }
+
+            LOGD("ClientToServerTotal: %d, ServerToClientTotal: %d",statisticsPtr->getClientToServerTotal(),statisticsPtr->getServerToClientTotal());
+
+            statisticsList->push_back(statisticsPtr);
+        }
+        if(statistics_list) {
+            g_list_free(statistics_list);
+        }
+
+        event->setSyncStatictics(statisticsList);
+
+        event->setResult(true);
+    }
+    Catch(NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        event->setResult(false);
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+
+    if(profile_h) {
+        sync_agent_ds_free_profile_info(profile_h);
+    }
+}
+
+}
+}
diff --git a/src/DataSync/DataSyncManager.h b/src/DataSync/DataSyncManager.h
new file mode 100755 (executable)
index 0000000..238181a
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _PLATFORM_DATASYNC_MANAGER_H_
+#define _PLATFORM_DATASYNC_MANAGER_H_
+
+#include "IDataSyncManager.h"
+#include "OnDataSyncStateChanged.h"
+#include "PlatformException.h"
+#include "Logger.h"
+
+#include <string>
+#include <map>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+#define MAX_PROFILES_NUM 5
+
+class DataSyncManager : public IDataSyncManager
+{
+public:
+    DataSyncManager();
+    virtual ~DataSyncManager();
+
+    virtual void addProfile(const IEventAddProfilePtr &event) {
+        OnRequestReceived(event);
+    }
+
+    virtual void updateProfile(const IEventUpdateProfilePtr &event) {
+        OnRequestReceived(event);
+    }
+
+    virtual void removeProfile(const IEventRemoveProfilePtr &event) {
+        OnRequestReceived(event);
+    }
+
+    virtual void getMaxProfilesNum(const IEventGetMaxProfilesNumPtr &event) {
+        OnRequestReceived(event);
+    }
+
+    virtual void getProfilesNum(const IEventGetProfilesNumPtr &event) {
+        OnRequestReceived(event);
+    }
+
+    virtual void getProfile(const IEventGetProfilePtr &event) {
+        OnRequestReceived(event);
+    }
+
+    virtual void getAllProfiles(const IEventGetAllProfilesPtr &event) {
+        OnRequestReceived(event);
+    }
+
+    virtual void startSync(const IEventStartSyncPtr &event) {
+        OnRequestReceived(event);
+    }
+
+    virtual void stopSync(const IEventStopSyncPtr &event) {
+        OnRequestReceived(event);
+    }
+
+    virtual void getLastSyncStatistics(const IEventGetLastSyncStatisticsPtr &event) {
+        OnRequestReceived(event);
+    }
+
+    std::map<std::string, OnDataSyncStateChangedEmitterPtr> m_changeEmitters;
+
+protected:
+    virtual void OnRequestReceived(const IEventAddProfilePtr &event);
+    virtual void OnRequestReceived(const IEventUpdateProfilePtr &event);
+    virtual void OnRequestReceived(const IEventRemoveProfilePtr &event);
+    virtual void OnRequestReceived(const IEventGetMaxProfilesNumPtr &event);
+    virtual void OnRequestReceived(const IEventGetProfilesNumPtr &event);
+    virtual void OnRequestReceived(const IEventGetProfilePtr &event);
+    virtual void OnRequestReceived(const IEventGetAllProfilesPtr &event);
+    virtual void OnRequestReceived(const IEventStartSyncPtr &event);
+    virtual void OnRequestReceived(const IEventStopSyncPtr &event);
+    virtual void OnRequestReceived(const IEventGetLastSyncStatisticsPtr &event);
+
+private:
+    std::string getDataSyncLogMessage(const int errorCode, const std::string &hint);
+
+    template <class T = WrtDeviceApis::Commons::PlatformException>
+    void throwDataSyncException(const int errorCode, const std::string &hint)
+    {
+        std::string log = getDataSyncLogMessage(errorCode, hint);
+        LOGE("%s", log.c_str());
+        ThrowMsg(T, log.c_str());
+    }
+
+    static int m_instanceCount;
+};
+
+}
+}
+
+#endif /* _PLATFORM_DATASYNC_MANAGER_H_ */
diff --git a/src/DataSync/DataSyncMultiCallback.h b/src/DataSync/DataSyncMultiCallback.h
new file mode 100755 (executable)
index 0000000..2c87f5e
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _DATASYNC_MULTI_CALLBACK_H_
+#define _DATASYNC_MULTI_CALLBACK_H_
+
+
+#include <Commons/IEvent.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class DataSyncStateChangeCallbackPrivateData : public WrtDeviceApis::Commons::IEventPrivateData
+{
+public:
+    DataSyncStateChangeCallbackPrivateData(const WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr& onProgress,
+        const WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr& onCompleted,
+        const WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr& onStopped,
+        const WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr& onFailed):
+        m_onProgress(onProgress),
+        m_onCompleted(onCompleted),
+        m_onStopped(onStopped),
+        m_onFailed(onFailed)
+    {
+    }
+
+    WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr getOnProgress() const
+    {
+        return m_onProgress;
+    }
+    WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr getOnCompleted() const
+    {
+        return m_onCompleted;
+    }
+    WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr getOnStopped() const
+    {
+        return m_onStopped;
+    }
+    WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr getOnFailed() const
+    {
+        return m_onFailed;
+    }
+
+private:
+    WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr m_onProgress;
+    WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr m_onCompleted;
+    WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr m_onStopped;
+    WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr m_onFailed;
+};
+
+typedef std::shared_ptr<DataSyncStateChangeCallbackPrivateData> DataSyncStateChangeCallbackPrivateDataPtr;
+
+}
+}
+
+#endif /* _DATASYNC_MULTI_CALLBACK_H_ */
diff --git a/src/DataSync/DataSyncResponseDispatcher.cpp b/src/DataSync/DataSyncResponseDispatcher.cpp
new file mode 100755 (executable)
index 0000000..c20df1c
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "DataSyncResponseDispatcher.h"
+#include "DataSyncConverter.h"
+#include "DataSyncMultiCallback.h"
+
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+DataSyncResponseDispatcher& DataSyncResponseDispatcher::getInstance()
+{
+    static DataSyncResponseDispatcher instance;
+    return instance;
+}
+
+DataSyncResponseDispatcher::DataSyncResponseDispatcher() :
+    OnDataSyncStateChangedListener(ThreadEnum::NULL_THREAD)
+{
+}
+
+DataSyncResponseDispatcher::~DataSyncResponseDispatcher()
+{
+}
+
+void DataSyncResponseDispatcher::onAnswerReceived(const OnDataSyncStateChangedPtr& event)
+{
+    DataSyncStateChangeCallbackPrivateDataPtr multiCallbacks =
+        std::static_pointer_cast<DataSyncStateChangeCallbackPrivateData>(event->getPrivateData());
+    if (!multiCallbacks) {
+        LOGE("No listener callback!");
+        return;
+    }
+
+    Try
+       {
+        JSContextRef context = multiCallbacks->getOnProgress()->getContext();
+        if( !GlobalContextManager::getInstance()->isAliveGlobalContext(context)){
+            LOGW("Global context invalidated.");
+            return;
+        }
+
+        if (event->getResult()) {
+            DataSyncConverter converter(context);
+            JSValueRef profileId = converter.toJSValueRef(event->getProfileId());
+            if( OnDataSyncStateChanged::PROGRESS_STATUS==event->getSessionStatus() ) {
+                LOGD("Sync progress: %d/%d",event->getSyncedPerService(),event->getTotalPerService());
+                JSValueRef serviceType = converter.toJSValueRef(converter.toTizenValue(event->getServiceType()));
+                JSValueRef isFromServer = converter.toJSValueRef(event->getIsFromServer());
+                JSValueRef totalPerService = converter.toJSValueRef(event->getTotalPerService());
+                JSValueRef syncedPerService = converter.toJSValueRef(event->getSyncedPerService());
+                JSValueRef objParam[5] = {profileId, serviceType, isFromServer, totalPerService, syncedPerService};
+                multiCallbacks->getOnProgress()->callOnSuccess(objParam, 5);
+            } else if ( OnDataSyncStateChanged::COMPLETE_STATUS==event->getSessionStatus() ) {
+                LOGD("Sync completed.");
+                multiCallbacks->getOnCompleted()->callOnSuccess(profileId);
+            } else if ( OnDataSyncStateChanged::STOP_STATUS==event->getSessionStatus() ) {
+                LOGD("Sync stopped.");
+                multiCallbacks->getOnStopped()->callOnSuccess(profileId);
+            } else if ( OnDataSyncStateChanged::FAIL_STATUS==event->getSessionStatus()) {
+                LOGD("Sync failed with: %d",event->getExceptionCode());
+                JSValueRef errorObject;
+                if (ExceptionCodes::PlatformException==event->getExceptionCode()) {
+                    //errorObject = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::NETWORK_ERROR, event->getErrorMessage());
+                    errorObject = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::NETWORK_ERROR);
+                } else {
+                    errorObject = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::UNKNOWN_ERROR);
+                }
+                JSValueRef objParam[2] = {profileId, errorObject};
+                multiCallbacks->getOnFailed()->callOnSuccess(objParam, 2);
+            } else {
+                LOGI("Undefined sync session state. Skip this.");
+            }
+        } else {
+            LOGW("Failed result received.");
+        }
+    }
+    Catch(Exception)
+    {
+        LOGE("Error during processing answer.");
+    }
+}
+
+}
+}
diff --git a/src/DataSync/DataSyncResponseDispatcher.h b/src/DataSync/DataSyncResponseDispatcher.h
new file mode 100755 (executable)
index 0000000..11ba842
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _DATASYNC_RESPONSE_DISPATCHER_H_
+#define _DATASYNC_RESPONSE_DISPATCHER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <Commons/EventListener.h>
+
+#include "OnDataSyncStateChanged.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+typedef WrtDeviceApis::Commons::EventListener<OnDataSyncStateChanged> OnDataSyncStateChangedListener;
+
+class DataSyncResponseDispatcher : public OnDataSyncStateChangedListener
+{
+public:
+    static DataSyncResponseDispatcher& getInstance();
+
+private:
+    DataSyncResponseDispatcher();
+    virtual ~DataSyncResponseDispatcher();
+
+protected:
+    void onAnswerReceived(const OnDataSyncStateChangedPtr& event);
+};
+
+}
+}
+
+#endif /* _DATASYNC_RESPONSE_DISPATCHER_H_ */
diff --git a/src/DataSync/IDataSyncManager.cpp b/src/DataSync/IDataSyncManager.cpp
new file mode 100755 (executable)
index 0000000..2aaf91f
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "IDataSyncManager.h"
+#include <Commons/ThreadPool.h>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+IDataSyncManager::IDataSyncManager() :
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventAddProfile >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD),
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventUpdateProfile >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD),
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventRemoveProfile >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD),
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventGetMaxProfilesNum >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD),
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventGetProfilesNum >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD),
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventGetProfile >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD),
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventGetAllProfiles >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD),
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventStartSync >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD),
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventStopSync >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD),
+    WrtDeviceApis::Commons::EventRequestReceiver< IEventGetLastSyncStatistics >(WrtDeviceApis::Commons::ThreadEnum::NULL_THREAD)
+{
+}
+
+IDataSyncManager::~IDataSyncManager()
+{
+}
+
+void IDataSyncManager::addProfile(const IEventAddProfilePtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventAddProfile>::PostRequest(event);
+}
+
+void IDataSyncManager::updateProfile(const IEventUpdateProfilePtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventUpdateProfile>::PostRequest(event);
+}
+
+void IDataSyncManager::removeProfile(const IEventRemoveProfilePtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventRemoveProfile>::PostRequest(event);
+}
+
+void IDataSyncManager::getMaxProfilesNum(const IEventGetMaxProfilesNumPtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventGetMaxProfilesNum>::PostRequest(event);
+}
+
+void IDataSyncManager::getProfilesNum(const IEventGetProfilesNumPtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventGetProfilesNum>::PostRequest(event);
+}
+
+void IDataSyncManager::getProfile(const IEventGetProfilePtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventGetProfile>::PostRequest(event);
+}
+
+void IDataSyncManager::getAllProfiles(const IEventGetAllProfilesPtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventGetAllProfiles>::PostRequest(event);
+}
+
+void IDataSyncManager::startSync(const IEventStartSyncPtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventStartSync>::PostRequest(event);
+}
+
+void IDataSyncManager::stopSync(const IEventStopSyncPtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventStopSync>::PostRequest(event);
+}
+
+void IDataSyncManager::getLastSyncStatistics(const IEventGetLastSyncStatisticsPtr &event)
+{
+    WrtDeviceApis::Commons::EventRequestReceiver<IEventGetLastSyncStatistics>::PostRequest(event);
+}
+
+}
+}
diff --git a/src/DataSync/IDataSyncManager.h b/src/DataSync/IDataSyncManager.h
new file mode 100755 (executable)
index 0000000..0b59c9d
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IDATASYNC_MANAGER_H_
+#define _ABSTRACT_LAYER_IDATASYNC_MANAGER_H_
+
+#include "IEventAddProfile.h"
+#include "IEventUpdateProfile.h"
+#include "IEventRemoveProfile.h"
+#include "IEventGetMaxProfilesNum.h"
+#include "IEventGetProfilesNum.h"
+#include "IEventGetProfile.h"
+#include "IEventGetAllProfiles.h"
+#include "IEventStartSync.h"
+#include "IEventStopSync.h"
+#include "IEventGetLastSyncStatistics.h"
+#include "OnDataSyncStateChanged.h"
+
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IDataSyncManager : public WrtDeviceApis::Commons::EventRequestReceiver< IEventAddProfile >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< IEventUpdateProfile >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< IEventRemoveProfile >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< IEventGetMaxProfilesNum >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< IEventGetProfilesNum >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< IEventGetProfile >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< IEventGetAllProfiles >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< IEventStartSync >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< IEventStopSync >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< IEventGetLastSyncStatistics >
+{
+public:
+    IDataSyncManager();
+    virtual ~IDataSyncManager();
+    virtual void addProfile(const IEventAddProfilePtr &event);
+    virtual void updateProfile(const IEventUpdateProfilePtr &event);
+    virtual void removeProfile(const IEventRemoveProfilePtr &event);
+    virtual void getMaxProfilesNum(const IEventGetMaxProfilesNumPtr &event);
+    virtual void getProfilesNum(const IEventGetProfilesNumPtr &event);
+    virtual void getProfile(const IEventGetProfilePtr &event);
+    virtual void getAllProfiles(const IEventGetAllProfilesPtr &event);
+    virtual void startSync(const IEventStartSyncPtr &event);
+    virtual void stopSync(const IEventStopSyncPtr &event);
+    virtual void getLastSyncStatistics(const IEventGetLastSyncStatisticsPtr &event);
+
+protected:
+    virtual void OnRequestReceived(const IEventAddProfilePtr &event) = 0;
+    virtual void OnRequestReceived(const IEventUpdateProfilePtr &event) = 0;
+    virtual void OnRequestReceived(const IEventRemoveProfilePtr &event) = 0;
+    virtual void OnRequestReceived(const IEventGetMaxProfilesNumPtr &event) = 0;
+    virtual void OnRequestReceived(const IEventGetProfilesNumPtr &event) = 0;
+    virtual void OnRequestReceived(const IEventGetProfilePtr &event) = 0;
+    virtual void OnRequestReceived(const IEventGetAllProfilesPtr &event) = 0;
+    virtual void OnRequestReceived(const IEventStartSyncPtr &event) = 0;
+    virtual void OnRequestReceived(const IEventStopSyncPtr &event) = 0;
+    virtual void OnRequestReceived(const IEventGetLastSyncStatisticsPtr &event) = 0;
+};
+
+typedef std::shared_ptr<IDataSyncManager> IDataSyncManagerPtr;
+
+}
+}
+
+#endif /* _ABSTRACT_LAYER_IDATASYNC_MANAGER_H_ */
diff --git a/src/DataSync/IEventAddProfile.h b/src/DataSync/IEventAddProfile.h
new file mode 100755 (executable)
index 0000000..fea8b68
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_ADD_PROFILE_H_
+#define _ABSTRACT_LAYER_IEVENT_ADD_PROFILE_H_
+
+#include <Commons/IEvent.h>
+
+
+#include "SyncProfileInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventAddProfile : public WrtDeviceApis::Commons::IEvent<IEventAddProfile>
+{
+    bool m_result;
+    SyncProfileInfoPtr m_profile;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setProfile(SyncProfileInfoPtr value)
+    {
+        m_profile = value;
+    }
+    SyncProfileInfoPtr getProfile() const
+    {
+        return m_profile;
+    }
+
+    IEventAddProfile() : m_result(false),
+        m_profile(static_cast<SyncProfileInfo*>(NULL))
+    {
+    }
+    ~IEventAddProfile()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventAddProfile> IEventAddProfilePtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_ADD_PROFILE_H_ */
diff --git a/src/DataSync/IEventGetAllProfiles.h b/src/DataSync/IEventGetAllProfiles.h
new file mode 100755 (executable)
index 0000000..edb0a05
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_GET_ALL_PROFILES_H_
+#define _ABSTRACT_LAYER_IEVENT_GET_ALL_PROFILES_H_
+
+#include <Commons/IEvent.h>
+
+
+#include "SyncProfileInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventGetAllProfiles : public WrtDeviceApis::Commons::IEvent<IEventGetAllProfiles>
+{
+    bool m_result;
+    SyncProfileInfoListPtr m_profiles;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setProfiles(SyncProfileInfoListPtr value)
+    {
+        m_profiles = value;
+    }
+    SyncProfileInfoListPtr getProfiles() const
+    {
+        return m_profiles;
+    }
+
+    IEventGetAllProfiles() : m_result(false),
+        m_profiles(new SyncProfileInfoList())
+    {
+    }
+    ~IEventGetAllProfiles()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventGetAllProfiles> IEventGetAllProfilesPtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_GET_ALL_PROFILES_H_ */
+
diff --git a/src/DataSync/IEventGetLastSyncStatistics.h b/src/DataSync/IEventGetLastSyncStatistics.h
new file mode 100755 (executable)
index 0000000..f39051b
--- /dev/null
@@ -0,0 +1,80 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_GET_LAST_SYNC_STATISTICS_H_
+#define _ABSTRACT_LAYER_IEVENT_GET_LAST_SYNC_STATISTICS_H_
+
+#include <Commons/IEvent.h>
+
+
+#include "SyncStatistics.h"
+
+#include <string>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventGetLastSyncStatistics : public WrtDeviceApis::Commons::IEvent<IEventGetLastSyncStatistics>
+{
+    bool m_result;
+    std::string m_profileId;
+    SyncStatisticsListPtr m_syncStatistics;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setProfileId(const std::string &value)
+    {
+        m_profileId = value;
+    }
+    std::string getProfileId() const
+    {
+        return m_profileId;
+    }
+
+    void setSyncStatictics(SyncStatisticsListPtr value)
+    {
+        m_syncStatistics = value;
+    }
+    SyncStatisticsListPtr getSyncStatistics() const
+    {
+        return m_syncStatistics;
+    }
+
+    IEventGetLastSyncStatistics() : m_result(false),
+        m_profileId(""),
+        m_syncStatistics(static_cast<SyncStatisticsList*>(NULL))
+    {
+    }
+    ~IEventGetLastSyncStatistics()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventGetLastSyncStatistics> IEventGetLastSyncStatisticsPtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_GET_LAST_SYNC_STATISTICS_H_ */
diff --git a/src/DataSync/IEventGetMaxProfilesNum.h b/src/DataSync/IEventGetMaxProfilesNum.h
new file mode 100755 (executable)
index 0000000..9fac428
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_GET_MAX_PROFILES_NUM_H_
+#define _ABSTRACT_LAYER_IEVENT_GET_MAX_PROFILES_NUM_H_
+
+#include <Commons/IEvent.h>
+
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventGetMaxProfilesNum : public WrtDeviceApis::Commons::IEvent<IEventGetMaxProfilesNum>
+{
+    bool m_result;
+    int m_numMaxProfiles;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setNumMaxProfiles(int value)
+    {
+        m_numMaxProfiles = value;
+    }
+    int getNumMaxProfiles() const
+    {
+        return m_numMaxProfiles;
+    }
+
+    IEventGetMaxProfilesNum() : m_result(false),
+        m_numMaxProfiles(0)
+    {
+    }
+    ~IEventGetMaxProfilesNum()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventGetMaxProfilesNum> IEventGetMaxProfilesNumPtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_GET_MAX_PROFILES_NUM_H_ */
+
diff --git a/src/DataSync/IEventGetProfile.h b/src/DataSync/IEventGetProfile.h
new file mode 100755 (executable)
index 0000000..8bddd4f
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_GET_PROFILE_H_
+#define _ABSTRACT_LAYER_IEVENT_GET_PROFILE_H_
+
+#include <Commons/IEvent.h>
+
+
+#include "SyncProfileInfo.h"
+
+#include <string>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventGetProfile : public WrtDeviceApis::Commons::IEvent<IEventGetProfile>
+{
+    bool m_result;
+    std::string m_profileId;
+    SyncProfileInfoPtr m_profile;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setProfileId(const std::string &value)
+    {
+        m_profileId = value;
+    }
+    std::string getProfileId() const
+    {
+        return m_profileId;
+    }
+
+    void setProfile(SyncProfileInfoPtr value)
+    {
+        m_profile = value;
+    }
+    SyncProfileInfoPtr getProfile() const
+    {
+        return m_profile;
+    }
+
+    IEventGetProfile() : m_result(false),
+        m_profileId(""),
+        m_profile(static_cast<SyncProfileInfo*>(NULL))
+    {
+    }
+    ~IEventGetProfile()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventGetProfile> IEventGetProfilePtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_GET_PROFILE_H_ */
+
diff --git a/src/DataSync/IEventGetProfilesNum.h b/src/DataSync/IEventGetProfilesNum.h
new file mode 100755 (executable)
index 0000000..4a73c9e
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_GET_PROFILES_NUM_H_
+#define _ABSTRACT_LAYER_IEVENT_GET_PROFILES_NUM_H_
+
+#include <Commons/IEvent.h>
+
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventGetProfilesNum : public WrtDeviceApis::Commons::IEvent<IEventGetProfilesNum>
+{
+    bool m_result;
+    int m_numProfiles;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setNumProfiles(int value)
+    {
+        m_numProfiles = value;
+    }
+    int getNumProfiles() const
+    {
+        return m_numProfiles;
+    }
+
+    IEventGetProfilesNum() : m_result(false),
+        m_numProfiles(0)
+    {
+    }
+    ~IEventGetProfilesNum()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventGetProfilesNum> IEventGetProfilesNumPtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_GET_PROFILES_NUM_H_ */
+
diff --git a/src/DataSync/IEventRemoveProfile.h b/src/DataSync/IEventRemoveProfile.h
new file mode 100755 (executable)
index 0000000..c7b9e09
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_REMOVE_PROFILE_H_
+#define _ABSTRACT_LAYER_IEVENT_REMOVE_PROFILE_H_
+
+#include <Commons/IEvent.h>
+
+
+#include <string>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventRemoveProfile : public WrtDeviceApis::Commons::IEvent<IEventRemoveProfile>
+{
+    bool m_result;
+    std::string m_profileId;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setProfileId(const std::string &value)
+    {
+        m_profileId = value;
+    }
+    std::string getProfileId() const
+    {
+        return m_profileId;
+    }
+
+    IEventRemoveProfile() : m_result(false),
+        m_profileId("")
+    {
+    }
+    ~IEventRemoveProfile()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventRemoveProfile> IEventRemoveProfilePtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_REMOVE_PROFILE_H_ */
+
diff --git a/src/DataSync/IEventStartSync.h b/src/DataSync/IEventStartSync.h
new file mode 100755 (executable)
index 0000000..1c64971
--- /dev/null
@@ -0,0 +1,80 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_START_SYNC_H_
+#define _ABSTRACT_LAYER_IEVENT_START_SYNC_H_
+
+#include <Commons/IEvent.h>
+
+
+#include "OnDataSyncStateChanged.h"
+
+#include <string>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventStartSync : public WrtDeviceApis::Commons::IEvent<IEventStartSync>
+{
+    bool m_result;
+    std::string m_profileId;
+    OnDataSyncStateChangedEmitterPtr m_emitter;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setProfileId(const std::string &value)
+    {
+        m_profileId = value;
+    }
+    std::string getProfileId() const
+    {
+        return m_profileId;
+    }
+
+    void setEmitter(OnDataSyncStateChangedEmitterPtr value)
+    {
+        m_emitter = value;
+    }
+    OnDataSyncStateChangedEmitterPtr getEmitter() const
+    {
+        return m_emitter;
+    }
+
+    IEventStartSync() : m_result(false),
+        m_profileId(""),
+        m_emitter(static_cast<OnDataSyncStateChangedEmitter*>(NULL))
+    {
+    }
+    ~IEventStartSync()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventStartSync> IEventStartSyncPtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_START_SYNC_H_ */
diff --git a/src/DataSync/IEventStopSync.h b/src/DataSync/IEventStopSync.h
new file mode 100755 (executable)
index 0000000..f563247
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_STOP_SYNC_H_
+#define _ABSTRACT_LAYER_IEVENT_STOP_SYNC_H_
+
+#include <Commons/IEvent.h>
+
+
+#include <string>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventStopSync : public WrtDeviceApis::Commons::IEvent<IEventStopSync>
+{
+    bool m_result;
+    std::string m_profileId;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setProfileId(const std::string &value)
+    {
+        m_profileId = value;
+    }
+    std::string getProfileId() const
+    {
+        return m_profileId;
+    }
+
+    IEventStopSync() : m_result(false),
+        m_profileId("")
+    {
+    }
+    ~IEventStopSync()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventStopSync> IEventStopSyncPtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_STOP_SYNC_H_ */
+
diff --git a/src/DataSync/IEventUpdateProfile.h b/src/DataSync/IEventUpdateProfile.h
new file mode 100755 (executable)
index 0000000..c7795ac
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_IEVENT_UPDATE_PROFILE_H_
+#define _ABSTRACT_LAYER_IEVENT_UPDATE_PROFILE_H_
+
+#include <Commons/IEvent.h>
+
+
+#include "SyncProfileInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class IEventUpdateProfile : public WrtDeviceApis::Commons::IEvent<IEventUpdateProfile>
+{
+    bool m_result;
+    SyncProfileInfoPtr m_profile;
+
+public:
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setProfile(SyncProfileInfoPtr value)
+    {
+        m_profile = value;
+    }
+    SyncProfileInfoPtr getProfile() const
+    {
+        return m_profile;
+    }
+
+    IEventUpdateProfile() : m_result(false),
+        m_profile(static_cast<SyncProfileInfo*>(NULL))
+    {
+    }
+    ~IEventUpdateProfile()
+    {
+    }
+};
+
+typedef std::shared_ptr<IEventUpdateProfile> IEventUpdateProfilePtr;
+
+}
+}
+#endif /* _ABSTRACT_LAYER_IEVENT_UPDATE_PROFILE_H_ */
+
diff --git a/src/DataSync/JSDataSyncManager.cpp b/src/DataSync/JSDataSyncManager.cpp
new file mode 100755 (executable)
index 0000000..2dd1bcc
--- /dev/null
@@ -0,0 +1,910 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <string>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+
+#include "OnDataSyncStateChanged.h"
+#include "DataSyncManager.h"
+#include "JSDataSyncManager.h"
+#include "DataSyncConverter.h"
+#include "JSSyncInfo.h"
+#include "JSSyncServiceInfo.h"
+#include "JSSyncProfileInfo.h"
+#include "plugin_config.h"
+#include "DataSyncResponseDispatcher.h"
+#include "DataSyncMultiCallback.h"
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+using WrtDeviceApis::Commons::UnknownException;
+using WrtDeviceApis::Commons::NotFoundException;
+
+JSClassDefinition JSDataSyncManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_DATA_SYNC_MANAGER_INTERFACE,
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function,
+    initialize,
+    finalize,
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSDataSyncManager::m_function[] = {
+    { DATASYNC_FUNCTION_API_ADD, add, kJSPropertyAttributeNone },
+    { DATASYNC_FUNCTION_API_UPDATE, update, kJSPropertyAttributeNone },
+    { DATASYNC_FUNCTION_API_REMOVE, remove, kJSPropertyAttributeNone },
+    { DATASYNC_FUNCTION_API_GET_MAX_PROFILES_NUM, getMaxProfilesNum, kJSPropertyAttributeNone },
+    { DATASYNC_FUNCTION_API_GET_PROFILES_NUM, getProfilesNum, kJSPropertyAttributeNone },
+    { DATASYNC_FUNCTION_API_GET, get, kJSPropertyAttributeNone },
+    { DATASYNC_FUNCTION_API_GET_ALL, getAll, kJSPropertyAttributeNone },
+    { DATASYNC_FUNCTION_API_START_SYNC, startSync, kJSPropertyAttributeNone },
+    { DATASYNC_FUNCTION_API_STOP_SYNC, stopSync, kJSPropertyAttributeNone },
+    { DATASYNC_FUNCTION_API_GET_LAST_SYNC_STATISTICS, getLastSyncStatistics, kJSPropertyAttributeNone },
+
+    { 0, 0, 0 }
+};
+
+JSClassRef JSDataSyncManager::m_jsClassRef = JSClassCreate(JSDataSyncManager::getClassInfo());
+
+void JSDataSyncManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        LOGI("Create datasync manager private object.");
+        IDataSyncManagerPtr datasync(new DataSyncManager());
+        DataSyncManagerPrivObject *priv = new DataSyncManagerPrivObject(context, datasync);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    } else {
+        LOGI("Private object already set.");
+    }
+}
+
+void JSDataSyncManager::finalize(JSObjectRef object)
+{
+    DataSyncManagerPrivObject *priv = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(object));
+    if (priv) {
+        LOGI("Deleting datasync manager private object.");
+        delete priv;
+        JSObjectSetPrivate(object, NULL);
+    }
+}
+
+const JSClassRef JSDataSyncManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSDataSyncManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSDataSyncManager::add(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_ADD);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        DataSyncConverter converter(context);
+
+        SyncProfileInfoPtr profile;
+        if (argumentCount>=1) {
+            if (!JSValueIsObjectOfClass(context, arguments[0], JSSyncProfileInfo::getClassRef())) {
+                ThrowMsg(ConversionException, "Wrong parameter type.");
+            }
+        } else {
+            ThrowMsg(ConversionException, "Wrong parameter type.");
+        }
+
+        profile = JSSyncProfileInfo::getPrivateObject(JSValueToObject(context, arguments[0], NULL));
+        if (!profile) {
+            ThrowMsg(ConversionException, "Parameter conversion failed.");
+        }
+
+        if (NULL!=profile->getServiceInfoJSRef()) {
+            LOGI("Process the JS serviceInfo array attribute.");
+            profile->setServiceInfo(converter.toServiceInfoList(profile->getServiceInfoJSRef()));
+        }
+
+        LOGD("profileName: %s",profile->getProfileName().c_str());
+
+        IEventAddProfilePtr dplEvent(new IEventAddProfile());
+
+        dplEvent->setProfile(profile);
+        dplEvent->setForSynchronousCall();
+        datasyncManager->addProfile(dplEvent);
+
+        if (dplEvent->getResult()) {
+            LOGD("Add succeeded with id: %s",dplEvent->getProfile()->getProfileId().c_str());
+            return JSValueMakeUndefined(context);
+        } else {
+            if (ExceptionCodes::OutOfRangeException==dplEvent->getExceptionCode()) {
+                ThrowMsg(OutOfRangeException, "No more profiles allowed by platform.");
+            } else {
+                ThrowMsg(UnknownException, "Add failed by unknown reason.");
+            }
+        }
+    }
+    Catch(OutOfRangeException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::QUOTA_EXCEEDED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+}
+
+JSValueRef JSDataSyncManager::update(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_UPDATE);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        DataSyncConverter converter(context);
+
+        SyncProfileInfoPtr profile;
+        if (argumentCount>=1) {
+            if (!JSValueIsObjectOfClass(context, arguments[0], JSSyncProfileInfo::getClassRef())) {
+                ThrowMsg(ConversionException, "Wrong parameter type.");
+            }
+        } else {
+            ThrowMsg(ConversionException, "Wrong parameter type.");
+        }
+
+        profile = JSSyncProfileInfo::getPrivateObject(JSValueToObject(context, arguments[0], NULL));
+        if (!profile) {
+            ThrowMsg(ConversionException, "Parameter conversion failed.");
+        }
+
+        if (NULL!=profile->getServiceInfoJSRef()) {
+            LOGI("Process the JS serviceInfo array attribute.");
+            profile->setServiceInfo(converter.toServiceInfoList(profile->getServiceInfoJSRef()));
+        }
+
+        LOGD("profileName: %s",profile->getProfileName().c_str());
+
+        IEventUpdateProfilePtr dplEvent(new IEventUpdateProfile());
+
+        dplEvent->setProfile(profile);
+        dplEvent->setForSynchronousCall();
+        datasyncManager->updateProfile(dplEvent);
+
+        if (dplEvent->getResult()) {
+            LOGD("Update succeeded with id: %s",dplEvent->getProfile()->getProfileId().c_str());
+            return JSValueMakeUndefined(context);
+        } else {
+            ThrowMsg(UnknownException, "Update failed by unknown reason.");
+        }
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+}
+
+JSValueRef JSDataSyncManager::remove(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_REMOVE);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        DataSyncConverter converter(context);
+
+        std::string profileId;
+        if (argumentCount>=1) {
+            profileId = converter.toString(arguments[0]);
+        }
+
+        LOGD("profileId: %s",profileId.c_str());
+
+        IEventRemoveProfilePtr dplEvent(new IEventRemoveProfile());
+
+        dplEvent->setProfileId(profileId);
+        dplEvent->setForSynchronousCall();
+        datasyncManager->removeProfile(dplEvent);
+
+        if (dplEvent->getResult()) {
+            LOGD("Remove succeeded with id: %s",dplEvent->getProfileId().c_str());
+            return JSValueMakeUndefined(context);
+        } else {
+            if (ExceptionCodes::NotFoundException==dplEvent->getExceptionCode()) {
+                ThrowMsg(NotFoundException, "Id not found.");
+            } else {
+                ThrowMsg(UnknownException, "Remove failed by unknown reason.");
+            }
+        }
+    }
+    Catch (NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+}
+
+JSValueRef JSDataSyncManager::getMaxProfilesNum(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_GET_MAX_PROFILES_NUM);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        DataSyncConverter converter(context);
+
+        IEventGetMaxProfilesNumPtr dplEvent(new IEventGetMaxProfilesNum());
+
+        dplEvent->setForSynchronousCall();
+        datasyncManager->getMaxProfilesNum(dplEvent);
+
+        if (dplEvent->getResult()) {
+            LOGD("Max number of profiles: %d",dplEvent->getNumMaxProfiles());
+            return converter.toJSValueRef(dplEvent->getNumMaxProfiles());
+        } else {
+            ThrowMsg(UnknownException, "Get the max number of profiles failed by unknown reason.");
+        }
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+}
+
+JSValueRef JSDataSyncManager::getProfilesNum(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_GET_PROFILES_NUM);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        DataSyncConverter converter(context);
+
+        IEventGetProfilesNumPtr dplEvent(new IEventGetProfilesNum());
+
+        dplEvent->setForSynchronousCall();
+        datasyncManager->getProfilesNum(dplEvent);
+
+        if (dplEvent->getResult()) {
+            LOGD("Number of profiles: %d",dplEvent->getNumProfiles());
+            return converter.toJSValueRef(dplEvent->getNumProfiles());
+        } else {
+            ThrowMsg(UnknownException, "Getting the number of profiles failed by unknown reason.");
+        }
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+}
+
+JSValueRef JSDataSyncManager::get(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_GET);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        DataSyncConverter converter(context);
+
+        std::string profileId;
+        if (argumentCount>=1) {
+            profileId = converter.toString(arguments[0]);
+        }
+
+        LOGD("profileId: %s",profileId.c_str());
+
+        IEventGetProfilePtr dplEvent(new IEventGetProfile());
+
+        dplEvent->setProfileId(profileId);
+        dplEvent->setForSynchronousCall();
+        datasyncManager->getProfile(dplEvent);
+
+        if (dplEvent->getResult()) {
+            LOGD("Get succeeded with id: %s",dplEvent->getProfileId().c_str());
+            return JSSyncProfileInfo::createJSSyncProfileInfo(context, dplEvent->getProfile());
+        } else {
+            if (ExceptionCodes::NotFoundException==dplEvent->getExceptionCode()) {
+                ThrowMsg(NotFoundException, "Id not found.");
+            } else {
+                ThrowMsg(UnknownException, "Get failed by unknown reason.");
+            }
+        }
+    }
+    Catch (NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+}
+
+JSValueRef JSDataSyncManager::getAll(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_GET_ALL);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        DataSyncConverter converter(context);
+
+        IEventGetAllProfilesPtr dplEvent(new IEventGetAllProfiles());
+
+        dplEvent->setForSynchronousCall();
+        datasyncManager->getAllProfiles(dplEvent);
+
+        if (dplEvent->getResult()) {
+            LOGD("Getting all profiles succeeded with length: %u",dplEvent->getProfiles()->size());
+            return converter.toJSValueRefProfileInfoList(dplEvent->getProfiles());
+        } else {
+            ThrowMsg(UnknownException, "Getting all profiles failed by unknown reason.");
+        }
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+}
+
+JSValueRef JSDataSyncManager::startSync(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_START_SYNC);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        JSContextRef globalContext = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        DataSyncConverter converter(context);
+
+        std::string profileId;
+        if (argumentCount>=1) {
+            profileId = converter.toString(arguments[0]);
+        }
+        LOGD("profileId: %s",profileId.c_str());
+
+        IEventStartSyncPtr dplEvent(new IEventStartSync());
+
+        if (argumentCount>=2) {
+            LOGD("Process the listener callback.");
+
+            if (JSValueIsObject(context, arguments[1])) {
+                LOGD("Non-null callbacks.");
+
+                JSObjectRef objectCallbacks = converter.toJSObjectRef(arguments[1]);
+                JSCallbackManagerPtr onProgressCbm(static_cast<JSCallbackManager*>(NULL)), onCompletedCbm(static_cast<JSCallbackManager*>(NULL)), onStoppedCbm(static_cast<JSCallbackManager*>(NULL)), onFailedCbm(static_cast<JSCallbackManager*>(NULL));
+                Validator validator(context);
+
+                JSValueRef onProgress = JSUtils::getJSPropertyOrUndefined(context, objectCallbacks, "onprogress");
+                if (validator.isNullOrUndefined(onProgress)) {
+                    onProgress = NULL;
+                } else if(!validator.isCallback(onProgress)) {
+                    ThrowMsg(ConversionException, "Wrong second parameter type.");
+                }
+
+                JSValueRef onCompleted = JSUtils::getJSPropertyOrUndefined(context, objectCallbacks, "oncompleted");
+                if (validator.isNullOrUndefined(onCompleted)) {
+                    onCompleted = NULL;
+                } else if(!validator.isCallback(onCompleted)) {
+                    ThrowMsg(ConversionException, "Wrong second parameter type.");
+                }
+
+                JSValueRef onStopped = JSUtils::getJSPropertyOrUndefined(context, objectCallbacks, "onstopped");
+                if (validator.isNullOrUndefined(onStopped)) {
+                    onStopped = NULL;
+                } else if(!validator.isCallback(onStopped)) {
+                    ThrowMsg(ConversionException, "Wrong second parameter type.");
+                }
+
+                JSValueRef onFailed = JSUtils::getJSPropertyOrUndefined(context, objectCallbacks, "onfailed");
+                if (validator.isNullOrUndefined(onFailed)) {
+                    onFailed = NULL;
+                } else if(!validator.isCallback(onFailed)) {
+                    ThrowMsg(ConversionException, "Wrong second parameter type.");
+                }
+
+                if (!onProgress && !onCompleted && !onStopped && !onFailed) {
+                    ThrowMsg(ConversionException, "Wrong second parameter type.");
+                }
+
+                onProgressCbm = JSCallbackManager::createObject(globalContext, onProgress, NULL);
+                onCompletedCbm = JSCallbackManager::createObject(globalContext, onCompleted, NULL);
+                onStoppedCbm = JSCallbackManager::createObject(globalContext, onStopped, NULL);
+                onFailedCbm = JSCallbackManager::createObject(globalContext, onFailed, NULL);
+
+                DataSyncStateChangeCallbackPrivateDataPtr privData(new DataSyncStateChangeCallbackPrivateData(onProgressCbm, onCompletedCbm, onStoppedCbm, onFailedCbm));
+                OnDataSyncStateChangedEmitterPtr emitter(new OnDataSyncStateChangedEmitter());
+                emitter->setListener(&DataSyncResponseDispatcher::getInstance());
+                emitter->setEventPrivateData(std::static_pointer_cast<IEventPrivateData>(privData));
+
+                LOGD("Set the emitter.");
+                dplEvent->setEmitter(emitter);
+            } else  if (JSValueIsNull(context, arguments[1]) ) {
+                LOGD("Null or undefined listener.");
+            } else {
+                ThrowMsg(ConversionException, "Wrong second parameter type.");
+            }
+        }
+
+        LOGD("Proceed the start sync event to the platform.");
+
+        dplEvent->setProfileId(profileId);
+        dplEvent->setForSynchronousCall();
+        datasyncManager->startSync(dplEvent);
+
+        if (dplEvent->getResult()) {
+            if(dplEvent->getEmitter()) {
+                LOGD("watcherId: %d",profileId.at(0));
+            }
+
+            LOGD("Starting the sync succeeded.");
+        } else {
+            switch (dplEvent->getExceptionCode()) {
+                case ExceptionCodes::NotFoundException:
+                    ThrowMsg(NotFoundException, "Id not found.");
+                    break;
+                case ExceptionCodes::InvalidArgumentException:
+                    ThrowMsg(InvalidArgumentException, "Invalid argument");
+                    break;
+                default:
+                    ThrowMsg(UnknownException, "Starting the sync failed by unknown reason.");
+                    break;
+            }
+        }
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch (NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSDataSyncManager::stopSync(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_STOP_SYNC);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        DataSyncConverter converter(context);
+
+        std::string profileId;
+        if (argumentCount>=1) {
+            profileId = converter.toString(arguments[0]);
+        }
+        LOGD("profileId: %s",profileId.c_str());
+
+        IEventStopSyncPtr dplEvent(new IEventStopSync());
+
+        dplEvent->setProfileId(profileId);
+        dplEvent->setForSynchronousCall();
+        datasyncManager->stopSync(dplEvent);
+
+        if (dplEvent->getResult()) {
+            LOGD("Stop sync succeeded.");
+        } else {
+            if (ExceptionCodes::NotFoundException==dplEvent->getExceptionCode()) {
+                ThrowMsg(NotFoundException, "Id not found.");
+            } else {
+                ThrowMsg(UnknownException, "Stopping the sync failed by unknown reason.");
+            }
+        }
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch (NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+JSValueRef JSDataSyncManager::getLastSyncStatistics(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    DataSyncManagerPrivObject *privateObject = static_cast<DataSyncManagerPrivObject*>(JSObjectGetPrivate(thisObject));
+
+    AceSecurityStatus status = DATASYNC_CHECK_ACCESS(DATASYNC_FUNCTION_API_GET_LAST_SYNC_STATISTICS);
+
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    Try
+    {
+        if (!privateObject) {
+            ThrowMsg(ConversionException, "Object is null.");
+        }
+
+        IDataSyncManagerPtr datasyncManager = privateObject->getObject();
+
+        DataSyncConverter converter(context);
+
+        std::string profileId;
+        if (argumentCount>=1) {
+            profileId = converter.toString(arguments[0]);
+        }
+
+        LOGD("profileId: %s",profileId.c_str());
+
+        IEventGetLastSyncStatisticsPtr dplEvent(new IEventGetLastSyncStatistics());
+
+        dplEvent->setProfileId(profileId);
+        dplEvent->setForSynchronousCall();
+        datasyncManager->getLastSyncStatistics(dplEvent);
+
+        if (dplEvent->getResult()) {
+            LOGD("Get sync statistics succeeded with length: %u",dplEvent->getSyncStatistics()->size());
+            return converter.toJSValueRefSyncStatisticsList(dplEvent->getSyncStatistics());
+        } else {
+            if (ExceptionCodes::NotFoundException==dplEvent->getExceptionCode()) {
+                ThrowMsg(NotFoundException, "Id not found.");
+            } else {
+                ThrowMsg(UnknownException, "Get statistics failed by unknown reason.");
+            }
+        }
+    }
+    Catch (NotFoundException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_FOUND_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+}
+
+}
+}
diff --git a/src/DataSync/JSDataSyncManager.h b/src/DataSync/JSDataSyncManager.h
new file mode 100755 (executable)
index 0000000..9630e37
--- /dev/null
@@ -0,0 +1,209 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_TIZEN_DATASYNC_MANAGER_H_
+#define _JS_TIZEN_DATASYNC_MANAGER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+
+#include "IDataSyncManager.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+#define TIZEN_DATA_SYNC_MANAGER_INTERFACE "DataSynchronizationManager"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<IDataSyncManagerPtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> DataSyncManagerPrivObject;
+
+#define TIZEN_DATA_SYNC_MODE_MANUAL "MANUAL"
+#define TIZEN_DATA_SYNC_MODE_PERIODIC "PERIODIC"
+#define TIZEN_DATA_SYNC_MODE_PUSH "PUSH"
+
+#define TIZEN_DATA_SYNC_TYPE_TWO_WAY "TWO_WAY"
+#define TIZEN_DATA_SYNC_TYPE_SLOW "SLOW"
+#define TIZEN_DATA_SYNC_TYPE_ONE_WAY_FROM_CLIENT "ONE_WAY_FROM_CLIENT"
+#define TIZEN_DATA_SYNC_TYPE_REFRESH_FROM_CLIENT "REFRESH_FROM_CLIENT"
+#define TIZEN_DATA_SYNC_TYPE_ONE_WAY_FROM_SERVER "ONE_WAY_FROM_SERVER"
+#define TIZEN_DATA_SYNC_TYPE_REFRESH_FROM_SERVER "REFRESH_FROM_SERVER"
+
+#define TIZEN_DATA_SYNC_INTERVAL_5_MINUTES "5_MINUTES"
+#define TIZEN_DATA_SYNC_INTERVAL_15_MINUTES "15_MINUTES"
+#define TIZEN_DATA_SYNC_INTERVAL_1_HOUR "1_HOUR"
+#define TIZEN_DATA_SYNC_INTERVAL_4_HOURS "4_HOURS"
+#define TIZEN_DATA_SYNC_INTERVAL_12_HOURS "12_HOURS"
+#define TIZEN_DATA_SYNC_INTERVAL_1_DAY "1_DAY"
+#define TIZEN_DATA_SYNC_INTERVAL_1_WEEK "1_WEEK"
+#define TIZEN_DATA_SYNC_INTERVAL_1_MONTH "1_MONTH"
+
+#define TIZEN_DATA_SYNC_SERVICE_TYPE_CONTACT "CONTACT"
+#define TIZEN_DATA_SYNC_SERVICE_TYPE_EVENT "EVENT"
+
+#define TIZEN_DATA_SYNC_STATUS_SUCCESS "SUCCESS"
+#define TIZEN_DATA_SYNC_STATUS_FAIL "FAIL"
+#define TIZEN_DATA_SYNC_STATUS_STOP "STOP"
+#define TIZEN_DATA_SYNC_STATUS_NONE "NONE"
+
+class JSDataSyncManager
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+private:
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Adds a profile.
+     */
+    static JSValueRef add(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Updates a profile.
+     */
+    static JSValueRef update(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Removes a profile.
+     */
+    static JSValueRef remove(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Gets the maximum number of supported profiles.
+     */
+    static JSValueRef getMaxProfilesNum(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Gets the present number of profiles.
+     */
+    static JSValueRef getProfilesNum(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Gets a profile.
+     */
+    static JSValueRef get(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Get all profiles.
+     */
+    static JSValueRef getAll(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Stars a sync.
+     */
+    static JSValueRef startSync(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Stops a sync.
+     */
+    static JSValueRef stopSync(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Gets the last sync statistics.
+     */
+    static JSValueRef getLastSyncStatistics(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+}
+}
+
+#endif /* _JS_TIZEN_DATASYNC_MANAGER_H_ */
+
diff --git a/src/DataSync/JSSyncInfo.cpp b/src/DataSync/JSSyncInfo.cpp
new file mode 100755 (executable)
index 0000000..f969e17
--- /dev/null
@@ -0,0 +1,304 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "JSSyncInfo.h"
+#include "DataSyncConverter.h"
+
+#include <JSWebAPIErrorFactory.h>
+#include <CommonsJavaScript/Converter.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+JSClassDefinition JSSyncInfo::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_SYNC_INFO_INTERFACE,
+    NULL, //parentClass
+    m_property,
+    NULL, //staticValues,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //constructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSSyncInfo::m_property[] = {
+    { TIZEN_SYNC_INFO_URL, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_INFO_ID, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_INFO_PASSWORD, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_INFO_MODE, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_INFO_TYPE, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_INFO_INTERVAL, getProperty, setProperty, kJSPropertyAttributeNone },
+
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSSyncInfo::m_jsClassRef = JSClassCreate(
+        JSSyncInfo::getClassInfo());
+
+const JSClassDefinition* JSSyncInfo::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+JSClassRef JSSyncInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+JSObjectRef JSSyncInfo::createJSSyncInfo(JSContextRef context, SyncInfoPtr syncInfo)
+{
+    SyncInfoPrivateObject *priv = new SyncInfoPrivateObject(context, syncInfo);
+    return JSObjectMake(context, getClassRef(), priv);
+}
+
+void JSSyncInfo::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        LOGD("Create JSSyncInfo private object.");
+        SyncInfoPtr syncInfo( new SyncInfo() );
+        SyncInfoPrivateObject *priv = new SyncInfoPrivateObject(context, syncInfo);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    } else {
+        LOGD("Private object already set.");
+    }
+}
+
+void JSSyncInfo::finalize(JSObjectRef object)
+{
+    SyncInfoPrivateObject* priv = static_cast<SyncInfoPrivateObject*>(JSObjectGetPrivate(object));
+    if (priv) {
+        LOGD("Deleting JSSyncInfo private object.");
+        delete priv;
+        JSObjectSetPrivate(object, NULL);
+    }
+}
+
+SyncInfoPtr JSSyncInfo::getPrivateObject(JSObjectRef object)
+{
+    SyncInfoPrivateObject *priv = static_cast<SyncInfoPrivateObject*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        ThrowMsg(NullPointerException, "Private object is null.");
+    }
+
+    SyncInfoPtr syncInfo = priv->getObject();
+    if (!syncInfo) {
+        ThrowMsg(NullPointerException, "JSSyncInfo object is null.");
+    }
+    return syncInfo;
+}
+
+void JSSyncInfo::setPrivateObject(const SyncInfoPtr &syncInfo,
+        JSContextRef ctx,
+        const JSObjectRef object)
+{
+    Try
+    {
+        SyncInfoPrivateObject *priv = static_cast<SyncInfoPrivateObject*>(JSObjectGetPrivate(object));
+        delete priv;
+        priv = new SyncInfoPrivateObject(ctx, syncInfo);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    }
+    Catch(Exception)
+    {
+        LOGE("Error during setting JSSyncInfo object.");
+    }
+}
+
+JSObjectRef JSSyncInfo::constructor(JSContextRef context,
+    JSObjectRef constructor,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    SyncInfoPtr syncInfo( new SyncInfo() );
+
+    Try
+    {
+        DataSyncConverter converter(context);
+
+
+        if (argumentCount>=1) {
+            syncInfo->setUrl(converter.toString(arguments[0]));
+        }
+        if (argumentCount>=2) {
+            syncInfo->setId(converter.toString(arguments[1]));
+        }
+        if (argumentCount>=3) {
+            syncInfo->setPassword(converter.toString(arguments[2]));
+        }
+        if (argumentCount>=4) {
+            syncInfo->setSyncMode(converter.toSyncMode(converter.toString(arguments[3])));
+        }
+
+        LOGD("mode: %d",syncInfo->getSyncMode());
+
+        if (SyncInfo::MANUAL_MODE==syncInfo->getSyncMode()) {
+            if (argumentCount>=5) {
+                syncInfo->setSyncType(converter.toSyncType(converter.toString(arguments[4])));
+            }
+        } else if (SyncInfo::PERIODIC_MODE==syncInfo->getSyncMode()) {
+            if (argumentCount>=5) {
+                syncInfo->setSyncInterval(converter.toSyncInterval(converter.toString(arguments[4])));
+            }
+        } else {
+            LOGD("The sync mode should be push.");
+        }
+
+        return createJSSyncInfo(context, syncInfo);
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+
+    return createJSSyncInfo(context, syncInfo);
+}
+
+JSValueRef JSSyncInfo::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    Try
+    {
+        SyncInfoPrivateObject* priv = static_cast<SyncInfoPrivateObject*>(JSObjectGetPrivate(object));
+        if (!priv) {
+            ThrowMsg(NullPointerException, "Private object is NULL.");
+        }
+
+        SyncInfoPtr syncInfo = priv->getObject();
+
+        DataSyncConverter converter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_URL)) {
+            return converter.toJSValueRef(syncInfo->getUrl());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_ID)) {
+            // For a privacy reason.
+            return JSValueMakeNull(context);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_PASSWORD)) {
+            // For a privacy reason.
+            return JSValueMakeNull(context);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_MODE)) {
+            return converter.toJSValueRef(converter.toTizenValue(syncInfo->getSyncMode()));
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_TYPE)) {
+            return converter.toJSValueRef(converter.toTizenValue(syncInfo->getSyncType()));
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_INTERVAL)) {
+            if( SyncInfo::INTERVAL_UNDEFINED==syncInfo->getSyncInterval() ) {
+                return JSValueMakeUndefined(context);
+            } else {
+                return converter.toJSValueRef(converter.toTizenValue(syncInfo->getSyncInterval()));
+            }
+        } else {
+            LOGD("Wrong property name.");
+        }
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+bool JSSyncInfo::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    Try
+    {
+        SyncInfoPrivateObject* priv = static_cast<SyncInfoPrivateObject*>(JSObjectGetPrivate(object));
+        if (!priv) {
+            ThrowMsg(NullPointerException, "Private object is NULL.");
+        }
+
+        SyncInfoPtr syncInfo = priv->getObject();
+
+        DataSyncConverter converter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_URL)) {
+            syncInfo->setUrl(converter.toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_ID)) {
+            syncInfo->setId(converter.toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_PASSWORD)) {
+            syncInfo->setPassword(converter.toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_MODE)) {
+            syncInfo->setSyncMode(converter.toSyncMode(converter.toString(value)));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_TYPE)) {
+            syncInfo->setSyncType(converter.toSyncType(converter.toString(value)));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_INFO_INTERVAL)) {
+            syncInfo->setSyncInterval(converter.toSyncInterval(converter.toString(value)));
+            return true;
+        } else {
+            LOGD("Wrong property name.");
+        }
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+    }
+
+    return true;
+}
+
+}
+}
diff --git a/src/DataSync/JSSyncInfo.h b/src/DataSync/JSSyncInfo.h
new file mode 100755 (executable)
index 0000000..df367f3
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_SYNC_INFO_H_
+#define _JS_SYNC_INFO_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "SyncInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+#define TIZEN_SYNC_INFO_INTERFACE "SyncInfo"
+
+#define TIZEN_SYNC_INFO_URL "url"
+#define TIZEN_SYNC_INFO_ID "id"
+#define TIZEN_SYNC_INFO_PASSWORD "password"
+#define TIZEN_SYNC_INFO_MODE "mode"
+#define TIZEN_SYNC_INFO_TYPE "type"
+#define TIZEN_SYNC_INFO_INTERVAL "interval"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<SyncInfoPtr,
+    WrtDeviceApis::CommonsJavaScript::NoOwnership> SyncInfoPrivateObject;
+
+class JSSyncInfo
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static JSObjectRef createJSSyncInfo(JSContextRef context, SyncInfoPtr syncInfo);
+
+    static SyncInfoPtr getPrivateObject(JSObjectRef object);
+
+    static void setPrivateObject(const SyncInfoPtr &syncInfo,
+            JSContextRef ctx,
+            const JSObjectRef object);
+
+    /**
+     * Constructor for the SyncInfo interface.
+     */
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+};
+
+}
+}
+
+#endif /* _JS_SYNC_INFO_H_ */
diff --git a/src/DataSync/JSSyncProfileInfo.cpp b/src/DataSync/JSSyncProfileInfo.cpp
new file mode 100755 (executable)
index 0000000..eea74d9
--- /dev/null
@@ -0,0 +1,301 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "JSSyncProfileInfo.h"
+#include "JSSyncInfo.h"
+#include "JSSyncServiceInfo.h"
+#include "DataSyncConverter.h"
+
+#include <JSWebAPIErrorFactory.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+JSClassDefinition JSSyncProfileInfo::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_SYNC_PROFILE_INFO_INTERFACE,
+    NULL, //parentClass
+    m_property,
+    NULL, //staticValues,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //constructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSSyncProfileInfo::m_property[] = {
+    { TIZEN_SYNC_PROFILE_INFO_PROFILE_ID, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_PROFILE_INFO_PROFILE_NAME, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_PROFILE_INFO_SYNC_INFO, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_PROFILE_INFO_SERVICE_INFO, getProperty, setProperty, kJSPropertyAttributeNone },
+
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSSyncProfileInfo::m_jsClassRef = JSClassCreate(
+        JSSyncProfileInfo::getClassInfo());
+
+const JSClassDefinition* JSSyncProfileInfo::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+JSClassRef JSSyncProfileInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+JSObjectRef JSSyncProfileInfo::createJSSyncProfileInfo(JSContextRef context, SyncProfileInfoPtr syncProfileInfo)
+{
+    SyncProfileInfoPrivateObject *priv = new SyncProfileInfoPrivateObject(context, syncProfileInfo);
+    return JSObjectMake(context, getClassRef(), priv);
+}
+
+void JSSyncProfileInfo::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        LOGD("Create JSSyncProfileInfo private object.");
+        SyncProfileInfoPtr syncProfileInfo( new SyncProfileInfo() );
+        SyncProfileInfoPrivateObject *priv = new SyncProfileInfoPrivateObject(context, syncProfileInfo);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    } else {
+        LOGD("Private object already set.");
+    }
+}
+
+void JSSyncProfileInfo::finalize(JSObjectRef object)
+{
+    SyncProfileInfoPrivateObject* priv = static_cast<SyncProfileInfoPrivateObject*>(JSObjectGetPrivate(object));
+    if (priv) {
+        LOGD("Deleting JSSyncProfileInfo private object.");
+        delete priv;
+        JSObjectSetPrivate(object, NULL);
+    }
+}
+
+SyncProfileInfoPtr JSSyncProfileInfo::getPrivateObject(JSObjectRef object)
+{
+    SyncProfileInfoPrivateObject *priv = static_cast<SyncProfileInfoPrivateObject*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        ThrowMsg(NullPointerException, "Private object is null.");
+    }
+
+    SyncProfileInfoPtr syncProfileInfo = priv->getObject();
+    if (!syncProfileInfo) {
+        ThrowMsg(NullPointerException, "JSSyncProfileInfo object is null.");
+    }
+    return syncProfileInfo;
+}
+
+void JSSyncProfileInfo::setPrivateObject(const SyncProfileInfoPtr &syncProfileInfo,
+        JSContextRef ctx,
+        const JSObjectRef object)
+{
+    Try
+    {
+        SyncProfileInfoPrivateObject *priv = static_cast<SyncProfileInfoPrivateObject*>(JSObjectGetPrivate(object));
+        delete priv;
+        priv = new SyncProfileInfoPrivateObject(ctx, syncProfileInfo);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    }
+    Catch(Exception)
+    {
+        LOGE("Error during setting JSSyncProfileInfo object.");
+    }
+}
+
+JSObjectRef JSSyncProfileInfo::constructor(JSContextRef context,
+    JSObjectRef constructor,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    SyncProfileInfoPtr syncProfileInfo( new SyncProfileInfo() );
+
+    Try
+    {
+        DataSyncConverter converter(context);
+
+        SyncProfileInfoPtr syncProfileInfo( new SyncProfileInfo() );
+
+        if (argumentCount>=1) {
+            syncProfileInfo->setProfileName(converter.toString(arguments[0]));
+        }
+        if (argumentCount>=2) {
+            if (!JSValueIsObjectOfClass(context, arguments[1], JSSyncInfo::getClassRef())) {
+                //ThrowMsg(ConversionException, "Wrong second parameter type.");
+            } else {
+                syncProfileInfo->setSyncInfo(JSSyncInfo::getPrivateObject(JSValueToObject(context, arguments[1], exception)));
+            }
+        }
+        if (argumentCount>=3) {
+            if(!JSIsArrayValue(context, arguments[2])) {
+                //ThrowMsg(ConversionException, "Wrong third parameter type.");
+            } else {
+                syncProfileInfo->setServiceInfo(converter.toServiceInfoList(arguments[2]));
+            }
+        }
+
+        LOGD("profileName: %s, serviceInfo.length: %u",syncProfileInfo->getProfileName().c_str(),syncProfileInfo->getServiceInfo()->size());
+
+        return createJSSyncProfileInfo(context, syncProfileInfo);
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+
+    return createJSSyncProfileInfo(context, syncProfileInfo);
+}
+
+JSValueRef JSSyncProfileInfo::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    Try
+    {
+        SyncProfileInfoPrivateObject* priv = static_cast<SyncProfileInfoPrivateObject*>(JSObjectGetPrivate(object));
+        if (!priv) {
+            ThrowMsg(NullPointerException, "Private object is NULL.");
+        }
+        JSContextRef globalContext = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        SyncProfileInfoPtr syncProfileInfo = priv->getObject();
+
+        DataSyncConverter converter(globalContext);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_PROFILE_INFO_PROFILE_ID)) {
+            return converter.toJSValueRef(syncProfileInfo->getProfileId());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_PROFILE_INFO_PROFILE_NAME)) {
+            return converter.toJSValueRef(syncProfileInfo->getProfileName());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_PROFILE_INFO_SYNC_INFO)) {
+            return JSUtils::makeObject(context, JSSyncInfo::getClassRef(), syncProfileInfo->getSyncInfo());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_PROFILE_INFO_SERVICE_INFO)) {
+            if(syncProfileInfo->getServiceInfoJSRef()) {
+                return syncProfileInfo->getServiceInfoJSRef();
+            } else {
+                LOGI("Create a JS object for serviceInfo.");
+                JSValueRef jsServiceInfo = converter.toJSValueRefServiceInfoList(syncProfileInfo->getServiceInfo());
+                syncProfileInfo->setServiceInfoJSRef(converter.toJSObjectRef(jsServiceInfo));
+                JSValueProtect(globalContext, jsServiceInfo);
+                syncProfileInfo->setContext(globalContext);
+                return jsServiceInfo;
+           }
+        } else {
+            LOGD("Wrong property name.");
+        }
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+bool JSSyncProfileInfo::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    Try
+    {
+        SyncProfileInfoPrivateObject* priv = static_cast<SyncProfileInfoPrivateObject*>(JSObjectGetPrivate(object));
+        if (!priv) {
+            ThrowMsg(NullPointerException, "Private object is NULL.");
+        }
+        SyncProfileInfoPtr syncProfileInfo = priv->getObject();
+
+        DataSyncConverter converter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_PROFILE_INFO_PROFILE_NAME)) {
+            syncProfileInfo->setProfileName(converter.toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_PROFILE_INFO_SYNC_INFO)) {
+            if (!JSValueIsObjectOfClass(context, value, JSSyncInfo::getClassRef())) {
+                ThrowMsg(ConversionException, "Wrong input type.");
+            }
+            syncProfileInfo->setSyncInfo(JSSyncInfo::getPrivateObject(JSValueToObject(context, value, exception)));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_PROFILE_INFO_SERVICE_INFO)) {
+            syncProfileInfo->setServiceInfo(converter.toServiceInfoList(value));
+
+            if(syncProfileInfo->getServiceInfoJSRef()) {
+                LOGI("Replace a JS object for serviceInfo.");
+                JSValueUnprotect(syncProfileInfo->getContext(), syncProfileInfo->getServiceInfoJSRef());
+                syncProfileInfo->setServiceInfoJSRef(converter.toJSObjectRef(value));
+                JSValueProtect(syncProfileInfo->getContext(), value);
+            }
+
+            return true;
+        } else {
+            LOGD("Wrong property name.");
+        }
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+    }
+
+    return true;
+}
+
+}
+}
diff --git a/src/DataSync/JSSyncProfileInfo.h b/src/DataSync/JSSyncProfileInfo.h
new file mode 100755 (executable)
index 0000000..7fbc1c3
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_SYNC_PROFILE_INFO_H_
+#define _JS_SYNC_PROFILE_INFO_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "SyncProfileInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+#define TIZEN_SYNC_PROFILE_INFO_INTERFACE "SyncProfileInfo"
+
+#define TIZEN_SYNC_PROFILE_INFO_PROFILE_ID "profileId"
+#define TIZEN_SYNC_PROFILE_INFO_PROFILE_NAME "profileName"
+#define TIZEN_SYNC_PROFILE_INFO_SYNC_INFO "syncInfo"
+#define TIZEN_SYNC_PROFILE_INFO_SERVICE_INFO "serviceInfo"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<SyncProfileInfoPtr,
+    WrtDeviceApis::CommonsJavaScript::NoOwnership> SyncProfileInfoPrivateObject;
+
+class JSSyncProfileInfo
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static JSObjectRef createJSSyncProfileInfo(JSContextRef context, SyncProfileInfoPtr syncProfileInfo);
+
+    static SyncProfileInfoPtr getPrivateObject(JSObjectRef object);
+
+    static void setPrivateObject(const SyncProfileInfoPtr &syncProfileInfo,
+            JSContextRef ctx,
+            const JSObjectRef object);
+
+    /**
+     * Constructor for the SyncProfileInfo interface.
+     */
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+};
+
+}
+}
+
+#endif /* _JS_SYNC_PROFILE_INFO_H_ */
diff --git a/src/DataSync/JSSyncServiceInfo.cpp b/src/DataSync/JSSyncServiceInfo.cpp
new file mode 100755 (executable)
index 0000000..7fef369
--- /dev/null
@@ -0,0 +1,284 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "JSSyncServiceInfo.h"
+#include <JSWebAPIErrorFactory.h>
+#include <CommonsJavaScript/Converter.h>
+#include "DataSyncConverter.h"
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+JSClassDefinition JSSyncServiceInfo::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_SYNC_SERVICE_INFO_INTERFACE,
+    NULL, //parentClass
+    m_property,
+    NULL, //staticValues,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //constructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSSyncServiceInfo::m_property[] = {
+    { TIZEN_SYNC_SERVICE_INFO_ENABLE, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_SERVICE_INFO_SERVICE_TYPE, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_SERVICE_INFO_SERVER_DATABSE_URI, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_SERVICE_INFO_ID, getProperty, setProperty, kJSPropertyAttributeNone },
+    { TIZEN_SYNC_SERVICE_INFO_PASSWORD, getProperty, setProperty, kJSPropertyAttributeNone },
+
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSSyncServiceInfo::m_jsClassRef = JSClassCreate(
+        JSSyncServiceInfo::getClassInfo());
+
+const JSClassDefinition* JSSyncServiceInfo::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+JSClassRef JSSyncServiceInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+JSObjectRef JSSyncServiceInfo::createJSSyncServiceInfo(JSContextRef context, SyncServiceInfoPtr syncServiceInfo)
+{
+    SyncServiceInfoPrivateObject *priv = new SyncServiceInfoPrivateObject(context, syncServiceInfo);
+    return JSObjectMake(context, getClassRef(), priv);
+}
+
+void JSSyncServiceInfo::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        LOGD("Create JSSyncServiceInfo private object.");
+        SyncServiceInfoPtr syncServiceInfo( new SyncServiceInfo() );
+        SyncServiceInfoPrivateObject *priv = new SyncServiceInfoPrivateObject(context, syncServiceInfo);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    } else {
+        LOGD("Private object already set.");
+    }
+}
+
+void JSSyncServiceInfo::finalize(JSObjectRef object)
+{
+    SyncServiceInfoPrivateObject* priv = static_cast<SyncServiceInfoPrivateObject*>(JSObjectGetPrivate(object));
+    if (priv) {
+        LOGD("Deleting JSSyncServiceInfo private object.");
+        delete priv;
+        JSObjectSetPrivate(object, NULL);
+    }
+}
+
+SyncServiceInfoPtr JSSyncServiceInfo::getPrivateObject(JSObjectRef object)
+{
+    SyncServiceInfoPrivateObject *priv = static_cast<SyncServiceInfoPrivateObject*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        ThrowMsg(NullPointerException, "Private object is null.");
+    }
+
+    SyncServiceInfoPtr syncServiceInfo = priv->getObject();
+    if (!syncServiceInfo) {
+        ThrowMsg(NullPointerException, "JSSyncServiceInfo object is null.");
+    }
+    return syncServiceInfo;
+}
+
+void JSSyncServiceInfo::setPrivateObject(const SyncServiceInfoPtr &syncServiceInfo,
+        JSContextRef ctx,
+        const JSObjectRef object)
+{
+    Try
+    {
+        SyncServiceInfoPrivateObject *priv = static_cast<SyncServiceInfoPrivateObject*>(JSObjectGetPrivate(object));
+        delete priv;
+        priv = new SyncServiceInfoPrivateObject(ctx, syncServiceInfo);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    }
+    Catch(Exception)
+    {
+        LOGE("Error during setting JSSyncServiceInfo object.");
+    }
+}
+
+JSObjectRef JSSyncServiceInfo::constructor(JSContextRef context,
+    JSObjectRef constructor,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    SyncServiceInfoPtr syncServiceInfo( new SyncServiceInfo() );
+
+    Try
+    {
+        DataSyncConverter converter(context);
+
+
+        if (argumentCount>=1) {
+            syncServiceInfo->setEnable(converter.toBool(arguments[0]));
+        }
+        if (argumentCount>=2) {
+            syncServiceInfo->setSyncServiceType(converter.toSyncServiceType(converter.toString(arguments[1])));
+        }
+        if (argumentCount>=3) {
+            syncServiceInfo->setServerDatabaseUri(converter.toString(arguments[2]));
+        }
+        if (argumentCount>=4) {
+            syncServiceInfo->setId(converter.toString(arguments[3]));
+        }
+        if (argumentCount>=5) {
+            syncServiceInfo->setPassword(converter.toString(arguments[4]));
+        }
+
+        LOGD("enable: %d, serviceType: %d",syncServiceInfo->getEnable(),syncServiceInfo->getSyncServiceType());
+
+        return createJSSyncServiceInfo(context, syncServiceInfo);
+    }
+    Catch(UnsupportedException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::INVALID_VALUES_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(ConversionException)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, _rethrown_exception.GetMessage());
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+        //return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, _rethrown_exception.GetMessage());
+    }
+
+    return createJSSyncServiceInfo(context, syncServiceInfo);
+}
+
+JSValueRef JSSyncServiceInfo::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    Try
+    {
+        SyncServiceInfoPrivateObject* priv = static_cast<SyncServiceInfoPrivateObject*>(JSObjectGetPrivate(object));
+        if (!priv) {
+            ThrowMsg(NullPointerException, "Private object is NULL.");
+        }
+
+        SyncServiceInfoPtr syncServiceInfo = priv->getObject();
+
+        DataSyncConverter converter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_ENABLE)) {
+            return converter.toJSValueRef(syncServiceInfo->getEnable());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_SERVICE_TYPE)) {
+            return converter.toJSValueRef(converter.toTizenValue(syncServiceInfo->getSyncServiceType()));
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_SERVER_DATABSE_URI)) {
+            return converter.toJSValueRef(syncServiceInfo->getServerDatabaseUri());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_ID)) {
+            // For a privacy reason.
+            return JSValueMakeNull(context);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_PASSWORD)) {
+            // For a privacy reason.
+            return JSValueMakeNull(context);
+        } else {
+            LOGD("Wrong property name.");
+        }
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+bool JSSyncServiceInfo::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    Try
+    {
+        SyncServiceInfoPrivateObject* priv = static_cast<SyncServiceInfoPrivateObject*>(JSObjectGetPrivate(object));
+        if (!priv) {
+            ThrowMsg(NullPointerException, "Private object is NULL.");
+        }
+
+        SyncServiceInfoPtr syncServiceInfo = priv->getObject();
+
+        DataSyncConverter converter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_ENABLE)) {
+            syncServiceInfo->setEnable(converter.toBool(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_SERVICE_TYPE)) {
+            syncServiceInfo->setSyncServiceType(converter.toSyncServiceType(converter.toString(value)));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_SERVER_DATABSE_URI)) {
+            syncServiceInfo->setServerDatabaseUri(converter.toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_ID)) {
+            syncServiceInfo->setId(converter.toString(value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_SERVICE_INFO_PASSWORD)) {
+            syncServiceInfo->setPassword(converter.toString(value));
+            return true;
+        } else {
+            LOGD("Wrong property name.");
+        }
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+    }
+
+    return true;
+}
+
+}
+}
diff --git a/src/DataSync/JSSyncServiceInfo.h b/src/DataSync/JSSyncServiceInfo.h
new file mode 100755 (executable)
index 0000000..608c5a8
--- /dev/null
@@ -0,0 +1,105 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_SYNC_SERVICE_INFO_H_
+#define _JS_SYNC_SERVICE_INFO_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "SyncServiceInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+#define TIZEN_SYNC_SERVICE_INFO_INTERFACE "SyncServiceInfo"
+
+#define TIZEN_SYNC_SERVICE_INFO_ENABLE "enable"
+#define TIZEN_SYNC_SERVICE_INFO_SERVICE_TYPE "serviceType"
+#define TIZEN_SYNC_SERVICE_INFO_SERVER_DATABSE_URI "serverDatabaseUri"
+#define TIZEN_SYNC_SERVICE_INFO_ID "id"
+#define TIZEN_SYNC_SERVICE_INFO_PASSWORD "password"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<SyncServiceInfoPtr,
+    WrtDeviceApis::CommonsJavaScript::NoOwnership> SyncServiceInfoPrivateObject;
+
+class JSSyncServiceInfo
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static JSObjectRef createJSSyncServiceInfo(JSContextRef context, SyncServiceInfoPtr syncServiceInfo);
+
+    static SyncServiceInfoPtr getPrivateObject(JSObjectRef object);
+
+    static void setPrivateObject(const SyncServiceInfoPtr &syncServiceInfo,
+            JSContextRef ctx,
+            const JSObjectRef object);
+
+    /**
+     * Constructor for the SyncInfo interface.
+     */
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+};
+
+}
+}
+
+#endif /* _JS_SYNC_SERVICE_INFO_H_ */
diff --git a/src/DataSync/JSSyncStatistics.cpp b/src/DataSync/JSSyncStatistics.cpp
new file mode 100644 (file)
index 0000000..a102f6b
--- /dev/null
@@ -0,0 +1,204 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "JSSyncStatistics.h"
+#include "DataSyncConverter.h"
+
+#include <JSWebAPIErrorFactory.h>
+#include <CommonsJavaScript/Converter.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+JSClassDefinition JSSyncStatistics::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_SYNC_STATISTICS_INTERFACE,
+    NULL, //parentClass
+    m_property,
+    NULL, //staticValues,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //constructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSSyncStatistics::m_property[] = {
+    { TIZEN_SYNC_STATISTICS_SYNC_STATUS, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_SERVICE_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_LAST_SYNC_TIME, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_TOTAL, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_ADDED, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_UPDATED, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_REMOVED, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_TOTAL, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_ADDED, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_UPDATED, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+    { TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_REMOVED, getProperty, NULL, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
+
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSSyncStatistics::m_jsClassRef = JSClassCreate(
+        JSSyncStatistics::getClassInfo());
+
+const JSClassDefinition* JSSyncStatistics::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+JSClassRef JSSyncStatistics::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+JSObjectRef JSSyncStatistics::createJSSyncStatistics(JSContextRef context, SyncStatisticsPtr syncStatistics)
+{
+    SyncStatisticsPrivateObject *priv = new SyncStatisticsPrivateObject(context, syncStatistics);
+    return JSObjectMake(context, getClassRef(), priv);
+}
+
+void JSSyncStatistics::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        LOGD("Create JSSyncStatistics private object.");
+        SyncStatisticsPtr syncStatistics( new SyncStatistics() );
+        SyncStatisticsPrivateObject *priv = new SyncStatisticsPrivateObject(context, syncStatistics);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    } else {
+        LOGD("Private object already set.");
+    }
+}
+
+void JSSyncStatistics::finalize(JSObjectRef object)
+{
+    SyncStatisticsPrivateObject* priv = static_cast<SyncStatisticsPrivateObject*>(JSObjectGetPrivate(object));
+    if (priv) {
+        LOGD("Deleting JSSyncStatistics private object.");
+        delete priv;
+        JSObjectSetPrivate(object, NULL);
+    }
+}
+
+SyncStatisticsPtr JSSyncStatistics::getPrivateObject(JSObjectRef object)
+{
+    SyncStatisticsPrivateObject *priv = static_cast<SyncStatisticsPrivateObject*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        ThrowMsg(NullPointerException, "Private object is null.");
+    }
+
+    SyncStatisticsPtr syncStatistics = priv->getObject();
+    if (!syncStatistics) {
+        ThrowMsg(NullPointerException, "JSSyncStatistics object is null.");
+    }
+    return syncStatistics;
+}
+
+void JSSyncStatistics::setPrivateObject(const SyncStatisticsPtr &syncStatistics,
+        JSContextRef ctx,
+        const JSObjectRef object)
+{
+    Try
+    {
+        SyncStatisticsPrivateObject *priv = static_cast<SyncStatisticsPrivateObject*>(JSObjectGetPrivate(object));
+        delete priv;
+        priv = new SyncStatisticsPrivateObject(ctx, syncStatistics);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    }
+    Catch(Exception)
+    {
+        LOGE("Error during setting JSSyncStatistics object.");
+    }
+}
+
+JSValueRef JSSyncStatistics::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    Try
+    {
+        SyncStatisticsPrivateObject* priv = static_cast<SyncStatisticsPrivateObject*>(JSObjectGetPrivate(object));
+        if (!priv) {
+            ThrowMsg(NullPointerException, "Private object is NULL.");
+        }
+
+        SyncStatisticsPtr syncStatistics = priv->getObject();
+
+        DataSyncConverter converter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_SYNC_STATUS)) {
+            return converter.toJSValueRef(converter.toTizenValue(syncStatistics->getSyncStatus()));
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_SERVICE_TYPE)) {
+            return converter.toJSValueRef(converter.toTizenValue(syncStatistics->getServiceType()));
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_LAST_SYNC_TIME)) {
+            if(UNDEFILED_TIME==syncStatistics->getLastSyncTime()) {
+                return JSValueMakeUndefined(context);
+            } else {
+                return converter.toJSValueRef((time_t)(syncStatistics->getLastSyncTime()));
+            }
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_TOTAL)) {
+            return converter.toJSValueRef(syncStatistics->getServerToClientTotal());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_ADDED)) {
+            return converter.toJSValueRef(syncStatistics->getServerToClientAdded());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_UPDATED)) {
+            return converter.toJSValueRef(syncStatistics->getServerToClientUpdated());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_REMOVED)) {
+            return converter.toJSValueRef(syncStatistics->getServerToClientRemoved());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_TOTAL)) {
+            return converter.toJSValueRef(syncStatistics->getClientToServerTotal());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_ADDED)) {
+            return converter.toJSValueRef(syncStatistics->getClientToServerAdded());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_UPDATED)) {
+            return converter.toJSValueRef(syncStatistics->getClientToServerUpdated());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_REMOVED)) {
+            return converter.toJSValueRef(syncStatistics->getClientToServerRemoved());
+        } else {
+            LOGD("Wrong property name.");
+        }
+    }
+    Catch(Exception)
+    {
+        LOGW("Exception: %s",_rethrown_exception.GetMessage().c_str());
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+}
+}
diff --git a/src/DataSync/JSSyncStatistics.h b/src/DataSync/JSSyncStatistics.h
new file mode 100755 (executable)
index 0000000..797433a
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _JS_SYNC_STATISTICS_H_
+#define _JS_SYNC_STATISTICS_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "SyncStatistics.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+#define TIZEN_SYNC_STATISTICS_INTERFACE "SyncStatistics"
+
+#define TIZEN_SYNC_STATISTICS_SYNC_STATUS "syncStatus"
+#define TIZEN_SYNC_STATISTICS_SERVICE_TYPE "serviceType"
+#define TIZEN_SYNC_STATISTICS_LAST_SYNC_TIME "lastSyncTime"
+#define TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_TOTAL "serverToClientTotal"
+#define TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_ADDED "serverToClientAdded"
+#define TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_UPDATED "serverToClientUpdated"
+#define TIZEN_SYNC_STATISTICS_SERVER_TO_CLIENT_REMOVED "serverToClientRemoved"
+#define TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_TOTAL "clientToServerTotal"
+#define TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_ADDED "clientToServerAdded"
+#define TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_UPDATED "clientToServerUpdated"
+#define TIZEN_SYNC_STATISTICS_CLIENT_TO_SERVER_REMOVED "clientToServerRemoved"
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<SyncStatisticsPtr,
+    WrtDeviceApis::CommonsJavaScript::NoOwnership> SyncStatisticsPrivateObject;
+
+class JSSyncStatistics
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static JSObjectRef createJSSyncStatistics(JSContextRef context, SyncStatisticsPtr syncStatistics);
+
+    static SyncStatisticsPtr getPrivateObject(JSObjectRef object);
+
+    static void setPrivateObject(const SyncStatisticsPtr &syncStatistics,
+            JSContextRef ctx,
+            const JSObjectRef object);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+};
+
+}
+}
+
+#endif /* _JS_SYNC_STATISTICS_H_ */
diff --git a/src/DataSync/OnDataSyncStateChanged.h b/src/DataSync/OnDataSyncStateChanged.h
new file mode 100755 (executable)
index 0000000..f2d90bc
--- /dev/null
@@ -0,0 +1,136 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_ON_DATASYNC_STATE_CHANGED_H_
+#define _ABSTRACT_LAYER_ON_DATASYNC_STATE_CHANGED_H_
+
+#include <Commons/IEvent.h>
+
+#include <Commons/ListenerEvent.h>
+#include <Commons/Emitters.h>
+
+#include <string>
+
+#include "SyncServiceInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class OnDataSyncStateChanged : public WrtDeviceApis::Commons::ListenerEvent<OnDataSyncStateChanged>
+{
+public:
+    typedef enum
+    {
+        PROGRESS_STATUS,
+        COMPLETE_STATUS,
+        FAIL_STATUS,
+        STOP_STATUS,
+        UNDEFINED_STATUS
+    } SyncSessionStatus;
+
+    OnDataSyncStateChanged(){
+        m_result = false;
+        m_profileId = "";
+        m_serviceType = SyncServiceInfo::UNDEFINED_SERVICE_TYPE;
+        m_isFromServer = false;
+        m_totalPerService = 0;
+        m_syncedPerService = 0;
+    }
+    ~OnDataSyncStateChanged() {
+    }
+
+    void setResult (bool value) {
+        m_result = value;
+    }
+    bool getResult() const {
+        return m_result;
+    }
+
+    void setSessionStatus(SyncSessionStatus value)
+    {
+        m_sessionStatus = value;
+    }
+    SyncSessionStatus getSessionStatus() const
+    {
+        return m_sessionStatus;
+    }
+
+    void setProfileId(const std::string &value)
+    {
+        m_profileId = value;
+    }
+    std::string getProfileId() const
+    {
+        return m_profileId;
+    }
+
+    void setServiceType(SyncServiceInfo::SyncServiceType value)
+    {
+        m_serviceType = value;
+    }
+    SyncServiceInfo::SyncServiceType getServiceType() const
+    {
+        return m_serviceType;
+    }
+
+    void setIsFromServer(bool value)
+    {
+        m_isFromServer = value;
+    }
+    bool getIsFromServer() const
+    {
+        return m_isFromServer;
+    }
+
+    void setTotalPerService(unsigned long value)
+    {
+        m_totalPerService = value;
+    }
+    unsigned long getTotalPerService() const
+    {
+        return m_totalPerService;
+    }
+
+    void setSynedPerService(unsigned long value)
+    {
+        m_syncedPerService = value;
+    }
+    unsigned long getSyncedPerService() const
+    {
+        return m_syncedPerService;
+    }
+
+private:
+
+    bool m_result;
+    SyncSessionStatus m_sessionStatus;
+    std::string m_profileId;
+    SyncServiceInfo::SyncServiceType m_serviceType;
+    bool m_isFromServer;
+    unsigned long m_totalPerService;
+    unsigned long m_syncedPerService;
+};
+
+typedef std::shared_ptr<OnDataSyncStateChanged> OnDataSyncStateChangedPtr;
+typedef WrtDeviceApis::Commons::ListenerEventEmitter<OnDataSyncStateChanged> OnDataSyncStateChangedEmitter;
+typedef std::shared_ptr<OnDataSyncStateChangedEmitter> OnDataSyncStateChangedEmitterPtr;
+
+}
+}
+
+#endif //_ABSTRACT_LAYER_ON_DATASYNC_STATE_CHANGED_H_
diff --git a/src/DataSync/SyncInfo.cpp b/src/DataSync/SyncInfo.cpp
new file mode 100755 (executable)
index 0000000..d7a9de6
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "SyncInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+SyncInfo::SyncInfo()
+{
+    m_url = "";
+    m_id = "";
+    m_password = "";
+    m_syncMode = UNDEFINED_MODE;
+    m_syncType = UNDEFINED_TYPE;
+    m_syncInterval = INTERVAL_UNDEFINED;
+}
+
+SyncInfo::SyncInfo(std::string url, std::string id, std::string password, SyncMode syncMode, SyncType syncType, SyncInterval syncInterval)
+{
+    m_url = url;
+    m_id = id;
+    m_password = password;
+    m_syncMode = syncMode;
+    m_syncType = syncType;
+    m_syncInterval = syncInterval;
+}
+
+SyncInfo::~SyncInfo()
+{
+}
+
+std::string SyncInfo::getUrl() const
+{
+    return m_url;
+}
+
+void SyncInfo::setUrl(const std::string &url)
+{
+    m_url = url;
+}
+
+std::string SyncInfo::getId() const
+{
+    return m_id;
+}
+
+void SyncInfo::setId(const std::string &id)
+{
+    m_id = id;
+}
+
+std::string SyncInfo::getPassword() const
+{
+    return m_password;
+}
+
+void SyncInfo::setPassword(const std::string &password)
+{
+    m_password = password;
+}
+
+SyncInfo::SyncMode SyncInfo::getSyncMode() const
+{
+    return m_syncMode;
+}
+
+void SyncInfo::setSyncMode(SyncInfo::SyncMode syncMode)
+{
+    m_syncMode = syncMode;
+}
+
+SyncInfo::SyncType SyncInfo::getSyncType() const
+{
+    return m_syncType;
+}
+
+void SyncInfo::setSyncType(SyncInfo::SyncType syncType)
+{
+    m_syncType = syncType;
+}
+
+SyncInfo::SyncInterval SyncInfo::getSyncInterval() const
+{
+    return m_syncInterval;
+}
+
+void SyncInfo::setSyncInterval(SyncInfo::SyncInterval syncInterval)
+{
+    m_syncInterval = syncInterval;
+}
+
+}
+}
diff --git a/src/DataSync/SyncInfo.h b/src/DataSync/SyncInfo.h
new file mode 100755 (executable)
index 0000000..52a04a1
--- /dev/null
@@ -0,0 +1,100 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_SYNC_INFO_H_
+#define _ABSTRACT_LAYER_SYNC_INFO_H_
+
+#include <string>
+#include <memory>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class SyncInfo
+{
+public:
+    typedef enum
+    {
+        MANUAL_MODE,
+        PERIODIC_MODE,
+        PUSH_MODE,
+        UNDEFINED_MODE
+    } SyncMode;
+
+    typedef enum
+    {
+        TWO_WAY_TYPE,
+        SLOW_TYPE,
+        ONE_WAY_FROM_CLIENT_TYPE,
+        REFRESH_FROM_CLIENT_TYPE,
+        ONE_WAY_FROM_SERVER_TYPE,
+        REFRESH_FROM_SERVER_TYPE,
+        UNDEFINED_TYPE
+    } SyncType;
+
+    typedef enum
+    {
+        INTERVAL_5_MINUTES,
+        INTERVAL_15_MINUTES,
+        INTERVAL_1_HOUR,
+        INTERVAL_4_HOURS,
+        INTERVAL_12_HOURS,
+        INTERVAL_1_DAY,
+        INTERVAL_1_WEEK,
+        INTERVAL_1_MONTH,
+        INTERVAL_UNDEFINED
+    } SyncInterval;
+
+    SyncInfo();
+    SyncInfo(std::string url, std::string id, std::string password, SyncMode syncMode, SyncType syncType, SyncInterval syncInterval);
+    virtual ~SyncInfo();
+
+    std::string getUrl() const;
+    void setUrl(const std::string &value);
+
+    std::string getId() const;
+    void setId(const std::string &value);
+
+    std::string getPassword() const;
+    void setPassword(const std::string &value);
+
+    SyncMode getSyncMode() const;
+    void setSyncMode(SyncMode value);
+
+    SyncType getSyncType() const;
+    void setSyncType(SyncType value);
+
+    SyncInterval getSyncInterval() const;
+    void setSyncInterval(SyncInterval value);
+
+protected:
+    std::string m_url;
+    std::string m_id;
+    std::string m_password;
+    SyncMode m_syncMode;
+    SyncType m_syncType;
+    SyncInterval m_syncInterval;
+};
+
+typedef std::shared_ptr<SyncInfo> SyncInfoPtr;
+
+}
+}
+
+#endif /* _ABSTRACT_LAYER_SYNC_INFO_H_ */
+
diff --git a/src/DataSync/SyncProfileInfo.cpp b/src/DataSync/SyncProfileInfo.cpp
new file mode 100755 (executable)
index 0000000..0ff2182
--- /dev/null
@@ -0,0 +1,110 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "SyncProfileInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+SyncProfileInfo::SyncProfileInfo()
+{
+    m_profileId = "";
+    m_profileName = "";
+    m_syncInfo = SyncInfoPtr(new SyncInfo());
+    m_serviceInfo = SyncServiceInfoListPtr(new SyncServiceInfoList());
+    m_serviceInfoJSRef = NULL;
+}
+
+SyncProfileInfo::SyncProfileInfo(std::string profileId, std::string profileName, SyncInfoPtr syncInfo, SyncServiceInfoListPtr serviceInfo)
+{
+    m_profileId = profileId;
+    m_profileName = profileName;
+    m_syncInfo = syncInfo;
+    m_serviceInfo = serviceInfo;
+    m_serviceInfoJSRef = NULL;
+}
+
+SyncProfileInfo::~SyncProfileInfo()
+{
+    if(m_serviceInfoJSRef) {
+        JSValueUnprotect(m_context, m_serviceInfoJSRef);
+    }
+}
+
+std::string SyncProfileInfo::getProfileId() const
+{
+    return m_profileId;
+}
+
+void SyncProfileInfo::setProfileId(const std::string &profileId)
+{
+    m_profileId = profileId;
+}
+
+std::string SyncProfileInfo::getProfileName() const
+{
+    return m_profileName;
+}
+
+void SyncProfileInfo::setProfileName(const std::string &profileName)
+{
+    m_profileName = profileName;
+}
+
+SyncInfoPtr SyncProfileInfo::getSyncInfo() const
+{
+    return m_syncInfo;
+}
+
+void SyncProfileInfo::setSyncInfo(SyncInfoPtr syncInfo)
+{
+    m_syncInfo = syncInfo;
+}
+
+SyncServiceInfoListPtr SyncProfileInfo::getServiceInfo() const
+{
+    return m_serviceInfo;
+}
+
+void SyncProfileInfo::setServiceInfo(SyncServiceInfoListPtr serviceInfo)
+{
+    m_serviceInfo = serviceInfo;
+}
+
+JSObjectRef SyncProfileInfo::getServiceInfoJSRef() const
+{
+    return m_serviceInfoJSRef;
+}
+
+void SyncProfileInfo::setServiceInfoJSRef(const JSObjectRef value)
+{
+    m_serviceInfoJSRef = value;
+}
+
+JSContextRef SyncProfileInfo::getContext() const
+{
+    return m_context;
+}
+
+void SyncProfileInfo::setContext(const JSContextRef contextRef)
+{
+    m_context = contextRef;
+}
+
+}
+}
diff --git a/src/DataSync/SyncProfileInfo.h b/src/DataSync/SyncProfileInfo.h
new file mode 100755 (executable)
index 0000000..da1b0ef
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_SYNC_PROFILE_INFO_H_
+#define _ABSTRACT_LAYER_SYNC_PROFILE_INFO_H_
+
+#include <string>
+#include <vector>
+
+
+#include "SyncInfo.h"
+#include "SyncServiceInfo.h"
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class SyncProfileInfo
+{
+public:
+
+    SyncProfileInfo();
+    SyncProfileInfo(std::string profileId, std::string profileName, SyncInfoPtr syncInfo, SyncServiceInfoListPtr serviceInfo);
+    virtual ~SyncProfileInfo();
+
+    std::string getProfileId() const;
+    void setProfileId(const std::string &value);
+
+    std::string getProfileName() const;
+    void setProfileName(const std::string &value);
+
+    SyncInfoPtr getSyncInfo() const;
+    void setSyncInfo(SyncInfoPtr value);
+
+    SyncServiceInfoListPtr getServiceInfo() const;
+    void setServiceInfo(SyncServiceInfoListPtr value);
+    JSObjectRef getServiceInfoJSRef() const;
+    void setServiceInfoJSRef(const JSObjectRef value);
+
+    JSContextRef getContext() const;
+    void setContext(const JSContextRef contextRef);
+
+protected:
+    std::string m_profileId;
+    std::string m_profileName;
+    SyncInfoPtr m_syncInfo;
+    SyncServiceInfoListPtr m_serviceInfo;
+    JSObjectRef m_serviceInfoJSRef;
+    JSContextRef m_context;
+};
+
+typedef std::shared_ptr<SyncProfileInfo> SyncProfileInfoPtr;
+typedef std::vector<SyncProfileInfoPtr> SyncProfileInfoList;
+typedef std::shared_ptr<SyncProfileInfoList> SyncProfileInfoListPtr;
+
+}
+}
+
+#endif /* _ABSTRACT_LAYER_SYNC_PROFILE_INFO_H_ */
+
diff --git a/src/DataSync/SyncServiceInfo.cpp b/src/DataSync/SyncServiceInfo.cpp
new file mode 100755 (executable)
index 0000000..2f15175
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "SyncServiceInfo.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+SyncServiceInfo::SyncServiceInfo()
+{
+    m_enable = true;
+    m_syncServiceType = UNDEFINED_SERVICE_TYPE;
+    m_serverDatabaseUri = "";
+    m_id = "";
+    m_password = "";
+}
+
+SyncServiceInfo::SyncServiceInfo(bool enable, SyncServiceType syncServiceType, std::string serverDatabaseUri, std::string id, std::string password)
+{
+    m_enable = enable;
+    m_syncServiceType = syncServiceType;
+    m_serverDatabaseUri = serverDatabaseUri;
+    m_id = id;
+    m_password = password;
+}
+
+SyncServiceInfo::~SyncServiceInfo()
+{
+}
+
+bool SyncServiceInfo::getEnable() const
+{
+    return m_enable;
+}
+
+void SyncServiceInfo::setEnable(bool enable)
+{
+    m_enable = enable;
+}
+
+SyncServiceInfo::SyncServiceType SyncServiceInfo::getSyncServiceType() const
+{
+    return m_syncServiceType;
+}
+
+void SyncServiceInfo::setSyncServiceType(SyncServiceInfo::SyncServiceType syncServiceType)
+{
+    m_syncServiceType = syncServiceType;
+}
+
+std::string SyncServiceInfo::getServerDatabaseUri() const
+{
+    return m_serverDatabaseUri;
+}
+
+void SyncServiceInfo::setServerDatabaseUri(const std::string &uri)
+{
+    m_serverDatabaseUri = uri;
+}
+
+std::string SyncServiceInfo::getId() const
+{
+    return m_id;
+}
+
+void SyncServiceInfo::setId(const std::string &id)
+{
+    m_id = id;
+}
+
+std::string SyncServiceInfo::getPassword() const
+{
+    return m_password;
+}
+
+void SyncServiceInfo::setPassword(const std::string &password)
+{
+    m_password = password;
+}
+
+}
+}
diff --git a/src/DataSync/SyncServiceInfo.h b/src/DataSync/SyncServiceInfo.h
new file mode 100755 (executable)
index 0000000..14a4dfe
--- /dev/null
@@ -0,0 +1,74 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_SYNC_SERVICE_INFO_H_
+#define _ABSTRACT_LAYER_SYNC_SERVICE_INFO_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class SyncServiceInfo
+{
+public:
+    typedef enum
+    {
+        CONTACT_SERVICE_TYPE,
+        EVENT_SERVICE_TYPE,
+        UNDEFINED_SERVICE_TYPE
+    } SyncServiceType;
+
+    SyncServiceInfo();
+    SyncServiceInfo(bool enable, SyncServiceType syncServiceType, std::string serverDatabaseUri, std::string id, std::string password);
+    virtual ~SyncServiceInfo();
+
+    bool getEnable() const;
+    void setEnable(bool value);
+
+    SyncServiceType getSyncServiceType() const;
+    void setSyncServiceType(SyncServiceType value);
+
+    std::string getServerDatabaseUri() const;
+    void setServerDatabaseUri(const std::string &value);
+
+    std::string getId() const;
+    void setId(const std::string &value);
+
+    std::string getPassword() const;
+    void setPassword(const std::string &value);
+
+protected:
+    bool m_enable;
+    SyncServiceType m_syncServiceType;
+    std::string m_serverDatabaseUri;
+    std::string m_id;
+    std::string m_password;
+};
+
+typedef std::shared_ptr<SyncServiceInfo> SyncServiceInfoPtr;
+typedef std::vector<SyncServiceInfoPtr> SyncServiceInfoList;
+typedef std::shared_ptr<SyncServiceInfoList> SyncServiceInfoListPtr;
+
+}
+}
+
+#endif /* _ABSTRACT_LAYER_SYNC_SERVICE_INFO_H_ */
+
diff --git a/src/DataSync/SyncStatistics.cpp b/src/DataSync/SyncStatistics.cpp
new file mode 100755 (executable)
index 0000000..7ccbda7
--- /dev/null
@@ -0,0 +1,179 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "SyncStatistics.h"
+
+namespace DeviceAPI {
+namespace DataSync {
+
+SyncStatistics::SyncStatistics()
+{
+    m_syncStatus = NONE_STATUS;
+    m_serviceType = SyncServiceInfo::UNDEFINED_SERVICE_TYPE;
+    m_lastSyncTime = UNDEFILED_TIME;
+    m_serverToClientTotal = 0;
+    m_serverToClientAdded = 0;
+    m_serverToClientUpdated = 0;
+    m_serverToClientRemoved = 0;
+    m_clientToServerTotal = 0;
+    m_clientToServerAdded = 0;
+    m_clientToServerUpdated = 0;
+    m_clientToServerRemoved = 0;
+}
+
+SyncStatistics::SyncStatistics(SyncStatus syncStatus,
+        SyncServiceInfo::SyncServiceType serviceType,
+        long long int lastSyncTime,
+        unsigned long serverToClientTotal,
+        unsigned long serverToClientAdded,
+        unsigned long serverToClientUpdated,
+        unsigned long serverToClientRemoved,
+        unsigned long clientToServerTotal,
+        unsigned long clientToServerAdded,
+        unsigned long clientToServerUpdated,
+        unsigned long clientToServerRemoved)
+{
+    m_syncStatus = syncStatus;
+    m_serviceType = serviceType;
+    m_lastSyncTime = lastSyncTime;
+    m_serverToClientTotal = serverToClientTotal;
+    m_serverToClientAdded = serverToClientAdded;
+    m_serverToClientUpdated = serverToClientUpdated;
+    m_serverToClientRemoved = serverToClientRemoved;
+    m_clientToServerTotal = clientToServerTotal;
+    m_clientToServerAdded = clientToServerAdded;
+    m_clientToServerUpdated = clientToServerUpdated;
+    m_clientToServerRemoved = clientToServerRemoved;
+}
+
+SyncStatistics::~SyncStatistics()
+{
+}
+
+SyncStatistics::SyncStatus SyncStatistics::getSyncStatus() const
+{
+    return m_syncStatus;
+}
+
+void SyncStatistics::setSyncStatus(SyncStatistics::SyncStatus syncStatus)
+{
+    m_syncStatus = syncStatus;
+}
+
+SyncServiceInfo::SyncServiceType SyncStatistics::getServiceType() const
+{
+    return m_serviceType;
+}
+
+void SyncStatistics::setServiceType(SyncServiceInfo::SyncServiceType serviceType)
+{
+    m_serviceType = serviceType;
+}
+
+long long int SyncStatistics::getLastSyncTime() const
+{
+    return m_lastSyncTime;
+}
+
+void SyncStatistics::setLastSyncTime(long long int lastSyncTime)
+{
+    m_lastSyncTime = lastSyncTime;
+}
+
+unsigned long SyncStatistics::getServerToClientTotal() const
+{
+    return m_serverToClientTotal;
+}
+
+void SyncStatistics::setServerToClientTotal(unsigned long serverToClientTotal)
+{
+    m_serverToClientTotal = serverToClientTotal;
+}
+
+unsigned long SyncStatistics::getServerToClientAdded() const
+{
+    return m_serverToClientAdded;
+}
+
+void SyncStatistics::setServerToClientAdded(unsigned long serverToClientAdded)
+{
+    m_serverToClientAdded = serverToClientAdded;
+}
+
+unsigned long SyncStatistics::getServerToClientUpdated() const
+{
+    return m_serverToClientUpdated;
+}
+
+void SyncStatistics::setServerToClientUpdated(unsigned long serverToClientUpdated)
+{
+    m_serverToClientUpdated = serverToClientUpdated;
+}
+
+unsigned long SyncStatistics::getServerToClientRemoved() const
+{
+    return m_serverToClientRemoved;
+}
+
+void SyncStatistics::setServerToClientRemoved(unsigned long serverToClientRemoved)
+{
+    m_serverToClientRemoved = serverToClientRemoved;
+}
+
+unsigned long SyncStatistics::getClientToServerTotal() const
+{
+    return m_clientToServerTotal;
+}
+
+void SyncStatistics::setClientToServerTotal(unsigned long clientToServerTotal)
+{
+    m_clientToServerTotal = clientToServerTotal;
+}
+
+unsigned long SyncStatistics::getClientToServerAdded() const
+{
+    return m_clientToServerAdded;
+}
+
+void SyncStatistics::setClientToServerAdded(unsigned long clientToServerAdded)
+{
+    m_clientToServerAdded = clientToServerAdded;
+}
+
+unsigned long SyncStatistics::getClientToServerUpdated() const
+{
+    return m_clientToServerUpdated;
+}
+
+void SyncStatistics::setClientToServerUpdated(unsigned long clientToServerUpdated)
+{
+    m_clientToServerUpdated = clientToServerUpdated;
+}
+
+unsigned long SyncStatistics::getClientToServerRemoved() const
+{
+    return m_clientToServerRemoved;
+}
+
+void SyncStatistics::setClientToServerRemoved(unsigned long clientToServerRemoved)
+{
+    m_clientToServerRemoved = clientToServerRemoved;
+}
+
+}
+}
diff --git a/src/DataSync/SyncStatistics.h b/src/DataSync/SyncStatistics.h
new file mode 100755 (executable)
index 0000000..f4a0261
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _ABSTRACT_LAYER_SYNC_STATISTICS_H_
+#define _ABSTRACT_LAYER_SYNC_STATISTICS_H_
+
+#include <string>
+
+
+#include "SyncServiceInfo.h"
+
+#define UNDEFILED_TIME -1
+
+namespace DeviceAPI {
+namespace DataSync {
+
+class SyncStatistics
+{
+public:
+    typedef enum
+    {
+        SUCCESS_STATUS,
+        FAIL_STATUS,
+        STOP_STATUS,
+        NONE_STATUS
+    } SyncStatus;
+
+    SyncStatistics();
+    SyncStatistics(SyncStatus syncStatus,
+            SyncServiceInfo::SyncServiceType serviceType,
+            long long int lastSyncTime,
+            unsigned long serverToClientTotal,
+            unsigned long serverToClientAdded,
+            unsigned long serverToClientUpdated,
+            unsigned long serverToClientRemoved,
+            unsigned long clientToServerTotal,
+            unsigned long clientToServerAdded,
+            unsigned long clientToServerUpdated,
+            unsigned long clientToServerRemoved);
+    virtual ~SyncStatistics();
+
+    SyncStatus getSyncStatus() const;
+    void setSyncStatus(SyncStatus value);
+
+    SyncServiceInfo::SyncServiceType getServiceType() const;
+    void setServiceType(SyncServiceInfo::SyncServiceType value);
+
+    long long int getLastSyncTime() const;
+    void setLastSyncTime(long long int value);
+
+    unsigned long getServerToClientTotal() const;
+    void setServerToClientTotal(unsigned long value);
+
+    unsigned long getServerToClientAdded() const;
+    void setServerToClientAdded(unsigned long value);
+
+    unsigned long getServerToClientUpdated() const;
+    void setServerToClientUpdated(unsigned long value);
+
+    unsigned long getServerToClientRemoved() const;
+    void setServerToClientRemoved(unsigned long value);
+
+    unsigned long getClientToServerTotal() const;
+    void setClientToServerTotal(unsigned long value);
+
+    unsigned long getClientToServerAdded() const;
+    void setClientToServerAdded(unsigned long value);
+
+    unsigned long getClientToServerUpdated() const;
+    void setClientToServerUpdated(unsigned long value);
+
+    unsigned long getClientToServerRemoved() const;
+    void setClientToServerRemoved(unsigned long value);
+
+protected:
+    SyncStatus m_syncStatus;
+    SyncServiceInfo::SyncServiceType m_serviceType;
+    long long int m_lastSyncTime;
+    unsigned long m_serverToClientTotal;
+    unsigned long m_serverToClientAdded;
+    unsigned long m_serverToClientUpdated;
+    unsigned long m_serverToClientRemoved;
+    unsigned long m_clientToServerTotal;
+    unsigned long m_clientToServerAdded;
+    unsigned long m_clientToServerUpdated;
+    unsigned long m_clientToServerRemoved;
+};
+
+typedef std::shared_ptr<SyncStatistics> SyncStatisticsPtr;
+typedef std::vector<SyncStatisticsPtr> SyncStatisticsList;
+typedef std::shared_ptr<SyncStatisticsList> SyncStatisticsListPtr;
+
+}
+}
+
+#endif /* _ABSTRACT_LAYER_SYNC_STATISTICS_H_ */
+
diff --git a/src/DataSync/config.xml b/src/DataSync/config.xml
new file mode 100755 (executable)
index 0000000..8486e4f
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-datasync.so</library-name>
+    <feature-install-uri>datasync.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/datasync</name>
+        <device-capability>datasync</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/DataSync/plugin_config.cpp b/src/DataSync/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..e17acb3
--- /dev/null
@@ -0,0 +1,184 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <dpl/exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define DATASYNC_FEATURE_API "http://tizen.org/privilege/datasync"
+
+#define DATASYNC_DEVICE_CAP "datasync"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+static FunctionMapping createDataSyncFunctions();
+
+static FunctionMapping DataSyncFunctions = createDataSyncFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(DataSync, DataSyncFunctions);
+
+#pragma GCC visibility pop
+
+static FunctionMapping createDataSyncFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_DATASYNC, DATASYNC_DEVICE_CAP);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_DATASYNC);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_DATASYNC, DEVICE_CAP_DATASYNC);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_DATASYNC, DATASYNC_FEATURE_API);
+
+    ACE_CREATE_FEATURE_LIST(DATASYNC_FEATURES);
+    ACE_ADD_API_FEATURE(DATASYNC_FEATURES, FEATURE_DATASYNC);
+
+    /**
+     * Functions
+     */
+    FunctionMapping dataSyncMapping;
+
+    // add
+    AceFunction addFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_ADD,
+            DATASYNC_FUNCTION_API_ADD,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_ADD,
+                               addFunc));
+
+    // update
+    AceFunction updateFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UPDATE,
+            DATASYNC_FUNCTION_API_UPDATE,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_UPDATE,
+                               updateFunc));
+
+    // remove
+    AceFunction removeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REMOVE,
+            DATASYNC_FUNCTION_API_REMOVE,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_REMOVE,
+                               removeFunc));
+
+    // getMaxProfilesNum
+    AceFunction getMaxProfilesNumFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MAX_PROFILES_NUM,
+            DATASYNC_FUNCTION_API_GET_MAX_PROFILES_NUM,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_GET_MAX_PROFILES_NUM,
+                               getMaxProfilesNumFunc));
+
+    // getProfilesNum
+    AceFunction getProfilesNumFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_PROFILES_NUM,
+            DATASYNC_FUNCTION_API_GET_PROFILES_NUM,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_GET_PROFILES_NUM,
+                               getMaxProfilesNumFunc));
+
+    // get
+    AceFunction getFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET,
+            DATASYNC_FUNCTION_API_GET,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_GET,
+                               getFunc));
+
+    // getAll
+    AceFunction getAllFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_ALL,
+            DATASYNC_FUNCTION_API_GET_ALL,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_GET_ALL,
+                               getAllFunc));
+
+    // startSync
+    AceFunction startSyncFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_START_SYNC,
+            DATASYNC_FUNCTION_API_START_SYNC,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_START_SYNC,
+                               startSyncFunc));
+
+    // stopSync
+    AceFunction stopSyncFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_STOP_SYNC,
+            DATASYNC_FUNCTION_API_STOP_SYNC,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_STOP_SYNC,
+                               stopSyncFunc));
+
+
+    // getLastSyncStatistics
+    AceFunction getLastSyncStatisticsFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_LAST_SYNC_STATISTICS,
+            DATASYNC_FUNCTION_API_GET_LAST_SYNC_STATISTICS,
+            DATASYNC_FEATURES,
+            DEVICE_LIST_DATASYNC);
+
+    dataSyncMapping.insert(std::make_pair(
+                               DATASYNC_FUNCTION_API_GET_LAST_SYNC_STATISTICS,
+                               getLastSyncStatisticsFunc));
+
+    return dataSyncMapping;
+}
+
+}
+}
diff --git a/src/DataSync/plugin_config.h b/src/DataSync/plugin_config.h
new file mode 100755 (executable)
index 0000000..5089695
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _DATASYNC_PLUGIN_CONFIG_H_
+#define _DATASYNC_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+namespace DeviceAPI {
+namespace DataSync {
+
+// Functions from datasync manager
+#define DATASYNC_FUNCTION_API_ADD "add"
+#define DATASYNC_FUNCTION_API_UPDATE "update"
+#define DATASYNC_FUNCTION_API_REMOVE "remove"
+#define DATASYNC_FUNCTION_API_GET_MAX_PROFILES_NUM "getMaxProfilesNum"
+#define DATASYNC_FUNCTION_API_GET_PROFILES_NUM "getProfilesNum"
+#define DATASYNC_FUNCTION_API_GET "get"
+#define DATASYNC_FUNCTION_API_GET_ALL "getAll"
+#define DATASYNC_FUNCTION_API_START_SYNC "startSync"
+#define DATASYNC_FUNCTION_API_STOP_SYNC "stopSync"
+#define DATASYNC_FUNCTION_API_GET_LAST_SYNC_STATISTICS "getLastSyncStatistics"
+
+DECLARE_FUNCTION_GETTER(DataSync);
+
+#define DATASYNC_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getDataSyncFunctionData, \
+    functionName)
+}
+}
+
+#endif // _DATASYNC_PLUGIN_CONFIG_H_
\ No newline at end of file
diff --git a/src/DataSync/plugin_initializer.cpp b/src/DataSync/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..c5e7dfc
--- /dev/null
@@ -0,0 +1,122 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+
+#include "JSDataSyncManager.h"
+#include "JSSyncInfo.h"
+#include "JSSyncServiceInfo.h"
+#include "JSSyncProfileInfo.h"
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+namespace Options{
+class_definition_options_t DataSyncOptions =
+{
+    JS_CLASS,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL,
+    NULL
+};
+
+class_definition_options_t DataSyncInterfaceOptions = {
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL, // JSWidget::acquireGlobalContext,
+    NULL,
+    NULL
+};
+}
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace DataSync {
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\DataSync] on_widget_start_callback (%d)", widgetId);
+
+    Try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } Catch (Exception) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\DataSync] on_widget_stop_callback (%d)", widgetId);
+
+    Try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } Catch (Exception) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\DataSync] on_frame_load_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\DataSync] on_frame_unload_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "datasync",
+        (js_class_template_getter)JSDataSyncManager::getClassRef,
+        &Options::DataSyncOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_SYNC_INFO_INTERFACE,
+        (js_class_template_getter)JSSyncInfo::getClassRef,
+        (js_class_constructor_cb_t)JSSyncInfo::constructor,
+        &Options::DataSyncInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_SYNC_SERVICE_INFO_INTERFACE,
+        (js_class_template_getter)JSSyncServiceInfo::getClassRef,
+        (js_class_constructor_cb_t)JSSyncServiceInfo::constructor,
+        &Options::DataSyncInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_SYNC_PROFILE_INFO_INTERFACE,
+        (js_class_template_getter)JSSyncProfileInfo::getClassRef,
+        (js_class_constructor_cb_t)JSSyncProfileInfo::constructor,
+        &Options::DataSyncInterfaceOptions)
+PLUGIN_CLASS_MAP_END
+
+}
+}
+
diff --git a/src/Download/CMakeLists.txt b/src/Download/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..205f896
--- /dev/null
@@ -0,0 +1,57 @@
+SET(TARGET_NAME ${download_target})
+SET(DESTINATION_NAME ${download_dest})
+SET(TARGET_IMPL_NAME ${download_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_download REQUIRED
+    capi-web-url-download capi-system-info capi-network-connection )
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${TOP}/Tizen
+    ${TOP}/Filesystem
+    ${platform_pkgs_download_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${filesystem_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    DownloadRequest.cpp
+    DownloadManager.cpp
+    DownloadCallback.cpp
+    JSDownloadManager.cpp
+    JSDownloadRequest.cpp
+    DownloadUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${filesystem_impl}
+    ${filesystem_config}
+    ${platform_pkgs_download_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/download
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Download/DownloadCallback.cpp b/src/Download/DownloadCallback.cpp
new file mode 100755 (executable)
index 0000000..fa8b416
--- /dev/null
@@ -0,0 +1,165 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include "Logger.h"
+
+#include "DownloadCallback.h"
+#include "GlobalContextManager.h"
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Download {
+
+DownloadCallback::DownloadCallback(JSContextRef globalCtx, JSObjectRef object)
+{
+    mCallbackUserData = new MultiCallbackUserData(globalCtx);
+
+    // onprogress
+    JSStringRef onprogress = JSStringCreateWithUTF8CString("onprogress");
+    bool has_onprogress = JSObjectHasProperty(globalCtx, object, onprogress);
+    JSStringRelease(onprogress);
+    if (has_onprogress) {
+        JSObjectRef cbObj = JSUtil::JSValueToObject(globalCtx, JSUtil::getProperty(globalCtx, object, "onprogress"));
+        if (JSObjectIsFunction(globalCtx, cbObj)) {
+            mCallbackUserData->setCallback("onprogress", cbObj);
+        } else {
+            throw TypeMismatchException("onprogress is not a callback function.");
+        }
+    }
+
+    // onpaused
+    JSStringRef onpaused = JSStringCreateWithUTF8CString("onpaused");
+    bool has_onpaused = JSObjectHasProperty(globalCtx, object, onpaused);
+    JSStringRelease(onpaused);
+    if (has_onpaused) {
+        JSObjectRef cbObj = JSUtil::JSValueToObject(globalCtx, JSUtil::getProperty(globalCtx, object, "onpaused"));
+        if (JSObjectIsFunction(globalCtx, cbObj)) {
+            mCallbackUserData->setCallback("onpaused", cbObj);
+        } else {
+            throw TypeMismatchException("onpaused is not a callback function.");
+        }
+    }
+
+    // oncanceled
+    JSStringRef oncanceled = JSStringCreateWithUTF8CString("oncanceled");
+    bool has_oncanceled = JSObjectHasProperty(globalCtx, object, oncanceled);
+    JSStringRelease(oncanceled);
+    if (has_oncanceled) {
+        JSObjectRef cbObj = JSUtil::JSValueToObject(globalCtx, JSUtil::getProperty(globalCtx, object, "oncanceled"));
+        if (JSObjectIsFunction(globalCtx, cbObj)) {
+            mCallbackUserData->setCallback("oncanceled", cbObj);
+        } else {
+            throw TypeMismatchException("oncanceled is not a callback function.");
+        }
+    }
+
+    // oncompleted
+    JSStringRef oncompleted = JSStringCreateWithUTF8CString("oncompleted");
+    bool has_oncompleted = JSObjectHasProperty(globalCtx, object, oncompleted);
+    JSStringRelease(oncompleted);
+    if (has_oncompleted) {
+        JSObjectRef cbObj = JSUtil::JSValueToObject(globalCtx, JSUtil::getProperty(globalCtx, object, "oncompleted"));
+        if (JSObjectIsFunction(globalCtx, cbObj)) {
+            mCallbackUserData->setCallback("oncompleted", cbObj);
+        } else {
+            throw TypeMismatchException("oncompleted is not a callback function.");
+        }
+    }
+
+    // onfailed
+    JSStringRef onfailed = JSStringCreateWithUTF8CString("onfailed");
+    bool has_onfailed = JSObjectHasProperty(globalCtx, object, onfailed);
+    JSStringRelease(onfailed);
+    if (has_onfailed) {
+        JSObjectRef cbObj = JSUtil::JSValueToObject(globalCtx, JSUtil::getProperty(globalCtx, object, "onfailed"));
+        if (JSObjectIsFunction(globalCtx, cbObj)) {
+            mCallbackUserData->setCallback("onfailed", cbObj);
+        } else {
+            throw TypeMismatchException("onfailed is not a callback function.");
+        }
+    }
+
+}
+
+DownloadCallback::~DownloadCallback() {
+    if (mCallbackUserData)
+        delete mCallbackUserData;
+}
+
+void DownloadCallback::onprogress(long downloadId, unsigned long long int receivedSize, unsigned long long int totalSize)
+{
+    JSContextRef context = mCallbackUserData->getContext();
+
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef objParam[3] = {
+            JSUtil::toJSValueRef(context, downloadId),
+            JSUtil::toJSValueRef(context, (long)receivedSize),
+            JSUtil::toJSValueRef(context, (long)totalSize)
+        };
+    mCallbackUserData->invokeCallback("onprogress", 3, objParam);
+}
+
+void DownloadCallback::onpaused(long downloadId)
+{
+    JSContextRef context = mCallbackUserData->getContext();
+
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    mCallbackUserData->invokeCallback("onpaused", JSUtil::toJSValueRef(context, downloadId));
+}
+
+void DownloadCallback::oncanceled(long downloadId)
+{
+    JSContextRef context = mCallbackUserData->getContext();
+
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    mCallbackUserData->invokeCallback("oncanceled", JSUtil::toJSValueRef(context, downloadId));
+}
+
+void DownloadCallback::oncompleted(long downloadId, std::string fullPath)
+{
+    JSContextRef context = mCallbackUserData->getContext();
+
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef objParam[2] = {
+            JSUtil::toJSValueRef(context, downloadId),
+            JSUtil::toJSValueRef(context, fullPath)
+        };
+    mCallbackUserData->invokeCallback("oncompleted", 2, objParam);
+}
+
+void DownloadCallback::onfailed(long downloadId, BasePlatformException &error)
+{
+    JSContextRef context = mCallbackUserData->getContext();
+
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    JSValueRef objParam[2] = {
+            JSUtil::toJSValueRef(context, downloadId),
+            JSWebAPIErrorFactory::makeErrorObject(context, error)
+        };
+    mCallbackUserData->invokeCallback("onfailed", 2, objParam);
+}
+
+} // Download
+} // DeviceAPI
diff --git a/src/Download/DownloadCallback.h b/src/Download/DownloadCallback.h
new file mode 100755 (executable)
index 0000000..7eaf933
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DOWNLOAD_CALLBACK_H__
+#define __TIZEN_DOWNLOAD_CALLBACK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Download {
+
+class DownloadCallback {
+public:
+    DownloadCallback(JSContextRef globalCtx, JSObjectRef object);
+    virtual ~DownloadCallback();
+
+    void onprogress(long downloadId, unsigned long long int receivedSize, unsigned long long int totalSize);
+    void onpaused(long downloadId);
+    void oncanceled(long downloadId);
+    void oncompleted(long downloadId, std::string fullPath);
+    void onfailed(long downloadId, BasePlatformException &error);
+
+private:
+    MultiCallbackUserData *mCallbackUserData;
+};
+
+} // Download
+} // DeviceAPI
+
+
+#endif // __TIZEN_DOWNLOAD_CALLBACK_H__
\ No newline at end of file
diff --git a/src/Download/DownloadManager.cpp b/src/Download/DownloadManager.cpp
new file mode 100755 (executable)
index 0000000..2cc7a6f
--- /dev/null
@@ -0,0 +1,904 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <glib.h>
+
+#include <download.h>
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <FilesystemExternalUtils.h>
+#include <system_info.h>
+#include <net_connection.h>
+
+#include "DownloadState.h"
+#include "DownloadNetworkType.h"
+#include "DownloadManager.h"
+#include "DownloadUtil.h"
+
+#ifdef ENABLE_TIME_TRACER
+#define _P(T, x) \
+    (TIME_TRACER_ITEM_BEGIN("DOWNLOAD_" #T "_PLATFORM", 0), x); \
+    TIME_TRACER_ITEM_END("DOWNLOAD_" #T "_PLATFORM", 0);
+#else
+#define _P(T, x) x
+#endif
+
+namespace DeviceAPI {
+namespace Download {
+
+typedef struct {
+    int downloadId;
+    download_state_e state;
+    unsigned long long received;
+    void *user_data;
+} DOWNLOAD_EVENT_DATA_T;
+
+static gboolean downloadEventCB(void *data) {
+    int ret;
+    DOWNLOAD_EVENT_DATA_T *fnData = static_cast<DOWNLOAD_EVENT_DATA_T*>(data);
+
+    try {
+        long downloadId = (long)fnData->downloadId;
+        LOGD("enter : %d", downloadId);
+
+        DownloadManager *thisObj = (DownloadManager*)fnData->user_data;
+        if (!thisObj) {
+            LOGE("UserData is NULL");
+            throw UnknownException("UserData is NULL.");
+        }
+
+        DownloadCallback *callback = thisObj->getCallbackFromMap(downloadId);
+        if (!callback) {
+            LOGE("Callback could not found.");
+            throw UnknownException("Callback could not found.");
+        }
+
+        switch(fnData->state) {
+            case DOWNLOAD_STATE_QUEUED:
+            {
+                LOGD("onprogress %d",downloadId);
+                callback->onprogress(downloadId, 0, 0);
+                break;
+            }
+            case DOWNLOAD_STATE_PAUSED:
+            {
+                LOGD("onpaused : %d",downloadId);
+                callback->onpaused(downloadId);
+                break;
+            }
+            case DOWNLOAD_STATE_DOWNLOADING:
+            {
+                LOGD("downloading");
+                if (fnData->received > 0) {
+                    unsigned long long totalSize = 0;
+                    ret = download_get_content_size(downloadId, &totalSize);
+                    if (ret != DOWNLOAD_ERROR_NONE) {
+                        LOGE("ret : %d", ret);
+                        DownloadUtil::throwDownloadException(ret, "download_get_content_size()");
+                    }
+
+                    LOGD("onprogress %d, %d, %d",downloadId, fnData->received, totalSize);
+                    callback->onprogress(downloadId, fnData->received, totalSize);
+                }
+                break;
+            }
+            case DOWNLOAD_STATE_COMPLETED:
+            {
+                LOGD("completed : %d",downloadId);
+                ret = download_unset_state_changed_cb(downloadId);
+                if (ret != DOWNLOAD_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    DownloadUtil::throwDownloadException(ret, "download_unset_state_changed_cb()");
+                }
+
+                ret = download_unset_progress_cb(downloadId);
+                if (ret != DOWNLOAD_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    DownloadUtil::throwDownloadException(ret, "download_unset_progress_cb()");
+                }
+
+                char *fullPath = NULL;
+                ret = download_get_downloaded_file_path(downloadId, &fullPath);
+                if (ret != DOWNLOAD_ERROR_NONE || !fullPath) {
+                    LOGE("ret : %d", ret);
+                    DownloadUtil::throwDownloadException(ret, "download_get_downloaded_file_path()");
+                }
+
+                ret = download_destroy(downloadId);
+                if (ret != DOWNLOAD_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    DownloadUtil::throwDownloadException(ret, "download_destroy()");
+                }
+
+                std::string virtualPath;
+                try {
+                    virtualPath = Filesystem::External::toVirtualPath(fullPath, NULL);
+                } catch (...) {
+                    LOGW("Platform error while converting fullPath.");
+                    virtualPath = fullPath;
+                }
+
+                LOGD("oncompleted : %d, %s", downloadId, virtualPath.c_str());
+                callback->oncompleted(downloadId, virtualPath);
+                free(fullPath);
+
+                thisObj->removeCallbackFromMap(downloadId);
+                break;
+            }
+            case DOWNLOAD_STATE_FAILED:
+            {
+                LOGD("failed : %d", downloadId);
+                ret = download_unset_state_changed_cb(downloadId);
+                if (ret != DOWNLOAD_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    DownloadUtil::throwDownloadException(ret, "download_unset_state_changed_cb()");
+                }
+
+                ret = download_unset_progress_cb(downloadId);
+                if (ret != DOWNLOAD_ERROR_NONE) {
+                    LOGE("ret : %d", ret);
+                    DownloadUtil::throwDownloadException(ret, "download_unset_progress_cb()");
+                }
+
+                int err = DOWNLOAD_ERROR_NONE;
+                std::string errMessage;
+                ret = download_get_error(downloadId, (download_error_e*)&err);
+                if (ret != DOWNLOAD_ERROR_NONE) {
+                    LOGE("Platform error while getting download error.");
+                } else {
+                    errMessage = DownloadUtil::getDownloadErrorMessage(err);
+                    LOGE("error : %d, %s", err, errMessage.c_str());
+                }
+
+                ret = download_destroy(downloadId);
+                if (ret != DOWNLOAD_ERROR_NONE) {
+                    LOGE("Platform error while destroying download handle. downloadId=%d", downloadId);
+                }
+
+                UnknownException error(errMessage.c_str());
+                callback->onfailed(downloadId, error);
+                thisObj->removeCallbackFromMap(downloadId);
+                break;
+            }
+            case DOWNLOAD_STATE_CANCELED:
+            {
+                LOGD("oncanceled : %d", downloadId);
+                callback->oncanceled(downloadId);
+                break;
+            }
+            default:
+                LOGW("State changed is ignored.");
+                break;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("download_state_changed_cb: %s", err.getMessage().c_str());
+    }
+
+    delete fnData;
+    return false;
+}
+
+static void download_state_changed_cb(int downloadId, download_state_e state, void *user_data)
+{
+    LOGD("enter %d , %d", downloadId, state);
+
+    DOWNLOAD_EVENT_DATA_T *data = new DOWNLOAD_EVENT_DATA_T;
+    data->downloadId = downloadId;
+    data->state = state;
+    data->received = 0;
+    data->user_data = user_data;
+
+    // download core f/w calls this callback function in another thread.
+    // so we should use g_idle_add() to switch context to main thread.
+    g_idle_add(downloadEventCB, static_cast<void*>(data));
+}
+
+static void download_progress_cb(int downloadId, unsigned long long received, void *user_data)
+{
+    LOGD("enter %d , %d", downloadId, received);
+    DOWNLOAD_EVENT_DATA_T *data = new DOWNLOAD_EVENT_DATA_T;
+    data->downloadId = downloadId;
+    data->state = DOWNLOAD_STATE_DOWNLOADING;
+    data->received = received;
+    data->user_data = user_data;
+
+    // download core f/w calls this callback function in another thread.
+    // so we should use g_idle_add() to switch context to main thread.
+    g_idle_add(downloadEventCB, static_cast<void*>(data));
+}
+
+DownloadManager *DownloadManager::getInstance()
+{
+    static DownloadManager instance;
+    return &instance;
+}
+
+DownloadManager::DownloadManager()
+{
+    LOGD("Enter");
+
+}
+
+DownloadManager::~DownloadManager()
+{
+    LOGD("PO is gone, try to unset");
+    int ret;
+
+    for (DownloadCallbackMapT::iterator it = mDownloadCallbacks.begin(); it != mDownloadCallbacks.end(); ++it)
+    {
+        ret = download_unset_progress_cb(it->first);
+        if (ret != DOWNLOAD_ERROR_NONE) {
+             LOGE("ret : %d", ret);
+             LOGE("download_unset_progress_cb error : %s", DownloadUtil::getDownloadErrorMessage(ret).c_str());
+        }
+        ret = download_unset_state_changed_cb(it->first);
+        if (ret != DOWNLOAD_ERROR_NONE) {
+             LOGE("ret : %d", ret);
+             LOGE("download_unset_state_changed_cb error : %s", DownloadUtil::getDownloadErrorMessage(ret).c_str());
+        }
+    }
+
+}
+
+void DownloadManager::cancelAll()
+{
+    LOGD("Enter");
+    int ret;
+
+    for (auto it = mDownloadCallbacks.begin(); it != mDownloadCallbacks.end(); ++it)
+    {
+        ret = download_cancel(it->first);
+        if (ret != DOWNLOAD_ERROR_NONE) {
+             LOGE("ret : %d", ret);
+             LOGE("download_cancel error : %s", DownloadUtil::getDownloadErrorMessage(ret).c_str());
+        }
+        ret = download_destroy(it->first);
+        if (ret != DOWNLOAD_ERROR_NONE) {
+             LOGE("ret : %d", ret);
+             LOGE("download_destroy error : %s", DownloadUtil::getDownloadErrorMessage(ret).c_str());
+        }
+    }
+}
+
+void DownloadManager::setCallbackToMap(long downloadId, DownloadCallback *callback)
+{
+    LOGD("Enter");
+    DownloadCallback *value = mDownloadCallbacks[downloadId];
+    if (value) {
+        delete value;
+    }
+    mDownloadCallbacks[downloadId] = callback;
+}
+
+DownloadCallback* DownloadManager::getCallbackFromMap(long downloadId)
+{
+    LOGD("Enter");
+    return mDownloadCallbacks[downloadId];
+}
+
+void DownloadManager::removeCallbackFromMap(long downloadId) {
+    LOGD("Enter %d",downloadId);
+    DownloadCallback *value = mDownloadCallbacks[downloadId];
+    mDownloadCallbacks.erase(downloadId);
+    if (value) {
+        delete value;
+    }
+}
+
+long DownloadManager::start(DownloadRequest *request,
+    DownloadCallback *downloadCallback, std::string& userAgent)
+{
+    LOGD("Enter");
+    int ret;
+    int downloadId = 0;
+
+    if (!request) {
+        LOGE("request is NULL.");
+        throw TypeMismatchException("request is NULL.");
+    }
+
+    std::string url = request->getUrl();
+    std::string destination = request->getDestination();
+    std::string fileName = request->getFileName();
+    std::string networkType = request->getNetworkType();
+    LOGD("enter %s , %s , %s , %s", url.c_str(), destination.c_str(), fileName.c_str(), networkType.c_str());
+
+    bool isSupported = false;
+    bool isFailed = false;
+    std::string err_msg;
+    std::map<std::string, std::string> httpHeader = request->getHttpHeader();
+    std::map<std::string, std::string> webAppHttpHeader = getWebAppHttpHeader();
+
+    connection_h connection_handle;
+    connection_type_e connection_type = CONNECTION_TYPE_DISCONNECTED;
+
+    if (networkType == TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_CELLULAR) {
+        LOGD("TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_CELLULAR type");
+        if (system_info_get_platform_bool("tizen.org/feature/network.telephony",
+                &isSupported) != SYSTEM_INFO_ERROR_NONE) {
+            LOGE("Can't know whether SMS is supported or not");
+            throw UnknownException("Failed to get telephony support");
+        }
+        LOGD("isCellular supported: %d", isSupported);
+
+        if (isSupported == false) {
+            LOGE("Cellular is not supported");
+            throw NotSupportedException("Unsupported network type (Cellular)");
+        }
+    } else if (networkType == TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_WIFI) {
+        LOGD("TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_WIFI type");
+        if (system_info_get_platform_bool("tizen.org/feature/network.wifi",
+                &isSupported) != SYSTEM_INFO_ERROR_NONE) {
+            LOGE("Can't know whether wifi is supported or not");
+            throw UnknownException("Failed to get WIFI support");
+        }
+        LOGD("isWiFi supported: %d", isSupported);
+
+        if (isSupported == false) {
+            LOGE("WIFI is not supported");
+            throw NotSupportedException("Unsupported message type (WiFi)");
+        }
+    } else if (networkType == TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_ALL) {
+        LOGD("TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_ALL type");
+    } else {
+        LOGE("Type is not matching");
+        throw DeviceAPI::Common::TypeMismatchException("Incorrect type passed");
+    }
+
+    ret = connection_create(&connection_handle);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("Can't create connection handle : %d", ret);
+        DownloadUtil::throwConnectionException(ret, "connection_create()");
+    }
+
+    ret = connection_get_type(connection_handle, &connection_type);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("Can't get network type : %d", ret);
+    }
+
+    ret = connection_destroy(connection_handle);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("Can't destroy connection handle : %d", ret);
+        DownloadUtil::throwConnectionException(ret, "connection_destroy()");
+    }
+
+    switch (connection_type) {
+        case CONNECTION_TYPE_DISCONNECTED : {
+            err_msg = "No network connection is established";
+            isFailed = true;
+            break;
+        }
+        case CONNECTION_TYPE_WIFI : {
+            if (networkType == TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_CELLULAR) {
+                err_msg = "Cellular network is not connected. The current connection type is Wi-Fi.";
+                isFailed = true;
+            }
+            break;
+        }
+        case CONNECTION_TYPE_CELLULAR : {
+            if (networkType == TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_WIFI) {
+                err_msg = "WIFI network is not connected. The current connection type is cellular.";
+                isFailed = true;
+            }
+            break;
+        }
+        case CONNECTION_TYPE_ETHERNET : {
+            if (networkType != TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_ALL) {
+                err_msg = "The requested network type and the current connected network type(ethernet) are not matched";
+                isFailed = true;
+            }
+            break;
+        }
+        case CONNECTION_TYPE_BT : {
+            if (networkType != TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_ALL) {
+                err_msg = "The requested network type and the current connected network type(bluetooth) are not matched";
+                isFailed = true;
+            }
+            break;
+        }
+        default: {
+            LOGE("Incorrect type", connection_type);
+            throw UnknownException("connection_get_type()");
+        }
+    }
+
+    if (isFailed) {
+        LOGE("%s", err_msg.c_str());
+        UnknownException e(err_msg.c_str());
+        if (downloadCallback) {
+            downloadCallback->onfailed(-1, e);
+            delete downloadCallback;
+        } else {
+            LOGE("Callback could not found.");
+        }
+        return -1;
+    }
+
+    // initialize webAppHttpHeader
+    if (!userAgent.empty()) {
+        std::pair<std::string, std::string> userAgentPair("User-Agent", userAgent);
+        webAppHttpHeader.insert(userAgentPair);
+    }
+
+    if (url.empty()) {
+        LOGE("Invalid DownloadRequest.url");
+        throw InvalidValuesException("Invalid DownloadRequest.url");
+    }
+
+    LOGD("enter %d , %s",downloadId, url.c_str());
+    ret = _P(start_download_create, download_create(&downloadId));
+    if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "_P(start_download_create, download_create(&downloadId))");
+    }
+
+    // set url
+    ret = _P(start_download_set_url, download_set_url(downloadId, url.c_str()));
+    if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "_P(start_download_set_url, download_set_url(downloadId, url.c_str())");
+    }
+
+    // set destination
+    if (!destination.empty()) {
+        LOGD("enter");
+        std::string fullPath;
+        try {
+            fullPath = Filesystem::External::fromVirtualPath(destination, NULL);
+        } catch (...) {
+            LOGW("Converting virtual path is failed. [%s]", destination.c_str());
+            fullPath = destination;
+        }
+        LOGD("full path : %s", fullPath.c_str());
+        ret = _P(start_download_set_destination,
+            download_set_destination(downloadId, fullPath.c_str()));
+        if (ret != DOWNLOAD_ERROR_NONE) {
+            if (ret == DOWNLOAD_ERROR_INVALID_DESTINATION) {
+                LOGE("ret : %d", ret);
+                DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "_P(start_download_set_destination, download_set_destination(downloadId, fullPath.c_str()))");
+            }
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "_P(start_download_set_destination, download_set_destination(downloadId, fullPath.c_str()))");
+        }
+    }
+
+    // set fileName
+    if (!fileName.empty()) {
+        ret = _P(start_download_set_file_name,
+            download_set_file_name(downloadId, fileName.c_str()));
+        if (ret != DOWNLOAD_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException(ret, "_P(start_download_set_file_name, download_set_file_name(downloadId, fileName.c_str()))");
+        }
+    }
+
+    // set networkType
+    if (!networkType.empty() && networkType != TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_ALL) {
+        ret = DOWNLOAD_ERROR_NONE;
+        if (networkType == TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_CELLULAR) {
+            ret = _P(start_download_set_network_type,
+                download_set_network_type(downloadId, DOWNLOAD_NETWORK_DATA_NETWORK));
+        } else if (networkType == TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_WIFI) {
+            ret = _P(start_download_set_network_type,
+                download_set_network_type(downloadId, DOWNLOAD_NETWORK_WIFI));
+        } else {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<TypeMismatchException>(ret, "Wrong DownloadNetworkType.");
+        }
+        if (ret != DOWNLOAD_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException(ret, "Platform error while setting network type.");
+        }
+    }
+
+    // set httpHeaders with wrt's HTTPHeaders.
+    // Values given by user prior to the wrt's.
+    for (auto iter = webAppHttpHeader.begin(); iter != webAppHttpHeader.end(); ++iter) {
+        if (httpHeader.find(iter->first) == httpHeader.end()) {
+            std::pair<std::string, std::string> headerPair(iter->first, iter->second);
+            httpHeader.insert(headerPair);
+            LOGD("httpHeader insert");
+
+        }
+    }
+
+    // set httpHeaders
+    std::map<std::string, std::string>::const_iterator iter;
+    for (iter = httpHeader.begin(); iter != httpHeader.end(); ++iter) {
+        LOGD("enter %s , %s",  iter->first.c_str(), iter->second.c_str());
+        ret = _P(start_download_add_http_header_field,
+            download_add_http_header_field(downloadId, iter->first.c_str(),
+                iter->second.c_str()));
+        if (ret != DOWNLOAD_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException(ret, "_P(start_download_add_http_header_field, download_add_http_header_field(downloadId, iter->first.c_str(), iter->second.c_str()))");
+        }
+    }
+
+    // set listeners
+    ret = _P(start_download_set_state_changed_cb,
+        download_set_state_changed_cb(downloadId, download_state_changed_cb, this));
+    if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "Platform error while setting state changed callback.");
+    }
+
+    ret = _P(start_download_set_progress_cb,
+        download_set_progress_cb(downloadId, download_progress_cb, this));
+    if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "Platform error while setting progress callback.");
+    }
+
+    LOGD("starte : %d", downloadId);
+    ret = _P(start_download_start, download_start(downloadId));
+    if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "Platform error while starting download.");
+    }
+
+    LOGD("start : %d", downloadId);
+    setCallbackToMap(downloadId, downloadCallback);
+
+    return downloadId;
+}
+
+void DownloadManager::cancel(long downloadId)
+{
+    int ret;
+    LOGD("enter");
+
+    ret = _P(cancel, download_cancel(downloadId));
+    if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+    } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+    } else if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "_P(cancel, download_cancel(downloadId))");
+    }
+    LOGD("end : %d", downloadId);
+}
+
+void DownloadManager::pause(long downloadId)
+{
+    LOGD("enter");
+    int ret;
+
+    ret = _P(pause, download_pause(downloadId));
+    if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+    } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+    } else if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "_P(pause, download_pause(downloadId))");
+    }
+    LOGD("end : %d", downloadId);
+}
+
+void DownloadManager::resume(long downloadId)
+{
+    LOGD("enter");
+    int ret;
+
+    ret = _P(resume, download_start(downloadId));
+    if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+    } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+    } else if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "_P(resume, download_start(downloadId))");
+    }
+    LOGD("end : %d", downloadId);
+}
+
+std::string DownloadManager::getState(long downloadId)
+{
+    LOGD("enter");
+    int ret;
+    download_state_e state;
+    std::string result;
+
+    ret = _P(getState, download_get_state(downloadId, &state));
+    if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+    } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+    } else if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "_P(getState, download_get_state(downloadId, &state))");
+    }
+
+    LOGD("enter %d", state);
+    switch (state) {
+        case DOWNLOAD_STATE_READY:
+        case DOWNLOAD_STATE_QUEUED:
+            result = TIZEN_ENUM_DOWNLOAD_STATE_QUEUED;
+            break;
+        case DOWNLOAD_STATE_DOWNLOADING:
+            result = TIZEN_ENUM_DOWNLOAD_STATE_DOWNLOADING;
+            break;
+        case DOWNLOAD_STATE_PAUSED:
+            result = TIZEN_ENUM_DOWNLOAD_STATE_PAUSED;
+            break;
+        case DOWNLOAD_STATE_COMPLETED:
+            result = TIZEN_ENUM_DOWNLOAD_STATE_COMPLETED;
+            break;
+        case DOWNLOAD_STATE_FAILED:
+            result = TIZEN_ENUM_DOWNLOAD_STATE_FAILED;
+            break;
+        case DOWNLOAD_STATE_CANCELED:
+            result = TIZEN_ENUM_DOWNLOAD_STATE_CANCELED;
+            break;
+        default:
+            result = "undefined";
+            LOGW("Unknown DownloadState was returned.");
+            break;
+    }
+
+    LOGD("enter %s", result.c_str());
+    return result;
+}
+
+DownloadRequest* DownloadManager::getDownloadRequest(long downloadId)
+{
+    int ret;
+    int i;
+
+    char *url = NULL;
+    char *destination = NULL;
+    char *fileName = NULL;
+    download_network_type_e networkTypeValue = DOWNLOAD_NETWORK_ALL;
+    char **fieldNames = NULL;
+    char *fieldValue = NULL;
+    int fieldLength = 0;
+
+    ret = _P(getDownloadRequest, download_get_url(downloadId, &url));
+    if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+    } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+    } else if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "_P(getDownloadRequest, download_get_url(downloadId, &url))");
+    }
+
+    if (url != NULL)
+        LOGD("%s", url);
+
+    ret = _P(getDownloadRequest, download_get_destination(downloadId, &destination));
+    if (ret != DOWNLOAD_ERROR_NONE && ret != DOWNLOAD_ERROR_NO_DATA) {
+        if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+        } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+        } else{
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException(ret, "_P(getDownloadRequest, download_get_destination(downloadId, &destination))");
+        }
+    }
+
+    if (destination != NULL)
+        LOGD("%s", destination);
+
+    ret = _P(getDownloadRequest, download_get_file_name(downloadId, &fileName));
+    if (ret != DOWNLOAD_ERROR_NONE && ret != DOWNLOAD_ERROR_NO_DATA) {
+        if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+        } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+        } else{
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException(ret, "_P(getDownloadRequest, download_get_file_name(downloadId, &fileName))");
+        }
+    }
+
+    if (fileName != NULL)
+        LOGD("%s", fileName);
+
+    ret = _P(getDownloadRequest, download_get_network_type(downloadId, &networkTypeValue));
+    if (ret != DOWNLOAD_ERROR_NONE && ret != DOWNLOAD_ERROR_NO_DATA) {
+        if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+        } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+        } else{
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException(ret, "_P(getDownloadRequest, download_get_network_type(downloadId, &networkTypeValue))");
+        }
+    }
+    LOGD("%d", networkTypeValue);
+
+    ret = _P(getDownloadRequest, download_get_http_header_field_list(downloadId, &fieldNames, &fieldLength));
+    if (ret != DOWNLOAD_ERROR_NONE && ret != DOWNLOAD_ERROR_NO_DATA) {
+        if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+        } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+        } else{
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException(ret, "_P(getDownloadRequest, download_get_http_header_field_list(downloadId, &fieldNames, &fieldLength))");
+        }
+    }
+    LOGD("%s , %d", fieldNames, networkTypeValue);
+
+    std::map<std::string, std::string> httpHeader;
+    for (i = 0; i < fieldLength; i++) {
+        ret = _P(getDownloadRequest, download_get_http_header_field(downloadId, fieldNames[i], &fieldValue));
+        if (ret != DOWNLOAD_ERROR_NONE) {
+            LOGW("Platform error while getting http header field. %s", DownloadUtil::getDownloadErrorMessage(ret).c_str());
+        }
+        if (fieldValue != NULL) {
+            LOGD("%s , %s", fieldNames[i], fieldValue);
+            httpHeader.insert(make_pair(std::string(fieldNames[i]), std::string(fieldValue)));
+
+            free(fieldValue);
+            fieldValue = NULL;
+        }
+        free(fieldNames[i]);
+    }
+    free(fieldNames);
+
+    DownloadRequest *request = new DownloadRequest();
+
+    if (url) {
+        LOGD("%s", url);
+        request->setUrl(url);
+        free(url);
+    }
+
+    if (destination) {
+        std::string virtualPath;
+        try {
+            virtualPath = Filesystem::External::toVirtualPath(destination, NULL);
+            LOGW("%s, %s", destination, virtualPath.c_str());
+        } catch (...) {
+            LOGW("Platform error while converting destination path.");
+            virtualPath = destination;
+        }
+        request->setDestination(virtualPath);
+        free(destination);
+    }
+
+    if (fileName) {
+        LOGD("%s, %s", fileName);
+        request->setFileName(fileName);
+        free(fileName);
+    }
+
+    switch(networkTypeValue) {
+    case DOWNLOAD_NETWORK_DATA_NETWORK:
+        LOGD("enter");
+        request->setNetworkType(TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_CELLULAR);
+        break;
+    case DOWNLOAD_NETWORK_WIFI:
+        LOGD("enter");
+        request->setNetworkType(TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_WIFI);
+        break;
+    default:
+        LOGD("enter");
+        request->setNetworkType(TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_ALL);
+        break;
+    }
+
+    if (fieldLength) {
+        request->setHttpHeader(httpHeader);
+    }
+
+
+    return request;
+}
+
+std::string DownloadManager::getMIMEType(long downloadId)
+{
+    int ret;
+    char *mimeType = NULL;
+    std::string result("");
+
+    ret = _P(getMIMEType, download_get_mime_type(downloadId, &mimeType));
+    if (ret != DOWNLOAD_ERROR_NONE) {
+        if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+        } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+        } else if (ret == DOWNLOAD_ERROR_NO_DATA) {
+            LOGE("no data : %s", DownloadUtil::getDownloadErrorMessage(ret).c_str());
+            result = "";
+        } else {
+            LOGE("ret : %d", ret);
+            DownloadUtil::throwDownloadException(ret, "_P(getMIMEType, download_get_mime_type(downloadId, &mimeType))");
+        }
+    } else {
+        result = mimeType;
+    }
+
+    if (mimeType) {
+        free(mimeType);
+    }
+
+    return result;
+}
+
+void DownloadManager::setListener(long downloadId, DownloadCallback *downloadCallback)
+{
+    int ret;
+
+    ret = _P(setListener, download_set_state_changed_cb(downloadId, download_state_changed_cb, this));
+    if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+    } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+    } else if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "_P(setListener, download_set_state_changed_cb(downloadId, download_state_changed_cb, this))");
+    }
+
+
+    ret = _P(setListener, download_set_progress_cb(downloadId, download_progress_cb, this));
+    if (ret == DOWNLOAD_ERROR_ID_NOT_FOUND) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<NotFoundException>(ret, "download id could not found.");
+    } else if (ret == DOWNLOAD_ERROR_INVALID_PARAMETER) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException<InvalidValuesException>(ret, "download id is not valid.");
+    } else if (ret != DOWNLOAD_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        DownloadUtil::throwDownloadException(ret, "_P(setListener, download_set_progress_cb(downloadId, download_progress_cb, this))");
+    }
+
+
+    LOGD("end");
+    setCallbackToMap(downloadId, downloadCallback);
+}
+
+std::map<std::string, std::string> DownloadManager::getWebAppHttpHeader()
+{
+    LOGD("enter");
+    std::map<std::string, std::string> webAppHttpHeader;
+
+    // TODO get HTTPHeaders from WRT
+
+    return webAppHttpHeader;
+}
+
+} // Download
+} // DeviceAPI
diff --git a/src/Download/DownloadManager.h b/src/Download/DownloadManager.h
new file mode 100755 (executable)
index 0000000..e41b153
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DOWNLOAD_MANAGER_H__
+#define __TIZEN_DOWNLOAD_MANAGER_H__
+
+#include <string>
+#include <map>
+#include <Security.h>
+
+#include "DownloadRequest.h"
+#include "DownloadCallback.h"
+
+namespace DeviceAPI {
+namespace Download {
+
+class DownloadManager :
+    public DeviceAPI::Common::SecurityAccessor
+{
+public:
+    DownloadManager();
+    virtual ~DownloadManager();
+
+    static DownloadManager *getInstance();
+
+    long start(DownloadRequest *request,
+        DownloadCallback *downloadCallback,
+        std::string& userAgent);
+    void cancel(long downloadId);
+    void pause(long downloadId);
+    void resume(long downloadId);
+    std::string getState(long downloadId);
+    DownloadRequest* getDownloadRequest(long downloadId);
+    std::string getMIMEType(long downloadId);
+    void setListener(long downloadId, DownloadCallback *downloadCallback);
+    void cancelAll();
+
+    // internal function
+    void setCallbackToMap(long downloadId, DownloadCallback *callback);
+    DownloadCallback* getCallbackFromMap(long downloadId);
+    void removeCallbackFromMap(long downloadId);
+
+private:
+    typedef std::map<long, DownloadCallback*> DownloadCallbackMapT;
+    DownloadCallbackMapT mDownloadCallbacks;
+
+    std::map<std::string, std::string> getWebAppHttpHeader();
+};
+
+}
+}
+
+
+
+#endif // __TIZEN_DOWNLOAD_MANAGER_H__
diff --git a/src/Download/DownloadNetworkType.h b/src/Download/DownloadNetworkType.h
new file mode 100755 (executable)
index 0000000..f8e4931
--- /dev/null
@@ -0,0 +1,31 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DOWNLOAD_NETWORK_TYPE_H__
+#define __TIZEN_DOWNLOAD_NETWORK_TYPE_H__
+
+namespace DeviceAPI {
+namespace Download {
+
+#define TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_CELLULAR "CELLULAR"
+#define TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_WIFI "WIFI"
+#define TIZEN_ENUM_DOWNLOAD_NETWORK_TYPE_ALL "ALL"
+
+} // Download
+} // DeviceAPI
+
+#endif // __TIZEN_DOWNLOAD_NETWORK_TYPE_H__
diff --git a/src/Download/DownloadRequest.cpp b/src/Download/DownloadRequest.cpp
new file mode 100755 (executable)
index 0000000..92ce0ba
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <Logger.h>
+
+
+#include "DownloadRequest.h"
+
+namespace DeviceAPI {
+namespace Download {
+
+DownloadRequest::DownloadRequest():
+    m_url(""),
+    m_destination(""),
+    m_fileName(""),
+    m_networkType("")
+{
+    LOGD("enter");
+
+    m_httpHeader.clear();
+}
+
+DownloadRequest::~DownloadRequest()
+{
+    LOGD("enter");
+}
+
+std::string DownloadRequest::getUrl() const
+{
+    return m_url;
+}
+
+void DownloadRequest::setUrl(std::string url)
+{
+    m_url = url;
+}
+
+std::string DownloadRequest::getDestination() const
+{
+    return m_destination;
+}
+
+void DownloadRequest::setDestination(std::string destination)
+{
+    m_destination = destination;
+}
+
+std::string DownloadRequest::getFileName() const
+{
+    return m_fileName;
+}
+
+void DownloadRequest::setFileName(std::string fileName)
+{
+    m_fileName = fileName;
+}
+
+std::string DownloadRequest::getNetworkType() const
+{
+    return m_networkType;
+}
+
+void DownloadRequest::setNetworkType(std::string networkType)
+{
+    LOGD("enter %s",m_networkType.c_str());
+
+    m_networkType = networkType;
+}
+
+std::map<std::string, std::string> DownloadRequest::getHttpHeader() const
+{
+    return m_httpHeader;
+}
+
+void DownloadRequest::setHttpHeader(std::map<std::string, std::string> httpHeader)
+{
+    m_httpHeader = httpHeader;
+}
+
+} // Download
+} // DeviceAPI
diff --git a/src/Download/DownloadRequest.h b/src/Download/DownloadRequest.h
new file mode 100755 (executable)
index 0000000..3bbd786
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DOWNLOAD_REQUEST_H__
+#define __TIZEN_DOWNLOAD_REQUEST_H__
+
+#include <map>
+#include <string>
+
+namespace DeviceAPI {
+namespace Download {
+
+class DownloadRequest
+{
+public:
+    DownloadRequest();
+    virtual ~DownloadRequest();
+
+    std::string getUrl() const;
+    void setUrl(std::string url);
+
+    std::string getDestination() const;
+    void setDestination(std::string destination);
+
+    std::string getFileName() const;
+    void setFileName(std::string fileName);
+
+    std::string getNetworkType() const;
+    void setNetworkType(std::string networkType);
+
+    std::map<std::string, std::string> getHttpHeader() const;
+    void setHttpHeader(std::map<std::string, std::string> httpHeader);
+
+
+private:
+    std::string m_url;
+    std::string m_destination;
+    std::string m_fileName;
+    std::string m_networkType;
+    std::map<std::string, std::string> m_httpHeader;
+};
+
+} // Download
+} // DeviceAPI
+
+#endif // __TIZEN_DOWNLOAD_REQUEST_H__
diff --git a/src/Download/DownloadState.h b/src/Download/DownloadState.h
new file mode 100755 (executable)
index 0000000..eb66727
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DOWNLOAD_STATE_H__
+#define __TIZEN_DOWNLOAD_STATE_H__
+
+namespace DeviceAPI {
+namespace Download {
+
+#define TIZEN_ENUM_DOWNLOAD_STATE_QUEUED "QUEUED"
+#define TIZEN_ENUM_DOWNLOAD_STATE_DOWNLOADING "DOWNLOADING"
+#define TIZEN_ENUM_DOWNLOAD_STATE_PAUSED "PAUSED"
+#define TIZEN_ENUM_DOWNLOAD_STATE_CANCELED "CANCELED"
+#define TIZEN_ENUM_DOWNLOAD_STATE_COMPLETED "COMPLETED"
+#define TIZEN_ENUM_DOWNLOAD_STATE_FAILED "FAILED"
+
+} // Download
+} // DeviceAPI
+
+#endif // __TIZEN_DOWNLOAD_STATE_H__
\ No newline at end of file
diff --git a/src/Download/DownloadUtil.cpp b/src/Download/DownloadUtil.cpp
new file mode 100755 (executable)
index 0000000..b05364e
--- /dev/null
@@ -0,0 +1,140 @@
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "DownloadUtil.h"
+#include <PlatformException.h>
+#include <Logger.h>
+#include <sstream>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Download {
+
+std::string DownloadUtil::getDownloadErrorMessage(const int errorCode) {
+    switch(errorCode) {
+        case DOWNLOAD_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case DOWNLOAD_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case DOWNLOAD_ERROR_NETWORK_UNREACHABLE:
+            return "Network is unreachable";
+        case DOWNLOAD_ERROR_CONNECTION_TIMED_OUT:
+            return "HTTP session time-out";
+        case DOWNLOAD_ERROR_NO_SPACE:
+            return "No space left on device";
+        case DOWNLOAD_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case DOWNLOAD_ERROR_NOT_SUPPORTED:
+            return "Not supported";
+        case DOWNLOAD_ERROR_INVALID_STATE:
+            return "Invalid state";
+        case DOWNLOAD_ERROR_CONNECTION_FAILED:
+            return "Connection failed";
+        case DOWNLOAD_ERROR_INVALID_URL:
+            return "Invalid URL";
+        case DOWNLOAD_ERROR_INVALID_DESTINATION:
+            return "Invalid destination";
+        case DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS:
+            return "Too many simultaneous downloads";
+        case DOWNLOAD_ERROR_QUEUE_FULL:
+            return "Download server queue is full";
+        case DOWNLOAD_ERROR_ALREADY_COMPLETED:
+            return "The download is already completed";
+        case DOWNLOAD_ERROR_FILE_ALREADY_EXISTS:
+            return "Failed to rename the downloaded file";
+        case DOWNLOAD_ERROR_CANNOT_RESUME:
+            return "Cannot resume";
+        case DOWNLOAD_ERROR_FIELD_NOT_FOUND:
+            return "Specified field not found";
+        case DOWNLOAD_ERROR_TOO_MANY_REDIRECTS:
+            return "Too many redirects from HTTP response header";
+        case DOWNLOAD_ERROR_UNHANDLED_HTTP_CODE:
+            return "The download cannot handle the HTTP status value";
+        case DOWNLOAD_ERROR_REQUEST_TIMEOUT:
+            return "No action after client creates a download ID";
+        case DOWNLOAD_ERROR_RESPONSE_TIMEOUT:
+            return "No call to start API for some time although the download is created";
+        case DOWNLOAD_ERROR_SYSTEM_DOWN:
+            return "Download ID does not exist in download service module";
+        case DOWNLOAD_ERROR_ID_NOT_FOUND:
+            return "Network bonding is set but network type is not set as DOWNLOAD_NETWORK_ALL";
+        case DOWNLOAD_ERROR_INVALID_NETWORK_TYPE:
+            return "Connection failed";
+        case DOWNLOAD_ERROR_NO_DATA:
+            return "No data because the set API is not called";
+        case DOWNLOAD_ERROR_IO_ERROR:
+            return "Internal I/O error";
+        default:
+            return "Unknown error";
+    }
+}
+
+
+std::string DownloadUtil::getDownloadLogMessage(const int errorCode, const std::string &hint) {
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getDownloadErrorMessage(errorCode) << ", " << errorCode;
+    return std::string(ss.str());
+}
+
+
+std::string DownloadUtil::getConnectionErrorMessage(const int errorCode) {
+    switch(errorCode) {
+        case CONNECTION_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case CONNECTION_ERROR_OUT_OF_MEMORY:
+            return "Out of memory error";
+        case CONNECTION_ERROR_INVALID_OPERATION:
+            return "Invalid Operation";
+        case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
+            return "Address family not supported";
+        case CONNECTION_ERROR_OPERATION_FAILED:
+            return "Operation failed";
+        case CONNECTION_ERROR_ITERATOR_END:
+            return "End of iteration";
+        case CONNECTION_ERROR_NO_CONNECTION:
+            return "There is no connection";
+        case CONNECTION_ERROR_NOW_IN_PROGRESS:
+            return "Now in progress";
+        case CONNECTION_ERROR_ALREADY_EXISTS:
+            return "Already exists";
+        case CONNECTION_ERROR_OPERATION_ABORTED:
+            return "Operation is aborted";
+        case CONNECTION_ERROR_DHCP_FAILED:
+            return "DHCP failed";
+        case CONNECTION_ERROR_INVALID_KEY:
+            return "Invalid key";
+        case CONNECTION_ERROR_NO_REPLY:
+            return "No reply";
+        case CONNECTION_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case CONNECTION_ERROR_NOT_SUPPORTED:
+            return "Not Supported";
+        default:
+            return "Unknown error";
+    }
+}
+
+
+std::string DownloadUtil::getConnectionLogMessage(const int errorCode, const std::string &hint) {
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getConnectionErrorMessage(errorCode) << ", " << errorCode;
+    return std::string(ss.str());
+}
+
+
+} // Download
+} // DeviceAPI
diff --git a/src/Download/DownloadUtil.h b/src/Download/DownloadUtil.h
new file mode 100755 (executable)
index 0000000..33330fd
--- /dev/null
@@ -0,0 +1,54 @@
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DOWNLOAD_UTIL_H__
+#define __TIZEN_DOWNLOAD_UTIL_H__
+
+#include <string>
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <download.h>
+#include <net_connection.h>
+
+namespace DeviceAPI {
+namespace Download {
+
+class DownloadUtil {
+public:
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwDownloadException(const int errorCode, const std::string &hint) {
+        std::string log = DownloadUtil::getDownloadLogMessage(errorCode, hint);
+        LOGE("%s", log.c_str());
+        throw T(log.c_str());
+    }
+    static std::string getDownloadErrorMessage(const int errorCode);
+    static std::string getDownloadLogMessage(const int errorCode, const std::string &hint);
+
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwConnectionException(const int errorCode, const std::string &hint) {
+        std::string log = DownloadUtil::getConnectionLogMessage(errorCode, hint);
+        LOGE("%s", log.c_str());
+        throw T(log.c_str());
+    }
+    static std::string getConnectionErrorMessage(const int errorCode);
+    static std::string getConnectionLogMessage(const int errorCode, const std::string &hint);
+};
+
+} // Download
+} // DeviceAPI
+
+#endif // __TIZEN_DOWNLOAD_UTIL_H__
diff --git a/src/Download/JSDownloadManager.cpp b/src/Download/JSDownloadManager.cpp
new file mode 100755 (executable)
index 0000000..6b0dc44
--- /dev/null
@@ -0,0 +1,484 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <JSStringRefWrapper.h>
+#include <Security.h>
+
+#include "plugin_config_impl.h"
+
+#include "JSDownloadManager.h"
+#include "JSDownloadRequest.h"
+#include "DownloadManager.h"
+#include "DownloadRequest.h"
+#include "DownloadCallback.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Download {
+
+namespace {
+    std::string getUserAgent(JSContextRef context)
+    {
+        std::string userAgent;
+
+        JSValueRef jsException = NULL;
+        JSObjectRef jsObjWindow = JSContextGetGlobalObject(context);
+        JSStringRefWrapper jsStrWrpNavigator("navigator");
+        JSValueRef jsValNavigator =
+            JSObjectGetProperty(context, jsObjWindow, jsStrWrpNavigator.get(),
+                &jsException);
+        if (jsException != NULL) {
+            LOGW("Fail to get userAgent while getting navigator value.");
+            return userAgent;
+        }
+
+        JSObjectRef jsObjNavigator = JSValueToObject(context, jsValNavigator,
+            &jsException);
+        if (jsException != NULL) {
+            LOGW("Fail to get userAgent while getting navigator object.");
+            return userAgent;
+        }
+
+        JSStringRefWrapper jsStrWrtUserAgent("userAgent");
+        JSValueRef jsValUserAgent = JSObjectGetProperty(context, jsObjNavigator,
+            jsStrWrtUserAgent.get(), &jsException);
+        if (jsException != NULL) {
+            LOGW("Fail to get userAgent while getting userAgent value.");
+            return userAgent;
+        }
+
+        JSStringRef jsStrUserAgent = JSValueToStringCopy(context,
+            jsValUserAgent, &jsException);
+        if (jsException != NULL) {
+            LOGW("Fail to get userAgent while getting userAgent string.");
+            return userAgent;
+        }
+
+        size_t size = JSStringGetLength(jsStrUserAgent);
+        char cstrUserAgent[size*3];
+        JSStringGetUTF8CString(jsStrUserAgent, cstrUserAgent, size*3);
+
+        userAgent = cstrUserAgent;
+
+        return userAgent;
+    }
+}
+
+JSClassDefinition JSDownloadManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "DownloadManager",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function,
+    initialize,
+    finalize,
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSDownloadManager::m_function[] = {
+    { DOWNLOAD_FUNCTION_API_START, startDownload, kJSPropertyAttributeNone },
+    { DOWNLOAD_FUNCTION_API_CANCEL, cancelDownload, kJSPropertyAttributeNone },
+    { DOWNLOAD_FUNCTION_API_PAUSE, pauseDownload, kJSPropertyAttributeNone },
+    { DOWNLOAD_FUNCTION_API_RESUME, resumeDownload, kJSPropertyAttributeNone },
+    { DOWNLOAD_FUNCTION_API_GET_STATE, getState, kJSPropertyAttributeNone },
+    { DOWNLOAD_FUNCTION_API_GET_DOWNLOAD_REQUEST, getDownloadRequest, kJSPropertyAttributeNone },
+    { DOWNLOAD_FUNCTION_API_GET_MIME_TYPE, getMIMEType, kJSPropertyAttributeNone },
+    { DOWNLOAD_FUNCTION_API_SET_LISTENER, setListener, kJSPropertyAttributeNone },
+
+    { 0, 0, 0 }
+};
+
+JSClassRef JSDownloadManager::m_jsClassRef = JSClassCreate(JSDownloadManager::getClassInfo());
+
+const JSClassRef JSDownloadManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSDownloadManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSDownloadManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        DownloadManager *downloadManager = DownloadManager::getInstance();
+        if (!JSObjectSetPrivate(object, static_cast<void*>(downloadManager))) {
+            //delete downloadManager;
+        }
+    }
+}
+
+void JSDownloadManager::finalize(JSObjectRef object)
+{
+    DownloadManager *downloadManager =
+        static_cast<DownloadManager*>(JSObjectGetPrivate(object));
+    if (downloadManager) {
+        JSObjectSetPrivate(object, NULL);
+        //delete downloadManager;
+    }
+}
+
+JSValueRef JSDownloadManager::startDownload(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try {
+        // Private Object
+        DownloadManager *downloadManager =
+            static_cast<DownloadManager*>(JSObjectGetPrivate(thisObject));
+        if (!downloadManager) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        // Access Check
+        TIME_TRACER_ITEM_BEGIN("DOWNLOAD_start_ACE", 0);
+        TIZEN_CHECK_ACCESS(context, exception, downloadManager,
+            DOWNLOAD_FUNCTION_API_START);
+        TIME_TRACER_ITEM_END("DOWNLOAD_start_ACE", 0);
+
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // downloadRequest
+        JSObjectRef downloadRequestObj =
+            validator.toObject(0, JSDownloadRequest::getClassRef());
+        DownloadRequest *downloadRequest =
+            JSDownloadRequest::getPrivateObject(context, downloadRequestObj);
+        if (!downloadRequest) {
+            throw TypeMismatchException("DownloadRequest's private object is NULL.");
+        }
+
+        // downloadCallback
+        DownloadCallback *downloadCallback = NULL;
+        JSObjectRef downloadCallbackObj = validator.toObject(1, true);
+        if (downloadCallbackObj) {
+            downloadCallback =
+                new DownloadCallback(GlobalContextManager::getInstance()->
+                    getGlobalContext(context), downloadCallbackObj);
+        }
+
+        // getting userAgent from navigator.userAgent (to be replaced by other method)
+        std::string userAgent = getUserAgent(context);
+
+        long downloadId = downloadManager->start(downloadRequest,
+            downloadCallback, userAgent);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSUtil::toJSValueRef(context, downloadId);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in tizen.download.start().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSDownloadManager::setListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        // Private Object
+        DownloadManager *downloadManager =
+            static_cast<DownloadManager*>(JSObjectGetPrivate(thisObject));
+        if (!downloadManager) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // downloadId
+        long downloadId = validator.toLong(0);
+
+        // downloadCallback
+        JSObjectRef downloadCallbackObj = validator.toObject(1);
+        DownloadCallback *downloadCallback =
+            new DownloadCallback(GlobalContextManager::getInstance()->
+                getGlobalContext(context), downloadCallbackObj);
+
+        // perform
+        downloadManager->setListener(downloadId, downloadCallback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in tizen.download.setListener().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSDownloadManager::cancelDownload(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        // Private Object
+        DownloadManager *downloadManager =
+            static_cast<DownloadManager*>(JSObjectGetPrivate(thisObject));
+        if (!downloadManager) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // downloadId
+        long downloadId = validator.toLong(0);
+
+        // perform
+        downloadManager->cancel(downloadId);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in tizen.download.cancel().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSDownloadManager::pauseDownload(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        // Private Object
+        DownloadManager *downloadManager =
+            static_cast<DownloadManager*>(JSObjectGetPrivate(thisObject));
+        if (!downloadManager) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // downloadId
+        long downloadId = validator.toLong(0);
+
+        // perform
+        downloadManager->pause(downloadId);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in tizen.download.pause().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSDownloadManager::resumeDownload(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        // Private Object
+        DownloadManager *downloadManager =
+            static_cast<DownloadManager*>(JSObjectGetPrivate(thisObject));
+        if (!downloadManager) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // downloadId
+        long downloadId = validator.toLong(0);
+
+        // perform
+        downloadManager->resume(downloadId);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in tizen.download.resume().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSDownloadManager::getState(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        // Private Object
+        DownloadManager *downloadManager =
+            static_cast<DownloadManager*>(JSObjectGetPrivate(thisObject));
+        if (!downloadManager) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // downloadId
+        long downloadId = validator.toLong(0);
+
+        // perform
+        std::string ret = downloadManager->getState(downloadId);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSUtil::toJSValueRef(context, ret);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException
+            err("Unknown Error in tizen.download.resume().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSDownloadManager::getDownloadRequest(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        // Private Object
+        DownloadManager *downloadManager =
+            static_cast<DownloadManager*>(JSObjectGetPrivate(thisObject));
+        if (!downloadManager) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // downloadId
+        long downloadId = validator.toLong(0);
+
+        // perform
+        JSObjectRef obj =
+            JSObjectMake(context, JSDownloadRequest::getClassRef(), NULL);
+        DownloadRequest *priv = downloadManager->getDownloadRequest(downloadId);
+        JSDownloadRequest::setPrivateObject(context, obj, priv);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return obj;
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in tizen.download.resume().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSDownloadManager::getMIMEType(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        // Private Object
+        DownloadManager *downloadManager =
+            static_cast<DownloadManager*>(JSObjectGetPrivate(thisObject));
+        if (!downloadManager) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // downloadId
+        long downloadId = validator.toLong(0);
+
+        // perform
+        std::string ret = downloadManager->getMIMEType(downloadId);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSUtil::toJSValueRef(context, ret);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in tizen.download.resume().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Download
+} // DeviceAPI
diff --git a/src/Download/JSDownloadManager.h b/src/Download/JSDownloadManager.h
new file mode 100755 (executable)
index 0000000..86c50f0
--- /dev/null
@@ -0,0 +1,151 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_DOWNLOAD_MANAGER_H__
+#define __TIZEN_JS_DOWNLOAD_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Download {
+
+class JSDownloadManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Start a download operation.
+     */
+    static JSValueRef startDownload(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Cancel a download operation.
+     */
+    static JSValueRef cancelDownload(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Pause a download operation.
+     */
+    static JSValueRef pauseDownload(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Resume a paused download operation.
+     */
+    static JSValueRef resumeDownload(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Get the current state of a download operation.
+     */
+    static JSValueRef getState(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Get the DownloadRequest of a download operation.
+     */
+    static JSValueRef getDownloadRequest(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Get the MIME type of a downloaded file.
+     */
+    static JSValueRef getMIMEType(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Set the listener to the ongoing download operation.
+     */
+    static JSValueRef setListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+};
+
+
+} // Download
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Download/JSDownloadRequest.cpp b/src/Download/JSDownloadRequest.cpp
new file mode 100755 (executable)
index 0000000..b5187d9
--- /dev/null
@@ -0,0 +1,276 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include <Logger.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+
+#include "JSDownloadRequest.h"
+#include "DownloadRequest.h"
+
+#define TIZEN_DOWNLOAD_REQUEST_URL "url"
+#define TIZEN_DOWNLOAD_REQUEST_DESTINATION "destination"
+#define TIZEN_DOWNLOAD_REQUEST_FILE_NAME "fileName"
+#define TIZEN_DOWNLOAD_REQUEST_NETWORK_TYPE "networkType"
+#define TIZEN_DOWNLOAD_REQUEST_HTTP_HEADER "httpHeader"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Download {
+
+JSClassDefinition JSDownloadRequest::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "DownloadRequest",
+    NULL, //parentClass
+    NULL, //staticValues,
+    NULL, //staticFunctions,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    setProperty, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //constructor
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+
+JSClassRef JSDownloadRequest::m_jsClassRef = JSClassCreate(JSDownloadRequest::getClassInfo());
+
+const JSClassDefinition* JSDownloadRequest::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+JSClassRef JSDownloadRequest::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSDownloadRequest::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        DownloadRequest *priv = new DownloadRequest();
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    }
+}
+
+void JSDownloadRequest::finalize(JSObjectRef object)
+{
+    DownloadRequest *priv = static_cast<DownloadRequest*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+bool JSDownloadRequest::setProperty(JSContextRef context, JSObjectRef object,
+        JSStringRef propertyName, JSValueRef value,  JSValueRef* exception)
+{
+    try {
+        // check url
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_DOWNLOAD_REQUEST_URL)) {
+            if (JSValueIsNull(context, value))
+            {
+                JSUtil::setProperty(context, object, TIZEN_DOWNLOAD_REQUEST_URL, JSUtil::toJSValueRef(context, JSUtil::JSValueToString(context, value)), kJSPropertyAttributeNone);
+                return true;
+            }else
+            {
+                JSUtil::JSValueToString(context, value);
+            }
+        }
+
+        // check destination
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_DOWNLOAD_REQUEST_DESTINATION)) {
+            JSUtil::JSValueToString(context, value);
+        }
+
+        // check fileName
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_DOWNLOAD_REQUEST_FILE_NAME)) {
+            JSUtil::JSValueToString(context, value);
+        }
+
+        // check networkType
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_DOWNLOAD_REQUEST_NETWORK_TYPE)) {
+            if (!JSValueIsNull(context, value)) {
+                std::string networkType = JSUtil::JSValueToString(context, value);
+                if (networkType != "CELLULAR" && networkType != "WIFI" && networkType != "ALL")
+                {
+                    throw TypeMismatchException("Invalid networkType");
+                }
+            }
+        }
+
+        // check httpHeader
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_DOWNLOAD_REQUEST_HTTP_HEADER)) {
+            if (!JSValueIsNull(context, value)) {
+                if (!JSValueIsObject(context, value)) {
+                    throw TypeMismatchException("Value is not Object");
+                }
+                JSUtil::JSValueToObject(context, value);
+            }
+        }
+    } catch (const BasePlatformException &err) {
+       LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+       return true;
+    }
+
+    return false;
+}
+
+JSObjectRef JSDownloadRequest::constructor(JSContextRef context,
+    JSObjectRef constructor,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    // constructor
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, obj, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    DownloadRequest *priv = new DownloadRequest();
+
+    try {
+        priv->setUrl(validator.toString(0, true, ""));
+    } catch (const BasePlatformException& err) {
+        LOGW("url convertion is failed. %s", err.getMessage().c_str());
+    }
+
+    try {
+        priv->setDestination(validator.toString(1, true, ""));
+    } catch (const BasePlatformException& err) {
+        LOGW("destination convertion is failed. %s", err.getMessage().c_str());
+    }
+
+    try {
+        priv->setFileName(validator.toString(2, true, ""));
+    } catch (const BasePlatformException& err) {
+        LOGW("fileName convertion is failed. %s", err.getMessage().c_str());
+    }
+
+    try {
+        std::string networkType = validator.toString(3, true, "ALL");
+        if (networkType.compare("CELLULAR") && networkType.compare("WIFI") && networkType.compare("ALL")) {
+            networkType = "ALL";
+            LOGW("networkType is invalid. 'ALL' type is set.");
+        }
+        priv->setNetworkType(networkType);
+    } catch (const BasePlatformException& err) {
+        LOGW("networkType convertion is failed. %s", err.getMessage().c_str());
+    }
+
+    try {
+        priv->setHttpHeader(validator.toStringMap(4, true));
+    } catch (const BasePlatformException& err) {
+        LOGW("httpHeader convertion is failed. %s", err.getMessage().c_str());
+    }
+
+    setPrivateObject(context, obj, priv);
+
+    return obj;
+}
+
+DownloadRequest* JSDownloadRequest::getPrivateObject(JSContextRef context, JSObjectRef object)
+{
+    DownloadRequest *priv = static_cast<DownloadRequest*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("DownloadRequest's private object is NULL.");
+    }
+
+    // url
+    JSValueRef url = JSUtil::getProperty(context, object, TIZEN_DOWNLOAD_REQUEST_URL);
+    priv->setUrl(JSUtil::JSValueToString(context, url));
+
+    // destination
+    JSValueRef destination = JSUtil::getProperty(context, object, TIZEN_DOWNLOAD_REQUEST_DESTINATION);
+    priv->setDestination(JSUtil::JSValueToString(context, destination));
+
+    // fileName
+    JSValueRef fileName = JSUtil::getProperty(context, object, TIZEN_DOWNLOAD_REQUEST_FILE_NAME);
+    priv->setFileName(JSUtil::JSValueToString(context, fileName));
+
+    // networkType
+    JSValueRef networkType = JSUtil::getProperty(context, object, TIZEN_DOWNLOAD_REQUEST_NETWORK_TYPE);
+    if (JSValueIsNull(context, networkType)) {
+        priv->setNetworkType("ALL");
+    } else {
+        priv->setNetworkType(JSUtil::JSValueToString(context, networkType));
+    }
+
+    // httpHeader
+    JSValueRef httpHeader = JSUtil::getProperty(context, object, TIZEN_DOWNLOAD_REQUEST_HTTP_HEADER);
+    if (JSValueIsNull(context, httpHeader)) {
+        priv->setHttpHeader(std::map<std::string, std::string>());
+    } else {
+        priv->setHttpHeader(JSUtil::JSValueToStringMap(context, httpHeader));
+    }
+
+    return priv;
+}
+
+void JSDownloadRequest::setPrivateObject(JSContextRef context, JSObjectRef object, DownloadRequest* priv)
+{
+    if (!priv) {
+        throw TypeMismatchException("DownloadRequest's private object is NULL.");
+    }
+
+    JSObjectSetPrivate(object, static_cast<void*>(priv));
+
+    // url
+    JSUtil::setProperty(context, object, TIZEN_DOWNLOAD_REQUEST_URL,
+            JSUtil::toJSValueRef(context, priv->getUrl()), kJSPropertyAttributeNone);
+
+    // destination
+    JSUtil::setProperty(context, object, TIZEN_DOWNLOAD_REQUEST_DESTINATION,
+            JSUtil::toJSValueRef(context, priv->getDestination()), kJSPropertyAttributeNone);
+
+    // fileName
+    JSUtil::setProperty(context, object, TIZEN_DOWNLOAD_REQUEST_FILE_NAME,
+            JSUtil::toJSValueRef(context, priv->getFileName()), kJSPropertyAttributeNone);
+
+    // networkType
+    JSUtil::setProperty(context, object, TIZEN_DOWNLOAD_REQUEST_NETWORK_TYPE,
+            JSUtil::toJSValueRef(context, priv->getNetworkType()), kJSPropertyAttributeNone);
+
+    // httpHeader
+    JSUtil::setProperty(context, object, TIZEN_DOWNLOAD_REQUEST_HTTP_HEADER,
+            JSUtil::toJSValueRef(context, priv->getHttpHeader()), kJSPropertyAttributeNone);
+}
+
+} // Download
+} // DeviceAPI
diff --git a/src/Download/JSDownloadRequest.h b/src/Download/JSDownloadRequest.h
new file mode 100755 (executable)
index 0000000..8705980
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_DOWNLOAD_REQUEST_H__
+#define __TIZEN_JS_DOWNLOAD_REQUEST_H__
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+#include "DownloadRequest.h"
+
+namespace DeviceAPI {
+namespace Download {
+
+class JSDownloadRequest {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static JSClassRef getClassRef();
+
+    /**
+     * Constructor for the DownloadRequest interface.
+     */
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static DownloadRequest* getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSContextRef context, JSObjectRef object, DownloadRequest* priv);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+} // Download
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_REQUEST_H__
\ No newline at end of file
diff --git a/src/Download/config.xml b/src/Download/config.xml
new file mode 100755 (executable)
index 0000000..f5db19c
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-download.so</library-name>
+    <feature-install-uri>download.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/download</name>
+        <device-capability>download</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/Download/plugin_config.cpp b/src/Download/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..b761e0c
--- /dev/null
@@ -0,0 +1,85 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+#include "plugin_config_impl.h"
+
+#define DOWNLOAD_FEATURE_API "http://tizen.org/privilege/download"
+
+#define DOWNLOAD_DEVICE_CAP "download"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Download {
+
+static FunctionMapping createDownloadFunctions();
+
+static FunctionMapping DownloadFunctions =
+    createDownloadFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(Download, DownloadFunctions);
+
+#pragma GCC visibility pop
+
+static FunctionMapping createDownloadFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_DOWNLOAD, DOWNLOAD_DEVICE_CAP);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_DOWNLOAD);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_DOWNLOAD, DEVICE_CAP_DOWNLOAD);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_DOWNLOAD, DOWNLOAD_FEATURE_API);
+
+    ACE_CREATE_FEATURE_LIST(DOWNLOAD_FEATURES);
+    ACE_ADD_API_FEATURE(DOWNLOAD_FEATURES, FEATURE_DOWNLOAD);
+
+    /**
+     * Functions
+     */
+    FunctionMapping downloadMapping;
+
+    // start
+    AceFunction startFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_START,
+            DOWNLOAD_FUNCTION_API_START,
+            DOWNLOAD_FEATURES,
+            DEVICE_LIST_DOWNLOAD);
+
+    downloadMapping.insert(std::make_pair(
+                               DOWNLOAD_FUNCTION_API_START,
+                               startFunc));
+
+    return downloadMapping;
+}
+
+}
+}
diff --git a/src/Download/plugin_config.h b/src/Download/plugin_config.h
new file mode 100755 (executable)
index 0000000..86f73a4
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _DOWNLOAD_PLUGIN_CONFIG_H_
+#define _DOWNLOAD_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+namespace DeviceAPI {
+namespace Download {
+
+DECLARE_FUNCTION_GETTER(Download);
+
+#define DOWNLOAD_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getDownloadFunctionData, \
+    functionName)
+}
+}
+
+#endif // _DOWNLOAD_PLUGIN_CONFIG_H_
\ No newline at end of file
diff --git a/src/Download/plugin_config_impl.h b/src/Download/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..c0a8e29
--- /dev/null
@@ -0,0 +1,31 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _DOWNLOAD_PLUGIN_CONFIG_IMPL_H_
+#define _DOWNLOAD_PLUGIN_CONFIG_IMPL_H_
+
+// Functions from download manager
+#define DOWNLOAD_FUNCTION_API_START "start"
+#define DOWNLOAD_FUNCTION_API_CANCEL "cancel"
+#define DOWNLOAD_FUNCTION_API_PAUSE "pause"
+#define DOWNLOAD_FUNCTION_API_RESUME "resume"
+#define DOWNLOAD_FUNCTION_API_GET_STATE "getState"
+#define DOWNLOAD_FUNCTION_API_GET_DOWNLOAD_REQUEST "getDownloadRequest"
+#define DOWNLOAD_FUNCTION_API_GET_MIME_TYPE "getMIMEType"
+#define DOWNLOAD_FUNCTION_API_SET_LISTENER "setListener"
+
+#endif
diff --git a/src/Download/plugin_initializer.cpp b/src/Download/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..f6ee03b
--- /dev/null
@@ -0,0 +1,130 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+#include <Security.h>
+
+#include "JSDownloadManager.h"
+#include "JSDownloadRequest.h"
+#include "DownloadManager.h"
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Download {
+
+AceSecurityStatus downloadAceCheckAccessFunction(const char* functionName)
+{
+    return DOWNLOAD_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerDownloadSetter,
+                                DownloadManager,
+                                gSecurityAccessor);
+
+class_definition_options_t ClassOptions =
+{
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerDownloadSetter,
+    NULL,
+    NULL
+};
+
+class_definition_options_t DownloadRequestOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Download] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, downloadAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Download] on_widget_stop_callback (%d)", widgetId);
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"Download");
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Download] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Download] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+
+    DownloadManager::getInstance()->cancelAll();
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "download",
+        (js_class_template_getter)JSDownloadManager::getClassRef,
+        &ClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "DownloadRequest",
+        (js_class_template_getter)JSDownloadRequest::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSDownloadRequest::constructor),
+        &DownloadRequestOptions)
+PLUGIN_CLASS_MAP_END
+
+}
+}
+
diff --git a/src/Exif/CMakeLists.txt b/src/Exif/CMakeLists.txt
new file mode 100644 (file)
index 0000000..63e2711
--- /dev/null
@@ -0,0 +1,72 @@
+SET(TARGET_NAME ${exif_target})
+SET(DESTINATION_NAME ${exif_dest})
+SET(TARGET_IMPL_NAME ${exif_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_exif REQUIRED libexif)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+SET(INCLUDE_DIRS
+    ${filesystem_include}
+    ${timeutil_include}
+    ${tizen_include}
+    ${platform_pkgs_exif_INCLUDE_DIRS}
+)
+
+INCLUDE_DIRECTORIES(${INCLUDE_COMMON} ${INCLUDE_DIRS})
+MESSAGE(STATUS "${TARGET_NAME} module includes: INCLUDE_COMMON ${INCLUDE_DIRS}")
+
+SET(CMAKE_INSTALL_RPATH
+
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${filesystem_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${timeutil_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSExifManager.cpp
+    ExifManager.cpp
+    JSExifInformation.cpp
+    ExifInformation.cpp
+    ExifManagerCallbacks.cpp
+    ExifUtil.cpp
+    ExifTagSaver.cpp
+    ExifGPSLocation.cpp
+    ExifGPSTime.cpp
+    Rational.cpp
+    JpegFile.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+SET(LINK_LIBS
+    ${tizen_impl}
+    ${timeutil_impl}
+    ${filesystem_impl}
+    ${filesystem_config}
+    ${platform_pkgs_exif_LIBRARIES}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME} ${LIBS_COMMON} ${LINK_LIBS})
+MESSAGE(STATUS "${TARGET_NAME} module links: LIBS_COMMON ${LINK_LIBS}")
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/exif
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Exif/ExifGPSLocation.cpp b/src/Exif/ExifGPSLocation.cpp
new file mode 100644 (file)
index 0000000..b1b2b49
--- /dev/null
@@ -0,0 +1,299 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ExifGPSLocation.h"
+
+#include <sstream>
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Exif {
+
+GCSPosition::GCSPosition()
+{
+}
+
+GCSPosition::GCSPosition(Rational _degrees, Rational _minutes, Rational _seconds) :
+        degrees(_degrees),
+        minutes(_minutes),
+        seconds(_seconds)
+{
+}
+
+bool GCSPosition::isValid() const
+{
+    if (!(degrees.isValid() && minutes.isValid() && seconds.isValid())) {
+        return false;
+    }
+
+    if ((degrees.toDouble() > 180.0f) ||
+            (minutes.toDouble() > 60.0f) ||
+            (seconds.toDouble() > 60.0f)) {
+        return false;
+    }
+
+    return toDouble() <= 180.0f;
+}
+
+double GCSPosition::toDouble() const
+{
+    const double degrees_value = degrees.toDouble();
+    const double minutes_value = minutes.toDouble();
+    const double seconds_value = seconds.toDouble();
+    return (degrees_value + (minutes_value/60.0) + (seconds_value/3600.0));
+}
+
+Rationals GCSPosition::toRationalsVector() const
+{
+    Rationals vec;
+    vec.push_back(degrees);
+    vec.push_back(minutes);
+    vec.push_back(seconds);
+    return vec;
+}
+
+std::string GCSPosition::toDebugString() const
+{
+    std::stringstream ss;
+    ss << degrees.toString() << "d ";
+    ss << minutes.toString() << "m ";
+    ss << seconds.toString() << "s";
+    return ss.str();
+}
+
+GCSPosition GCSPosition::createFromDouble(double value)
+{
+    LOGD("Entered value:%f");
+    if (value < 0) {
+        LOGW("Trying to create GCSPosition with double < 0: %f", value);
+        return GCSPosition();
+    }
+
+    if (value > 180.0) {
+        LOGW("Trying to create GCSPosition with double > 180.0: %f", value);
+        return GCSPosition();
+    }
+
+    const double d_degrees = floor(value);
+    double left = value - d_degrees;
+
+    const double d_minutes = floor(left * 60.0);
+    left -= d_minutes / 60.0;
+
+    const double d_seconds = left * 3600.0;
+
+    LOGD("d_degrees:%f d_minutes:%f d_seconds:%f", d_degrees, d_minutes, d_seconds);
+
+    GCSPosition pos;
+    pos.degrees = Rational(static_cast<ExifLong>(d_degrees), 1);
+    pos.minutes = Rational(static_cast<ExifLong>(d_minutes), 1);
+    pos.seconds = Rational::createFromDouble(d_seconds);
+    return pos;
+}
+
+ExifGPSLocation::ExifGPSLocation() :
+        m_longitude_ref(GPS_LOCATION_WEST),
+        m_latitude_ref(GPS_LOCATION_NORTH)
+{
+    for(int i = 0; i < EXIF_GPS_LOCATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES; ++i) {
+        m_is_set[i] = false;
+    }
+}
+
+void ExifGPSLocation::setLongitude(const GCSPosition& longitude)
+{
+    if (!longitude.isValid()) {
+        LOGW("longitude is not valid!");
+        return;
+    }
+
+    m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE] = true;
+    m_longitude = longitude;
+}
+
+const GCSPosition& ExifGPSLocation::getLongitude() const
+{
+    return m_longitude;
+}
+
+void ExifGPSLocation::setLongitudeRef(GPSLocationDirectionLongitude ref)
+{
+    m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE_REF] = true;
+    m_longitude_ref = ref;
+}
+
+GPSLocationDirectionLongitude ExifGPSLocation::getLongitudeRef() const
+{
+    return m_longitude_ref;
+}
+
+void ExifGPSLocation::setLatitude(const GCSPosition& latitude)
+{
+    if (!latitude.isValid()) {
+        LOGW("latitude is not valid!");
+        return;
+    }
+
+    m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE] = true;
+    m_latitude = latitude;
+}
+
+const GCSPosition& ExifGPSLocation::getLatitude() const
+{
+    return m_latitude;
+}
+
+void ExifGPSLocation::setLatitudeRef(GPSLocationDirectionLatitude ref)
+{
+    m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE_REF] = true;
+    m_latitude_ref = ref;
+}
+
+GPSLocationDirectionLatitude ExifGPSLocation::getLatitudeRef() const
+{
+    return m_latitude_ref;
+}
+
+bool ExifGPSLocation::isSet(ExifGPSLocationAttributes attribute) const
+{
+    return m_is_set[attribute];
+}
+
+void ExifGPSLocation::unset(ExifGPSLocationAttributes attribute)
+{
+    m_is_set[attribute] = false;
+}
+
+void ExifGPSLocation::unsetAll()
+{
+    m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE] = false;
+    m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE_REF] = false;
+    m_longitude =  GCSPosition();
+
+    m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE] = false;
+    m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE_REF] = false;
+    m_latitude = GCSPosition();
+}
+
+bool ExifGPSLocation::isComplete() const
+{
+    return m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE] &&
+            m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE_REF] &&
+            m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE] &&
+            m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE_REF];
+}
+
+
+bool ExifGPSLocation::isValid() const
+{
+    return isComplete() && m_latitude.isValid() && m_longitude.isValid();
+}
+
+Tizen::SimpleCoordinatesPtr ExifGPSLocation::getSimpleCoordinates() const
+{
+    if (!isComplete()) {
+        LOGW("Some attributes are not set!");
+        return Tizen::SimpleCoordinatesPtr();
+    }
+
+    if (!isValid()) {
+        LOGW("Some attributes are not valid!");
+        return Tizen::SimpleCoordinatesPtr();
+    }
+
+    const double cur_latitude = getLatitudeValue();
+    const double cur_longitude = getLongitudeValue();
+
+    return Tizen::SimpleCoordinatesPtr(
+            new Tizen::SimpleCoordinates(cur_latitude, cur_longitude));
+}
+
+double ExifGPSLocation::getLongitudeValue() const
+{
+    const double longitude_dir = (m_longitude_ref == GPS_LOCATION_WEST) ? -1.0f : 1.0f;
+    const double longitude = m_longitude.toDouble() * longitude_dir;
+    return longitude;
+}
+
+double ExifGPSLocation::getLatitudeValue() const
+{
+    const double latitude_dir = (m_latitude_ref == GPS_LOCATION_SOUTH) ? -1.0f : 1.0f;
+    const double latitude = m_latitude.toDouble() * latitude_dir;
+    return latitude;
+}
+
+bool ExifGPSLocation::set(Tizen::SimpleCoordinatesPtr scoords)
+{
+    LOGD("Entered");
+    if (!scoords) {
+        LOGW("Trying to set null SimpleCoordinates!");
+        return false;
+    }
+
+    const double longitude = scoords->getLongitude();
+    const double latitude = scoords->getLatitude();
+    bool updateLongitude = true;
+    bool updateLatitude = true;
+
+    if(isComplete()) {
+        updateLatitude = getLatitudeValue() != latitude;
+        updateLongitude = getLongitudeValue() != longitude;
+    }
+
+    LOGD("latitude:%f longitude:%f", latitude, longitude);
+
+    GCSPosition gcs_longitude = GCSPosition::createFromDouble(fabs(longitude));
+    LOGD("gcs_longitude deg:%s min:%s sec:%s", gcs_longitude.degrees.toString().c_str(),
+            gcs_longitude.minutes.toString().c_str(),
+            gcs_longitude.seconds.toString().c_str());
+
+    GCSPosition gcs_latitude = GCSPosition::createFromDouble(fabs(latitude));
+    LOGD("gcs_latitude deg:%s min:%s sec:%s", gcs_latitude.degrees.toString().c_str(),
+            gcs_latitude.minutes.toString().c_str(),
+            gcs_latitude.seconds.toString().c_str());
+
+    if (!gcs_latitude.isValid() || !gcs_longitude.isValid()) {
+        return false;
+    }
+
+    if(updateLongitude) {
+        setLongitude(gcs_longitude);
+        if (longitude >= 0.0) {
+            setLongitudeRef(GPS_LOCATION_EAST);
+        }
+        else {
+            setLongitudeRef(GPS_LOCATION_WEST);
+        }
+    }
+
+    if(updateLatitude) {
+        setLatitude(gcs_latitude);
+        if (latitude >= 0.0) {
+            setLatitudeRef(GPS_LOCATION_NORTH);
+        }
+        else {
+            setLatitudeRef(GPS_LOCATION_SOUTH);
+        }
+    }
+
+    return true;
+}
+
+
+} // Exif
+} // DeviceAPI
diff --git a/src/Exif/ExifGPSLocation.h b/src/Exif/ExifGPSLocation.h
new file mode 100644 (file)
index 0000000..d7aecc7
--- /dev/null
@@ -0,0 +1,147 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_EXIF_EXIF_GPS_LOCATION_H_
+#define __TIZEN_EXIF_EXIF_GPS_LOCATION_H_
+
+#include <string>
+
+#include <SimpleCoordinates.h>
+
+#include "ExifUtil.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+enum GPSLocationDirectionLongitude {
+    GPS_LOCATION_WEST,
+    GPS_LOCATION_EAST
+};
+
+enum GPSLocationDirectionLatitude {
+    GPS_LOCATION_NORTH,
+    GPS_LOCATION_SOUTH
+};
+
+enum ExifGPSLocationAttributes {
+    EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE = 0,
+    EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE_REF,
+    EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE,
+    EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE_REF,
+    EXIF_GPS_LOCATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES
+};
+
+/**
+ * This class represents Global Coordinate System using
+ * three Rational numbers (as stored in Exif)
+ */
+struct GCSPosition
+{
+    GCSPosition();
+    GCSPosition(Rational degrees, Rational minutes, Rational seconds);
+
+    /**
+     * Create GCSPosition from degrees represented as double value
+     */
+    static GCSPosition createFromDouble(double value);
+
+    /**
+     * Verify that all components are valid Rational numbers and
+     * each component is within valid range. Sum of degrees,
+     * minutes and seconds should not be bigger then 180.0
+     */
+    bool isValid() const;
+
+    /**
+     * Return position in degrees
+     */
+    double toDouble() const;
+
+    /**
+     * Return vector of three rationals: dgrees, minutes, seconds
+     */
+    Rationals toRationalsVector() const;
+
+    /**
+     * Return string for debugging purposes
+     */
+    std::string toDebugString() const;
+
+    Rational degrees;
+    Rational minutes;
+    Rational seconds;
+};
+
+class ExifGPSLocation
+{
+public:
+    ExifGPSLocation();
+
+    void setLongitude(const GCSPosition& longitude);
+    const GCSPosition& getLongitude() const;
+
+    void setLongitudeRef(GPSLocationDirectionLongitude ref);
+    GPSLocationDirectionLongitude getLongitudeRef() const;
+
+    void setLatitude(const GCSPosition& latitude);
+    const GCSPosition& getLatitude() const;
+
+    void setLatitudeRef(GPSLocationDirectionLatitude ref);
+    GPSLocationDirectionLatitude getLatitudeRef() const;
+
+    bool isSet(ExifGPSLocationAttributes attribute) const;
+    void unset(ExifGPSLocationAttributes attribute);
+    void unsetAll();
+
+    /**
+     * Returns true only if all components are set.
+     */
+    bool isComplete() const;
+
+    /**
+     * Returns true only if all components are set and valid.
+     */
+    bool isValid() const;
+
+    /**
+     * Returns null pointer if any information is missing or incorrect
+     */
+    Tizen::SimpleCoordinatesPtr getSimpleCoordinates() const;
+
+    /**
+     * Return true if scoords has been set
+     */
+    bool set(Tizen::SimpleCoordinatesPtr scoords);
+
+private:
+
+    double getLongitudeValue() const;
+    double getLatitudeValue() const;
+
+    GCSPosition m_longitude;
+    GPSLocationDirectionLongitude m_longitude_ref;
+
+    GCSPosition m_latitude;
+    GPSLocationDirectionLatitude m_latitude_ref;
+
+    bool m_is_set[EXIF_GPS_LOCATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES];
+};
+
+} // Exif
+} // DeviceAPI
+
+#endif // __TIZEN_EXIF_EXIF_GPS_LOCATION_H_
diff --git a/src/Exif/ExifGPSTime.cpp b/src/Exif/ExifGPSTime.cpp
new file mode 100644 (file)
index 0000000..2c95f24
--- /dev/null
@@ -0,0 +1,273 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ExifGPSTime.h"
+
+#include <iomanip>
+#include <sstream>
+#include <time.h>
+
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace Exif {
+
+bool isValidDateFormat(const std::string& date)
+{
+    //Exif 2.2 spec: "YYYY:MM:DD."
+    //There is no trailig '.' at the end it is just null terminate sign
+    //Example: tag name:GPSDateStamp type:ASCII size:11 components:11 value:2014:06:25
+    //         RAW DATA:[32 30 31 34 3a 30 36 3a 32 35 00]
+
+    if (date.length() != 10) {
+        return false;
+    }
+
+    //"YYYY:MM:DD"
+    // 0123456789
+    //     :  :
+    for(size_t i = 0; i < date.length(); ++i) {
+        const char& cur = date[i];
+
+        if (4 == i || 7 == i) {
+            if (cur != ':') {
+                return false;
+            }
+        }
+        else {
+            if (cur < '0' || cur > '9') {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+bool extractDateFromString(const std::string& date, int& out_year, int& out_month,
+        int& out_day)
+{
+    if (!isValidDateFormat(date)) {
+        return false;
+    }
+
+    if (3 != sscanf(date.c_str(), "%d:%d:%d", &out_year, &out_month, &out_day)) {
+        LOGE("Couldn't parse date string: [%s]", date.c_str());
+        return false;
+    }
+
+    return true;
+}
+
+bool isValidTime(const Rationals& time)
+{
+    return (time.size() >= 3) &&
+            time[0].isValid() &&
+            time[1].isValid() &&
+            time[2].isValid() &&
+            (time[0].nominator % time[0].denominator == 0) &&
+            (time[1].nominator % time[1].denominator == 0) &&
+            (time[2].nominator % time[2].denominator == 0);
+}
+
+ExifGPSTime::ExifGPSTime() :
+        m_time_is_set(false),
+        m_date_is_set(false),
+        m_time_and_date(0)
+{
+    m_time.push_back(Rational());
+    m_time.push_back(Rational());
+    m_time.push_back(Rational());
+}
+
+bool ExifGPSTime::isValid() const
+{
+    return isComplete() && isValidDateFormat(m_date) && isValidTime(m_time);
+}
+
+bool ExifGPSTime::isComplete() const
+{
+    return m_time_is_set && m_date_is_set;
+}
+
+void ExifGPSTime::unsetAll()
+{
+    m_date_is_set = false;
+    m_time_is_set = false;
+}
+
+void ExifGPSTime::setTime(const Rationals& time)
+{
+    if (time.size() < 3) {
+        LOGE("time is not having enought members: %d needed 3!", time.size());
+        return;
+    }
+
+    if (time.size() > 3) {
+        LOGW("time is having more members: %d then needed 3!", time.size());
+    }
+
+    if (!isValidTime(time)) {
+        LOGE("time is invalid: [%s]h [%s]m [%s]s", time[0].toString().c_str(),
+                time[1].toString().c_str(),
+                time[2].toString().c_str());
+        return;
+    }
+
+    //Copy just 3 Rationals
+    m_time_is_set = true;
+    for(size_t i = 0; i < 3 && i < time.size(); ++i) {
+        m_time[i] = time[i];
+    }
+}
+
+const Rationals& ExifGPSTime::getTime() const
+{
+    return m_time;
+}
+
+bool ExifGPSTime::isTimeSet() const
+{
+    return m_time_is_set;
+}
+
+void ExifGPSTime::setDate(const std::string& date)
+{
+    if (!isValidDateFormat(date)) {
+        LOGW("Trying to set incorrect date: [%s]", date.c_str());
+        return;
+    }
+
+    m_date_is_set = true;
+    m_date = date;
+}
+
+const std::string& ExifGPSTime::getDate() const
+{
+    return m_date;
+}
+
+bool ExifGPSTime::isDateSet() const
+{
+    return m_date_is_set;
+}
+
+time_t ExifGPSTime::getDateAndTime() const
+{
+    if (!isValid()) {
+        LOGE("ExifGPSTime object is not valid!");
+        return 0;
+    }
+
+    int year, month, day;
+    if (!extractDateFromString(m_date, year, month, day)) {
+        LOGE("Couldn't extract date from m_date string");
+        return 0;
+    }
+
+    time_t out_time = ExifUtil::convertToTimeT(year, month, day,
+        m_time[0].nominator / m_time[0].denominator,
+        m_time[1].nominator / m_time[1].denominator,
+        m_time[2].nominator / m_time[2].denominator);
+
+    LOGD("[%s] [%s]h [%s]m [%s]s ---> time_t: %d", m_date.c_str(),
+            m_time[0].toString().c_str(),
+            m_time[1].toString().c_str(),
+            m_time[2].toString().c_str(),
+            out_time);
+
+    return out_time;
+}
+
+void ExifGPSTime::setDateAndTime(time_t new_time)
+{
+    int year, month, day, hour, min, sec;
+    ExifUtil::extractFromTimeT(new_time, year, month, day, hour, min, sec);
+
+    std::stringstream new_date_ss;
+    new_date_ss << std::setfill('0') << std::setw(4) << year << ':' ;
+    new_date_ss << std::setfill('0') << std::setw(2) << month << ':';
+    new_date_ss << std::setfill('0') << std::setw(2) << day;
+    m_date = new_date_ss.str();
+    m_date_is_set = true;
+
+    m_time[0] = Rational(static_cast<ExifLong>(hour), 1);
+    m_time[1] = Rational(static_cast<ExifLong>(min), 1);
+    m_time[2] = Rational(static_cast<ExifLong>(sec), 1);
+    m_time_is_set = true;
+
+    LOGD("time_t: %d ---> [%s] [%s]h [%s]m [%s]s",
+            new_time,
+            m_date.c_str(),
+            m_time[0].toString().c_str(),
+            m_time[1].toString().c_str(),
+            m_time[2].toString().c_str());
+}
+
+Time::TZDatePtr ExifGPSTime::getTZDate() const
+{
+    if(!isValid()) {
+        LOGW("ExifGPSTime is not valid");
+        return Time::TZDatePtr();
+    }
+
+    int year, month, day;
+    extractDateFromString(m_date, year, month, day);
+
+    const int hour = static_cast<int>(m_time[0].nominator / m_time[0].denominator);
+    const int min = static_cast<int>(m_time[1].nominator / m_time[1].denominator);
+    const int sec = static_cast<int>(m_time[2].nominator / m_time[2].denominator);
+
+    Time::TZDate* new_time = new (std::nothrow) Time::TZDate(year, month-1, day,
+        hour, min, sec, 0, "UTC");
+    if(!new_time) {
+        LOGE("Couldn't create TZDate!");
+        return Time::TZDatePtr();
+    }
+
+    return Time::TZDatePtr(new_time);
+}
+
+void ExifGPSTime::setDateAndTime(Time::TZDatePtr new_time)
+{
+    if(!new_time) {
+        LOGW("TZDate new_time is NULL");
+    }
+
+    std::stringstream new_date_ss;
+    new_date_ss << std::setfill('0') << std::setw(4) << new_time->getUTCFullYear() << ':';
+    new_date_ss << std::setfill('0') << std::setw(2) << new_time->getUTCMonth()+1 << ':';
+    new_date_ss << std::setfill('0') << std::setw(2) << new_time->getUTCDate();
+    m_date = new_date_ss.str();
+    m_date_is_set = true;
+
+    m_time[0] = Rational(static_cast<ExifLong>(new_time->getUTCHours()), 1);
+    m_time[1] = Rational(static_cast<ExifLong>(new_time->getUTCMinutes()), 1);
+    m_time[2] = Rational(static_cast<ExifLong>(new_time->getUTCSeconds()), 1);
+    m_time_is_set = true;
+
+    LOGD("TZDatePtr: %d ---> [%s] [%s]h [%s]m [%s]s",
+            new_time->toString().c_str(),
+            m_date.c_str(),
+            m_time[0].toString().c_str(),
+            m_time[1].toString().c_str(),
+            m_time[2].toString().c_str());
+}
+
+} // Exif
+} // DeviceAPI
diff --git a/src/Exif/ExifGPSTime.h b/src/Exif/ExifGPSTime.h
new file mode 100644 (file)
index 0000000..24f15cd
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_EXIF_EXIF_GPS_TIME_H_
+#define __TIZEN_EXIF_EXIF_GPS_TIME_H_
+
+#include <string>
+
+#include <TZDate.h>
+
+#include "ExifUtil.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+class ExifGPSTime
+{
+public:
+    ExifGPSTime();
+
+    /**
+     * Returns true if both and time is set and valid
+     */
+    bool isValid() const;
+
+    /**
+     * Returns true if both date and time has been set
+     */
+    bool isComplete() const;
+
+    /**
+     * Unset both date and time
+     */
+    void unsetAll();
+
+    void setTime(const Rationals& date);
+    const Rationals& getTime() const;
+    bool isTimeSet() const;
+
+    void setDate(const std::string& date);
+    const std::string& getDate() const;
+    bool isDateSet() const;
+
+    time_t getDateAndTime() const;
+    void setDateAndTime(time_t new_time);
+
+    /**
+     * Returns NULL pointer if this ExifGPSTime is not valid
+     */
+    Time::TZDatePtr getTZDate() const;
+
+    /**
+     * If new_time is NULL nothing is done
+     */
+    void setDateAndTime(Time::TZDatePtr new_time);
+
+private:
+    Rationals m_time;
+    bool m_time_is_set;
+
+    std::string m_date;
+    bool m_date_is_set;
+
+    time_t m_time_and_date;
+};
+
+} // Exif
+} // DeviceAPI
+
+#endif // __TIZEN_EXIF_EXIF_GPS_TIME_H_
diff --git a/src/Exif/ExifInformation.cpp b/src/Exif/ExifInformation.cpp
new file mode 100644 (file)
index 0000000..9447c73
--- /dev/null
@@ -0,0 +1,1358 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ExifInformation.h"
+
+
+#include <memory>
+
+#include <Logger.h>
+#include <PlatformException.h>
+
+#include "ExifTagSaver.h"
+#include "ExifUtil.h"
+#include "JpegFile.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Exif {
+
+const size_t EXIF_UNDEFINED_TYPE_LENGTH = 8;
+const std::string EXIF_UNDEFINED_TYPE_ASCII =
+        std::string("ASCII\0\0\0", EXIF_UNDEFINED_TYPE_LENGTH);
+const std::string EXIF_UNDEFINED_TYPE_JIS =
+        std::string("JIS\0\0\0\0\0", EXIF_UNDEFINED_TYPE_LENGTH);
+const std::string EXIF_UNDEFINED_TYPE_UNICODE =
+        std::string("UNICODE\0", EXIF_UNDEFINED_TYPE_LENGTH);
+const std::string EXIF_UNDEFINED_TYPE_UNDEFINED =
+        std::string("\0\0\0\0\0\0\0\0", EXIF_UNDEFINED_TYPE_LENGTH);
+
+ExifInformation::ExifInformation()
+{
+    for (int attr = 0; attr < EXIF_INFORMATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES; attr++) {
+        unset(static_cast<ExifInformationAttribute>(attr));
+    }
+}
+
+ExifInformation::~ExifInformation()
+{
+}
+
+const std::string& ExifInformation::getUri()
+{
+    LOGD("Entered");
+    return m_uri;
+}
+
+void ExifInformation::setUri(const std::string& uri)
+{
+    LOGD("Entered");
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_URI] = true;
+    m_uri = uri;
+}
+
+unsigned long ExifInformation::getWidth() const
+{
+    LOGD("Entered");
+    return m_width;
+}
+
+void ExifInformation::setWidth(unsigned long width)
+{
+    LOGD("Entered");
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_WIDTH] = true;
+    m_width = width;
+}
+
+unsigned long ExifInformation::getHeight() const
+{
+    LOGD("Entered");
+    return m_height;
+}
+
+void ExifInformation::setHeight(unsigned long height)
+{
+    LOGD("Entered");
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_HEIGHT] = true;
+    m_height = height;
+}
+
+const std::string& ExifInformation::getDeviceMaker()
+{
+    LOGD("Entered");
+    return m_device_maker;
+}
+
+void ExifInformation::setDeviceMaker(const std::string& device_maker)
+{
+    LOGD("Entered");
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER] = true;
+    m_device_maker = device_maker;
+}
+
+const std::string& ExifInformation::getDeviceModel()
+{
+    LOGD("Entered");
+    return m_device_model;
+}
+
+void ExifInformation::setDeviceModel(const std::string& device_model)
+{
+    LOGD("Entered");
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL] = true;
+    m_device_model = device_model;
+}
+
+time_t ExifInformation::getOriginalTime() const
+{
+    LOGD("Entered");
+    return m_original_time;
+}
+
+void ExifInformation::setOriginalTime(time_t original_time)
+{
+    LOGD("Entered");
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_ORIGINAL_TIME] = true;
+    m_original_time = original_time;
+}
+
+ImageOrientation ExifInformation::getOrientation() const
+{
+    LOGD("Entered");
+    return m_orientation;
+}
+
+void ExifInformation::setOrientation(ImageOrientation orientation)
+{
+    LOGD("Entered");
+    if(EXIF_ORIENTATION_NOT_VALID == orientation) {
+        LOGW("Trying to set NOT VALID orientation");
+        return;
+    }
+
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_ORIENTATION] = true;
+    m_orientation = orientation;
+}
+
+const Rational& ExifInformation::getFNumber() const
+{
+    LOGD("Entered");
+    return m_f_number;
+}
+
+void ExifInformation::setFNumber(Rational f_number)
+{
+    LOGD("Entered");
+    if(!f_number.isValid()) {
+        LOGW("Trying to set invalid F-Number: %s", f_number.toString().c_str());
+        return;
+    }
+
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_FNUMBER] = true;
+    m_f_number = f_number;
+}
+
+Common::JSLongLongVector ExifInformation::getIsoSpeedRatings()
+{
+    LOGD("Entered");
+    return m_iso_speed_ratings;
+}
+
+void ExifInformation::setIsoSpeedRatings(
+        const std::vector<long long int>& iso_speed_ratings)
+{
+    LOGD("Entered");
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS] = true;
+    m_iso_speed_ratings = iso_speed_ratings;
+}
+
+void ExifInformation::appendIsoSpeedRatings(long long int iso_speed_rating)
+{
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS] = true;
+    m_iso_speed_ratings.push_back(iso_speed_rating);
+}
+
+const Rational& ExifInformation::getExposureTime()
+{
+    LOGD("Entered");
+    return m_exposure_time;
+}
+
+void ExifInformation::setExposureTime(const Rational& exposure_time)
+{
+    LOGD("Entered");
+    if (!exposure_time.isValid() || 0 == exposure_time.nominator) {
+        LOGW("Trying to set invalid exposure time: [%s]",
+                exposure_time.toString().c_str());
+        return;
+    }
+
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_TIME] = true;
+    m_exposure_time = exposure_time;
+}
+
+ExposureProgram ExifInformation::getExposureProgram()
+{
+    LOGD("Entered");
+    return m_exposure_program;
+}
+
+void ExifInformation::setExposureProgram(ExposureProgram exposure_program)
+{
+    LOGD("Entered");
+    if (EXIF_EXPOSURE_PROGRAM_NOT_VALID == exposure_program) {
+        LOGW("Trying to set NOT VALID exposure program");
+        return;
+    }
+
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_PROGRAM] = true;
+    m_exposure_program = exposure_program;
+}
+
+bool ExifInformation::getFlash() const
+{
+    LOGD("Entered");
+    return m_flash;
+}
+
+void ExifInformation::setFlash(bool flash)
+{
+    LOGD("Entered");
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_FLASH] = true;
+    m_flash = flash;
+}
+
+const Rational& ExifInformation::getFocalLength() const
+{
+    LOGD("Entered");
+    return m_focal_length;
+}
+
+void ExifInformation::setFocalLength(Rational focal_length)
+{
+    LOGD("Entered");
+    if(!focal_length.isValid()) {
+        LOGW("Trying to set invalid focal length: %s", focal_length.toString().c_str());
+        return;
+    }
+
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_FOCAL_LENGTH] = true;
+    m_focal_length = focal_length;
+}
+
+WhiteBalanceMode ExifInformation::getWhiteBalanceMode() const
+{
+    LOGD("Entered");
+    return m_white_balance;
+}
+
+void ExifInformation::setWhiteBalanceMode(WhiteBalanceMode white_balance)
+{
+    LOGD("Entered");
+    if (EXIF_WHITE_BALANCE_MODE_NOT_VALID == white_balance) {
+        LOGW("Trying to set NOT VALID white balance mode");
+        return;
+    }
+
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_WHITE_BALANCE] = true;
+    m_white_balance = white_balance;
+}
+
+ExifGPSLocation& ExifInformation::getGPSExifLocation()
+{
+    return m_exif_gps_location;
+}
+
+Tizen::SimpleCoordinatesPtr ExifInformation::getGPSLocation()
+{
+    if(m_gps_location) {
+        return m_gps_location;
+    }
+
+
+    Tizen::SimpleCoordinatesPtr nscoords = m_exif_gps_location.getSimpleCoordinates();
+    if(!nscoords) {
+        return nscoords;
+    }
+
+    m_gps_location = nscoords;
+    return m_gps_location;
+}
+
+void ExifInformation::setGPSLocation(Tizen::SimpleCoordinatesPtr gps_location)
+{
+    if(!gps_location) {
+        LOGW("Trying to set NULL gps location!");
+        return;
+    }
+
+    m_gps_location = gps_location;
+}
+
+void ExifInformation::unsetGPSLocation()
+{
+    m_gps_location = Tizen::SimpleCoordinatesPtr();
+    m_exif_gps_location.unsetAll();
+}
+
+const Rational& ExifInformation::getGpsAltitude() const
+{
+    LOGD("Entered");
+    return m_gps_altitude;
+}
+
+void ExifInformation::setGpsAltitude(Rational gps_altitude)
+{
+    LOGD("Entered");
+    if(!gps_altitude.isValid()) {
+        LOGW("Trying to set invalid gps altitude: %s", gps_altitude.toString().c_str());
+        return;
+    }
+
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE] = true;
+    m_gps_altitude = gps_altitude;
+}
+
+GpsAltitudeRef ExifInformation::getGpsAltitudeRef() const
+{
+    LOGD("Entered");
+    return m_gps_altitude_ref;
+}
+
+void ExifInformation::setGpsAltitudeRef(const GpsAltitudeRef ref)
+{
+    LOGD("Entered");
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE_REF] = true;
+    m_gps_altitude_ref = ref;
+}
+
+void ExifInformation::setGpsAltitudeWithRef(double gps_altitude)
+{
+    LOGD("Entered");
+    setGpsAltitude(Rational::createFromDouble(fabs(gps_altitude)));
+
+    if(gps_altitude >= 0.0) {
+        setGpsAltitudeRef(GPS_ALTITUDE_REF_ABOVE_SEA);
+    } else {
+        setGpsAltitudeRef(GPS_ALTITUDE_REF_BELOW_SEA);
+    }
+
+}
+
+double ExifInformation::getGpsAltitudeWithRef() const
+{
+    LOGD("Entered");
+
+    if(!m_is_set[EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE_REF] ||
+            GPS_ALTITUDE_REF_ABOVE_SEA == m_gps_altitude_ref) {
+        return m_gps_altitude.toDouble();
+    } else {
+        return -1.0 * m_gps_altitude.toDouble();
+    }
+}
+
+const std::string& ExifInformation::getGpsProcessingMethod() const
+{
+    LOGD("Entered");
+    return m_gps_processing_method;
+}
+
+const std::string& ExifInformation::getGpsProcessingMethodType() const
+{
+    LOGD("Entered");
+    return m_gps_processing_method_type;
+}
+
+void ExifInformation::setGpsProcessingMethod(const std::string& type,
+        const std::string& processing_method)
+{
+    LOGD("Entered");
+    if(type != EXIF_UNDEFINED_TYPE_ASCII &&
+            type != EXIF_UNDEFINED_TYPE_JIS &&
+            type != EXIF_UNDEFINED_TYPE_UNICODE &&
+            type != EXIF_UNDEFINED_TYPE_UNDEFINED) {
+        LOGW("Trying to set invalid GPSProcessingMethod type: [%s] len:%d",
+                type.c_str(), type.length());
+        return;
+    }
+
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD] = true;
+    m_gps_processing_method = processing_method;
+    m_gps_processing_method_type = type;
+}
+
+ExifGPSTime& ExifInformation::getExifGpsTime()
+{
+    return m_exif_gps_time;
+}
+
+const ExifGPSTime& ExifInformation::getExifGpsTime() const
+{
+    return m_exif_gps_time;
+}
+
+Time::TZDatePtr ExifInformation::getGpsTime()
+{
+    if(m_gps_time) {
+        return m_gps_time;
+    }
+
+    if(!m_exif_gps_time.isValid()) {
+        return Time::TZDatePtr();
+    }
+
+
+    m_gps_time = m_exif_gps_time.getTZDate();
+    return m_gps_time;
+}
+
+void ExifInformation::setGpsTime(Time::TZDatePtr new_time)
+{
+    if(!new_time) {
+        LOGW("Trying to set null new_time!");
+        return;
+    }
+
+    m_gps_time = new_time;
+}
+
+void ExifInformation::unsetGPStime()
+{
+    m_exif_gps_time.unsetAll();
+    m_gps_time = NULL;
+}
+
+
+const std::string& ExifInformation::getUserComment()
+{
+    LOGD("Entered");
+    return m_user_comment;
+}
+
+const std::string& ExifInformation::getUserCommentType()
+{
+    LOGD("Entered");
+    return m_user_comment_type;
+}
+
+void ExifInformation::setUserComment(const std::string& type,
+        const std::string& user_comment)
+{
+    LOGD("Entered");
+    if(type != EXIF_UNDEFINED_TYPE_ASCII &&
+            type != EXIF_UNDEFINED_TYPE_JIS &&
+            type != EXIF_UNDEFINED_TYPE_UNICODE &&
+            type != EXIF_UNDEFINED_TYPE_UNDEFINED) {
+        LOGW("Trying to set invalid user comment type: [%s] len:%d",
+                type.c_str(), type.length());
+        return;
+    }
+
+    m_is_set[EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT] = true;
+    m_user_comment_type = type;
+    m_user_comment = user_comment;
+}
+
+bool ExifInformation::isSet(ExifInformationAttribute attribute) const
+{
+    LOGD("Entered");
+    return m_is_set[attribute];
+}
+
+void ExifInformation::unset(ExifInformationAttribute attribute)
+{
+    LOGD("Entered");
+    if(attribute >= EXIF_INFORMATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES) {
+        return;
+    }
+
+    m_is_set[attribute] = false;
+    switch (attribute) {
+        case EXIF_INFORMATION_ATTRIBUTE_URI:
+            m_uri = std::string();
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_WIDTH:
+            m_width = 0;
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_HEIGHT:
+            m_height = 0;
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER:
+            m_device_maker = std::string();
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL:
+            m_device_model = std::string();
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_ORIGINAL_TIME:
+            m_original_time = 0;
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_ORIENTATION:
+            m_orientation = EXIF_ORIENTATION_NOT_VALID;
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_FNUMBER:
+            m_f_number = Rational::createInvalid();
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS:
+            m_iso_speed_ratings = std::vector<long long int>();
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_TIME:
+            m_exposure_time = Rational::createInvalid();
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_PROGRAM:
+            m_exposure_program = EXIF_EXPOSURE_PROGRAM_NOT_VALID;
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_FLASH:
+            m_flash = false;
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_FOCAL_LENGTH:
+            m_focal_length = Rational::createInvalid();
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_WHITE_BALANCE:
+            m_white_balance = EXIF_WHITE_BALANCE_MODE_NOT_VALID;
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE:
+            m_gps_altitude = Rational::createInvalid();
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE_REF:
+            m_gps_altitude_ref = GPS_ALTITUDE_REF_ABOVE_SEA;
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD:
+            m_gps_processing_method = std::string();
+            m_gps_processing_method_type = EXIF_UNDEFINED_TYPE_ASCII;
+            break;
+        case EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT:
+            m_user_comment = std::string();
+            m_user_comment_type = EXIF_UNDEFINED_TYPE_ASCII;
+            break;
+        default:
+            break;
+    }
+}
+
+bool getGCSPositionFromEntry(ExifEntry *entry, ExifData* exif_data, GCSPosition& out_pos)
+{
+    //RATIONAL - 3
+    if (EXIF_FORMAT_RATIONAL == entry->format &&
+            entry->components >= 3 &&
+            entry->data) {
+        const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+        out_pos.degrees = Rational(exif_get_rational(entry->data, order));
+        out_pos.minutes = Rational(exif_get_rational(
+                entry->data +   ExifTypeInfo::RationalSize, order));
+        out_pos.seconds = Rational(exif_get_rational(
+                entry->data + 2*ExifTypeInfo::RationalSize, order));
+        return true;
+    }
+    else {
+        return false;
+    }
+}
+
+bool getRationalsFromEntry(ExifEntry *entry, ExifData* exif_data,
+            unsigned long required_count, Rationals& out_rationals)
+{
+    if (EXIF_FORMAT_RATIONAL == entry->format &&
+            entry->components >= required_count &&
+            entry->data) {
+        const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+        unsigned char* ptr = entry->data;
+
+        for(unsigned long i = 0; i < required_count; ++i) {
+            out_rationals.push_back(Rational(exif_get_rational(ptr, order)));
+            ptr += ExifTypeInfo::RationalSize;
+        }
+
+        return true;
+    }
+    else {
+        return false;
+    }
+}
+
+Rational getRationalFromEntry(ExifEntry *entry, ExifData* exif_data)
+{
+    if (EXIF_FORMAT_RATIONAL == entry->format && entry->components >= 1 && entry->data) {
+        const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+        return Rational(exif_get_rational(entry->data, order));
+    }
+    else {
+        return Rational::createInvalid();
+    }
+}
+
+bool decomposeExifUndefined(ExifEntry* entry, std::string& type, std::string& value)
+{
+    if(!entry || !entry->data) {
+        LOGW("exif entry is NULL/empty");
+        return false;
+    }
+
+    if(entry->size < EXIF_UNDEFINED_TYPE_LENGTH) {
+        LOGW("entry size is invalid %d < EXIF_UNDEFINED_TYPE_LENGTH", entry->size);
+        return false;
+    }
+
+    const char* ptr = reinterpret_cast<const char*>(entry->data);
+    type = std::string(ptr, EXIF_UNDEFINED_TYPE_LENGTH);
+    ptr += EXIF_UNDEFINED_TYPE_LENGTH;
+    value = std::string(ptr, entry->size - EXIF_UNDEFINED_TYPE_LENGTH);
+    return true;
+}
+
+void ExifInformation::processEntry(ExifEntry* entry, ExifData* exif_data)
+{
+    char buf[2000];
+    exif_entry_get_value(entry, buf, sizeof(buf));
+    ExifUtil::printExifEntryInfo(entry, exif_data);
+
+    const ExifIfd cur_ifd = exif_entry_get_ifd(entry);
+    if (EXIF_IFD_INTEROPERABILITY == cur_ifd || EXIF_IFD_1 == cur_ifd) {
+        return;
+    }
+
+    switch (static_cast<unsigned int>(entry->tag)) {
+        case EXIF_TAG_IMAGE_WIDTH: {
+            //SHORT or LONG - 1
+            exif_entry_get_value(entry, buf, sizeof(buf));
+            LOGD( "Setting ExifInformation width to: [%s]", buf );
+            setWidth(atol(buf));
+            break;
+        }
+        case EXIF_TAG_IMAGE_LENGTH: {
+            //SHORT or LONG - 1
+            exif_entry_get_value(entry, buf, sizeof(buf));
+            LOGD( "Setting ExifInformation height to: [%s]", buf );
+            setHeight(atol(buf));
+            break;
+        }
+        case EXIF_TAG_MAKE: {
+            //ASCII - Any
+            exif_entry_get_value(entry, buf, sizeof(buf));
+            LOGD( "Setting ExifInformation maker to: [%s]", buf );
+            setDeviceMaker(std::string(buf));
+            break;
+        }
+        case EXIF_TAG_MODEL: {
+            //ASCII - Any
+            exif_entry_get_value(entry, buf, sizeof(buf));
+            LOGD( "Setting ExifInformation model to: [%s]", buf );
+            setDeviceModel(std::string(buf));
+            break;
+        }
+        case EXIF_TAG_DATE_TIME_ORIGINAL: {
+            //ASCII - 20
+            exif_entry_get_value(entry, buf, sizeof(buf));
+            const time_t time = ExifUtil::exifDateTimeOriginalToTimeT(
+                    reinterpret_cast<const char*>(entry->data));
+            LOGD( "Setting ExifInformation time original to: [%s] time_t:%d", buf,
+                    (int)time);
+            setOriginalTime(time);
+            break;
+        }
+        case EXIF_TAG_ORIENTATION: {
+            //SHORT - 1
+            exif_entry_get_value(entry, buf, sizeof(buf));
+            const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+            const ExifShort orient(exif_get_short(entry->data, order));
+
+            if(orient < EXIF_ORIENTATION_NORMAL || orient >= EXIF_ORIENTATION_NOT_VALID) {
+                LOGW("Couldn't set ExifInformation - orientation is not valid: %d (%s)",
+                        orient, buf);
+            }
+            else {
+                LOGD("Setting ExifInformation orientation to: %d [%s]", orient, buf);
+                setOrientation(static_cast<ImageOrientation>(orient));
+            }
+            break;
+        }
+        case EXIF_TAG_FNUMBER:
+        {
+            //RATIONAL - 1
+            Rational fnumber = getRationalFromEntry(entry, exif_data);
+            if(fnumber.isValid()) {
+                LOGD("Setting ExifInformation fnumber to: %f (%s)", fnumber.toDouble(),
+                    fnumber.toString().c_str());
+                setFNumber(fnumber);
+            }
+            else {
+                LOGW("Couldn't set ExifInformation - fnumber is not valid: %s",
+                        fnumber.toString().c_str());
+            }
+            break;
+        }
+        case EXIF_TAG_ISO_SPEED_RATINGS: {
+            //SHORT - Any
+            if (EXIF_FORMAT_SHORT == entry->format &&
+                    entry->components > 0 &&
+                    entry->data) {
+                const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+                unsigned char* read_ptr = entry->data;
+                const size_t size_per_member =
+                        ExifUtil::getSizeOfExifFormatType(entry->format);
+
+                for(unsigned long i = 0; i < entry->components; ++i) {
+                    ExifShort iso_rating = exif_get_short(read_ptr, order);
+                    appendIsoSpeedRatings(iso_rating);
+
+                    LOGD("Appending ExifInformation speed ratings with: %d",
+                            static_cast<int>(iso_rating));
+
+                    read_ptr += size_per_member;
+                }
+            }
+            else {
+                LOGE("iso speed ratings: format or components count is invalid!");
+            }
+            break;
+        }
+        case EXIF_TAG_EXPOSURE_TIME: {
+            //RATIONAL - 1
+            if (EXIF_FORMAT_RATIONAL == entry->format &&
+                    entry->components > 0 &&
+                    entry->data) {
+
+                const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+                const Rational exp_time(exif_get_rational(entry->data, order));
+
+                if (exp_time.isValid()) {
+                    LOGD("Setting ExifInformation exposure time to: %s (%s)",
+                            exp_time.toString().c_str(),
+                            exp_time.toExposureTimeString().c_str());
+                    setExposureTime(exp_time);
+                }
+                else {
+                    LOGD("Couldn't set ExifInformation - exposure time is not valid: %s",
+                            exp_time.toString().c_str());
+                }
+            }
+            else {
+                LOGE("exposure time: format or components count is invalid!");
+            }
+            break;
+        }
+        case EXIF_TAG_EXPOSURE_PROGRAM: {
+            //SHORT - 1
+            exif_entry_get_value(entry, buf, sizeof(buf));
+
+            const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+            const ExifShort exp_program = exif_get_short(entry->data, order);
+            if(exp_program >= EXIF_EXPOSURE_PROGRAM_NOT_VALID) {
+                LOGW("ExposureProgram: %d (%s) is not valid!", exp_program, buf);
+            }
+            else {
+                LOGD("Setting ExifInformation exposure program to: %d [%s]",
+                        exp_program, buf );
+                setExposureProgram(static_cast<ExposureProgram>(exp_program));
+            }
+            break;
+        }
+        case EXIF_TAG_FLASH: {
+            //SHORT - 1
+            exif_entry_get_value(entry, buf, sizeof(buf));
+
+            const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+            const ExifShort flash = exif_get_short(entry->data, order);
+
+            LOGD( "Setting ExifInformation flash to: [%s] flash=%d", buf, flash);
+            setFlash(flash != 0);
+            break;
+        }
+        case EXIF_TAG_FOCAL_LENGTH: {
+            //RATIONAL - 1
+            Rational flength = getRationalFromEntry(entry, exif_data);
+            if(flength.isValid()) {
+                LOGD("Setting ExifInformation focal length to: %f (%s)",
+                        flength.toDouble(), flength.toString().c_str());
+                setFocalLength(flength);
+            }
+            else {
+                LOGW("Couldn't set ExifInformation - focal length is not valid: %s",
+                        flength.toString().c_str());
+            }
+            break;
+        }
+        case EXIF_TAG_WHITE_BALANCE: {
+            //SHORT - 1
+            exif_entry_get_value(entry, buf, sizeof(buf));
+
+            const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+            const ExifShort wb_raw = exif_get_short(entry->data, order);
+            const bool manual_mode = (wb_raw == 1);
+
+            LOGD("Setting ExifInformation white balance to: [%s] wb_raw:%d -> %s", buf,
+                    wb_raw, manual_mode ? "manual" : "auto");
+
+            if (manual_mode) {
+                setWhiteBalanceMode(EXIF_WHITE_BALANCE_MODE_MANUAL);
+            }
+            else {
+                setWhiteBalanceMode(EXIF_WHITE_BALANCE_MODE_AUTO);
+            }
+            break;
+        }
+        case EXIF_TAG_GPS_LONGITUDE: {
+            //RATIONAL - 3
+            GCSPosition longitude;
+            if (getGCSPositionFromEntry(entry, exif_data, longitude)) {
+                m_exif_gps_location.setLongitude(longitude);
+                LOGD("Setting ExifInformation gps longitude to: %s; %s; %s valid:%d",
+                        longitude.degrees.toString().c_str(),
+                        longitude.minutes.toString().c_str(),
+                        longitude.seconds.toString().c_str(),
+                        longitude.isValid());
+            }
+            else {
+                exif_entry_get_value(entry, buf, sizeof(buf));
+                LOGW("Couldn't set longitude pos - data is not valid: [%s]", buf);
+            }
+            break;
+        }
+        case EXIF_TAG_GPS_LONGITUDE_REF: {
+            //ASCII - 2
+            if(entry->size < 1) {
+                LOGW("Longtitude ref entry do not contain enought data!");
+                break;
+            }
+
+            const char ref = static_cast<char>(entry->data[0]);
+            if ('E' == ref || 'e' == ref) {          //East
+                m_exif_gps_location.setLongitudeRef(GPS_LOCATION_EAST);
+                LOGD("Setting ExifInformation gps longitude REF to: EAST");
+            }
+            else if ('W' == ref || 'w' == ref) {     //West
+                m_exif_gps_location.setLongitudeRef(GPS_LOCATION_WEST);
+                LOGD("Setting ExifInformation gps longitude REF to: WEST");
+            }
+            else {
+                LOGW("Unknown longitude ref: %c (0x%x)", ref, static_cast<int>(ref));
+            }
+            break;
+        }
+        case EXIF_TAG_GPS_LATITUDE: {
+            //RATIONAL - 3
+            exif_entry_get_value(entry, buf, sizeof(buf));
+            LOGD( "Setting ExifInformation latitude to: [%s], tag->%s",
+                    buf, exif_tag_get_name(entry->tag) );
+
+            GCSPosition latitude;
+            if (getGCSPositionFromEntry(entry, exif_data, latitude)) {
+                m_exif_gps_location.setLatitude(latitude);
+                LOGD("Setting ExifInformation gps latitude to: %s; %s; %s valid:%d",
+                        latitude.degrees.toString().c_str(),
+                        latitude.minutes.toString().c_str(),
+                        latitude.seconds.toString().c_str(),
+                        latitude.isValid());
+            }
+            else {
+                LOGW("Couldn't set latitude pos - data is not valid!");
+            }
+            break;
+        }
+        case EXIF_TAG_GPS_LATITUDE_REF: {
+            //ASCII - 2
+            if(entry->size < 1) {
+                LOGW("Latitude ref entry do not contain enought data!");
+                break;
+            }
+
+            const char ref = static_cast<char>(entry->data[0]);
+            if ('N' == ref || 'n' == ref) {          //North
+                m_exif_gps_location.setLatitudeRef(GPS_LOCATION_NORTH);
+                LOGD("Setting ExifInformation gps latitude REF to: NORTH");
+            }
+            else if ('S' == ref || 's' == ref) {     //South
+                m_exif_gps_location.setLatitudeRef(GPS_LOCATION_SOUTH);
+                LOGD("Setting ExifInformation gps latitude REF to: SOUTH");
+            }
+            else {
+                LOGW("Unknown latitude ref: %c (0x%x)", ref, static_cast<int>(ref));
+            }
+            break;
+        }
+        case EXIF_TAG_GPS_ALTITUDE: {
+            //RATIONAL - 1
+            Rational gps_altitude = getRationalFromEntry(entry, exif_data);
+            if(gps_altitude.isValid()) {
+                LOGD("Setting ExifInformation gps altitude to: %f (%s)",
+                        gps_altitude.toDouble(), gps_altitude.toString().c_str());
+                setGpsAltitude(gps_altitude);
+            }
+            else {
+                LOGW("Couldn't set ExifInformation - gps altitude is not valid: %s",
+                        gps_altitude.toString().c_str());
+            }
+            break;
+        }
+        case EXIF_TAG_GPS_ALTITUDE_REF: {
+            //BYTE - 1
+            const ExifByte altitude_ref = static_cast<ExifByte>(entry->data[0]);
+            if(static_cast<ExifByte>(GPS_ALTITUDE_REF_ABOVE_SEA) == altitude_ref ||
+                    static_cast<ExifByte>(GPS_ALTITUDE_REF_BELOW_SEA) == altitude_ref) {
+                setGpsAltitudeRef(static_cast<GpsAltitudeRef>(altitude_ref));
+                LOGD( "Setting ExifInformation gps altitude ref to: %d (%s)",
+                        static_cast<int>(altitude_ref),
+                        (altitude_ref > 0) ? "below sea" : "above sea");
+            } else {
+                LOGW("GPS altitude ref is invalid:%d should be 0 or 1!",
+                        static_cast<int>(altitude_ref));
+            }
+            break;
+        }
+        case EXIF_TAG_GPS_PROCESSING_METHOD: {
+            //UNDEFINED - Any
+            std::string type, value;
+            if(decomposeExifUndefined(entry, type, value)) {
+                LOGD("Extracted GPSProcessingMethod: [%s], len:%d, type:%s",
+                        value.c_str(), value.length(), type.c_str());
+                setGpsProcessingMethod(type, value);
+
+                LOGD("Setting ExifInformation processing method to: [%s], len:%d, type:%s",
+                        m_gps_processing_method.c_str(),
+                        m_gps_processing_method.length(),
+                        m_gps_processing_method_type.c_str());
+            }
+            else {
+                LOGW("GPSProcessingMethod tag contains invalid values!");
+            }
+            break;
+        }
+        case EXIF_TAG_GPS_DATE_STAMP: {
+            //ASCII - 11
+            exif_entry_get_value(entry, buf, sizeof(buf));
+            LOGD( "Setting ExifInformation gps date stamp to: [%s]", buf );
+            m_exif_gps_time.setDate(buf);
+            break;
+        }
+        case EXIF_TAG_GPS_TIME_STAMP: {
+            //Rational - 3
+            exif_entry_get_value(entry, buf, sizeof(buf));
+            LOGD( "Setting ExifInformation gps time stamp to: [%s]", buf);
+
+            Rationals time;
+            if (getRationalsFromEntry(entry, exif_data, 3, time)) {
+                m_exif_gps_time.setTime(time);
+            }
+            break;
+        }
+        case EXIF_TAG_USER_COMMENT: {
+            //UNDEFINED - Any
+            std::string type, value;
+            if(decomposeExifUndefined(entry, type, value)) {
+                LOGD("Extracted UserComment: [%s], len:%d, type:%s",
+                        value.c_str(), value.length(), type.c_str());
+                setUserComment(type, value);
+
+                LOGD("Setting ExifInformation user comment to: [%s], len:%d, type:%s",
+                        m_user_comment.c_str(),
+                        m_user_comment.length(),
+                        m_user_comment_type.c_str());
+            }
+            else {
+                LOGW("UserComment tag contains invalid values!");
+            }
+
+            break;
+        }
+        default:
+            LOGD("Field of tag:%x.H [%s] is not supported, value: [%s]", entry->tag,
+                    exif_tag_get_name_in_ifd(entry->tag, cur_ifd),
+                    exif_entry_get_value(entry, buf, sizeof(buf)));
+    }
+}
+
+struct ExifInfoAndDataHolder {
+    ExifInformationPtr exif_info;
+    ExifData* exif_data;
+};
+
+void ExifInformation::contentForeachFunctionProxy(ExifEntry *entry, void *user_data)
+{
+    ExifInfoAndDataHolder* holder = static_cast<ExifInfoAndDataHolder*>(user_data);
+    if (!holder) {
+        LOGE("holder is NULL");
+        return;
+    }
+
+    if (!holder->exif_info) {
+        LOGE("exif_info is NULL!");
+        return;
+    }
+
+    if (!holder->exif_data) {
+        LOGE("exif_data is NULL!");
+        return;
+    }
+
+    try {
+        holder->exif_info->processEntry(entry, holder->exif_data);
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("processEntry thrown exception: %s : %s", err.getName().c_str(),
+                    err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while processing Exif entry.");
+    }
+}
+
+void ExifInformation::dataForeachFunction(ExifContent *content, void *user_data)
+{
+    exif_content_foreach_entry(content, contentForeachFunctionProxy, user_data);
+}
+
+
+ExifInformationPtr ExifInformation::loadFromURI(const std::string& uri)
+{
+    ExifInformationPtr exif_info(new ExifInformation());
+    exif_info->setUri(uri);
+
+    const std::string file_path = ExifUtil::convertUriToPath(uri);
+    ExifData* ed = exif_data_new_from_file (file_path.c_str());
+    if (!ed) {
+        LOGE("Error reading exif from file %s", file_path.c_str());
+        throw NotFoundException("Error reading exif from file");
+    }
+
+    LOGD("exif_data_foreach_content START");
+
+    ExifInfoAndDataHolder holder;
+    holder.exif_info = exif_info;
+    holder.exif_data = ed;
+    exif_data_foreach_content(ed, dataForeachFunction, static_cast<void*>(&holder));
+
+    LOGD("exif_data_foreach_content END");
+
+    exif_data_unref(ed);
+    ed = NULL;
+
+    return exif_info;
+}
+
+
+void ExifInformation::removeNulledAttributesFromExifData(ExifData* exif_data)
+{
+    LOGD("Entered");
+    if(!exif_data) {
+        LOGE("exif_data is NULL");
+        throw UnknownException("Invalid Exif provided");
+    }
+
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_WIDTH)) {
+        LOGD("Removing width");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_IMAGE_WIDTH, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_HEIGHT)) {
+        LOGD("Removing height");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_IMAGE_LENGTH, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER)) {
+        LOGD("Removing device maker");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_MAKE, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_ORIENTATION)) {
+        LOGD("Removing orientation");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_ORIENTATION, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_PROGRAM)) {
+        LOGD("Removing exposure program");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_EXPOSURE_PROGRAM, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS)) {
+        LOGD("Removing iso speed ratings");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_ISO_SPEED_RATINGS, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_WHITE_BALANCE)) {
+        LOGD("Removing white balance");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_WHITE_BALANCE, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL)) {
+        LOGD("Removing device model");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_MODEL, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_ORIGINAL_TIME)) {
+        LOGD("Removing original time");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_DATE_TIME_ORIGINAL, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_TIME)) {
+        LOGD("Removing exposure time");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_EXPOSURE_TIME, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_FNUMBER)) {
+        LOGD("Removing f-number");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_FNUMBER, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_FLASH)) {
+        LOGD("Removing flash");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_FLASH, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_FOCAL_LENGTH)) {
+        LOGD("Removing focal length");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_FOCAL_LENGTH, exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE)) {
+        LOGD("Removing gps altitude");
+        ExifTagSaver::removeExifEntryWithTag(
+            static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE), exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE_REF)) {
+        LOGD("Removing gps altitude ref");
+        ExifTagSaver::removeExifEntryWithTag(
+                static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE_REF), exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD)) {
+        LOGD("Removing gps processing method");
+        ExifTagSaver::removeExifEntryWithTag(
+                static_cast<ExifTag>(EXIF_TAG_GPS_PROCESSING_METHOD), exif_data);
+    }
+    if (!isSet(EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT)) {
+        LOGD("Removing user comment");
+        ExifTagSaver::removeExifEntryWithTag(EXIF_TAG_USER_COMMENT, exif_data);
+    }
+
+    if (!m_exif_gps_location.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE)) {
+        LOGD("Removing latitude");
+        ExifTagSaver::removeExifEntryWithTag(
+                static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE), exif_data);
+    }
+    if (!m_exif_gps_location.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE_REF)) {
+        LOGD("Removing latitude ref");
+        ExifTagSaver::removeExifEntryWithTag(
+                static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE_REF), exif_data);
+    }
+    if (!m_exif_gps_location.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE)) {
+        LOGD("Removing longitude");
+        ExifTagSaver::removeExifEntryWithTag(
+                static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE), exif_data);
+    }
+    if (!m_exif_gps_location.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE_REF)) {
+        LOGD("Removing longitude ref");
+        ExifTagSaver::removeExifEntryWithTag(
+                static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE_REF), exif_data);
+    }
+
+    if (!m_exif_gps_time.isTimeSet()) {
+        LOGD("Removing gps time");
+        ExifTagSaver::removeExifEntryWithTag(
+                static_cast<ExifTag>(EXIF_TAG_GPS_TIME_STAMP), exif_data);
+    }
+    if (!m_exif_gps_time.isDateSet()) {
+        LOGD("Removing gps date");
+        ExifTagSaver::removeExifEntryWithTag(
+                static_cast<ExifTag>(EXIF_TAG_GPS_DATE_STAMP), exif_data);
+    }
+}
+
+void ExifInformation::updateAttributesInExifData(ExifData* exif_data)
+{
+    LOGD("Entered");
+    if(!exif_data) {
+        LOGE("exif_data is NULL");
+        throw UnknownException("Invalid Exif provided");
+    }
+
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_WIDTH)) {
+        LOGD("Saving width: %d", getWidth());
+        ExifTagSaver::saveToExif(getWidth(),
+                EXIF_TAG_IMAGE_WIDTH, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_HEIGHT)) {
+        LOGD("Saving height: %d", getHeight());
+        ExifTagSaver::saveToExif(getHeight(),
+                EXIF_TAG_IMAGE_LENGTH, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER)) {
+        LOGD("Saving device maker: %s", getDeviceMaker().c_str());
+        ExifTagSaver::saveToExif(getDeviceMaker(),
+                EXIF_TAG_MAKE, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_ORIENTATION)) {
+        LOGD("Saving orientation: %d", static_cast<int>(getOrientation()));
+        ExifTagSaver::saveToExif(static_cast<long int>(getOrientation()),
+                EXIF_TAG_ORIENTATION, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_PROGRAM)) {
+        LOGD("Saving exposure program: %d", static_cast<int>(getExposureProgram()));
+        ExifTagSaver::saveToExif(getExposureProgram(),
+                EXIF_TAG_EXPOSURE_PROGRAM, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS)) {
+        std::vector<long long int> iso_ratings = getIsoSpeedRatings();
+        LOGD("Saving iso speed ratings count:%d", iso_ratings.size());
+        ExifTagSaver::saveToExif(iso_ratings, EXIF_FORMAT_SHORT,
+                EXIF_TAG_ISO_SPEED_RATINGS, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_WHITE_BALANCE)) {
+        LOGD("Saving white balance: %d", static_cast<int>(getWhiteBalanceMode()));
+        ExifTagSaver::saveToExif(getWhiteBalanceMode(),
+                EXIF_TAG_WHITE_BALANCE, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL)) {
+        LOGD("Saving device model: %s", getDeviceModel().c_str());
+        ExifTagSaver::saveToExif(getDeviceModel(),
+                EXIF_TAG_MODEL, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_ORIGINAL_TIME)) {
+        const time_t o_time = getOriginalTime();
+        const std::string o_time_str = ExifUtil::timeTToExifDateTimeOriginal(o_time);
+        LOGD("Saving original time time_t:%d, format:%s", static_cast<int>(o_time),
+                o_time_str.c_str());
+
+        ExifTagSaver::saveToExif(o_time_str,
+                EXIF_TAG_DATE_TIME_ORIGINAL, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_TIME)) {
+        Rational exposure_time = getExposureTime();
+        if (exposure_time.isValid()) {
+            LOGD("Saving exposure time: %s (%s)",
+                    exposure_time.toString().c_str(),
+                    exposure_time.toExposureTimeString().c_str());
+
+            ExifTagSaver::saveToExif(exposure_time,
+                    EXIF_TAG_EXPOSURE_TIME, exif_data);
+        }
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_FNUMBER)) {
+        auto f_number = getFNumber();
+        LOGD("Saving f-number: %f (%s)", f_number.toDouble(),
+                f_number.toString().c_str());
+        ExifTagSaver::saveToExif(f_number,
+                EXIF_TAG_FNUMBER, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_FLASH)) {
+        LOGD("Saving flash: %s", getFlash() ? "ON" : "OFF");
+        ExifTagSaver::saveToExif(getFlash(),
+                EXIF_TAG_FLASH, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_FOCAL_LENGTH)) {
+        auto f_length = getFocalLength();
+        LOGD("Saving focal length:%f (%s)", f_length.toDouble(),
+                f_length.toString().c_str());
+        ExifTagSaver::saveToExif(f_length,
+                EXIF_TAG_FOCAL_LENGTH, exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE)) {
+        LOGD("Saving gps altitude:%f (%s)", m_gps_altitude.toDouble(),
+                 m_gps_altitude.toString().c_str());
+        ExifTagSaver::saveToExif(m_gps_altitude,
+                static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE), exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE_REF)) {
+        //Exif spec:
+        //0 = Sea level
+        //1 = Sea level reference (negative value)
+        LOGD("Saving gps altitude ref:%d (%s)", static_cast<int>(m_gps_altitude_ref),
+                (m_gps_altitude_ref > 0) ? "below sea" : "above sea");
+        ExifTagSaver::saveToExif(static_cast<long int>(m_gps_altitude_ref),
+                static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE_REF), exif_data);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD)) {
+        LOGD("Saving gps processing method: [%s] type:%s",
+                getGpsProcessingMethod().c_str(), getGpsProcessingMethodType().c_str());
+
+        const std::string joined = getGpsProcessingMethodType() + getGpsProcessingMethod();
+        LOGD("joined: [%s]", joined.c_str());
+
+        ExifTagSaver::saveToExif(joined,
+                static_cast<ExifTag>(EXIF_TAG_GPS_PROCESSING_METHOD), exif_data, false);
+    }
+    if (isSet(EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT)) {
+        LOGD("Saving user comment: %s (type:%s)", getUserComment().c_str(),
+            getUserCommentType().c_str());
+
+        const std::string joined = getUserCommentType() + getUserComment();
+        LOGD("joined: [%s]", joined.c_str());
+
+        ExifTagSaver::saveToExif(joined,
+                EXIF_TAG_USER_COMMENT, exif_data, false);
+    }
+
+    if(m_gps_location) {
+        m_exif_gps_location.set(m_gps_location);
+    }
+    ExifTagSaver::saveGpsLocationToExif(m_exif_gps_location, exif_data);
+
+    if(m_gps_time) {
+        m_exif_gps_time.setDateAndTime(m_gps_time);
+        LOGD("Updated m_exif_gps_time from TZDate: %s to "
+               "date:[%s] time:[%s] [%s] [%s]" ,
+                m_gps_time->toString().c_str(),
+                m_exif_gps_time.getDate().c_str(),
+                m_exif_gps_time.getTime()[0].toString().c_str(),
+                m_exif_gps_time.getTime()[1].toString().c_str(),
+                m_exif_gps_time.getTime()[2].toString().c_str());
+    }
+    ExifTagSaver::saveGpsTimeToExif(m_exif_gps_time, exif_data);
+}
+
+void ExifInformation::saveToFile(const std::string& file_path)
+{
+    LOGD("Entered");
+    LOGD("Using JpegFile to read: [%s] and Exif if present", file_path.c_str());
+
+    bool exif_data_is_new = false;
+    JpegFilePtr jpg_file = JpegFile::loadFile(file_path);
+    ExifData* exif_data = jpg_file->getExifData();
+
+    //Exif is not present in file - create new ExifData
+    if (!exif_data) {
+        LOGD("Exif is not present in file: [%s] creating new", file_path.c_str());
+
+        exif_data = exif_data_new();
+        exif_data_set_option(exif_data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+        exif_data_set_data_type(exif_data, EXIF_DATA_TYPE_COMPRESSED);
+        exif_data_set_byte_order(exif_data, EXIF_BYTE_ORDER_MOTOROLA);
+        exif_data_is_new = true;
+    }
+
+    if (!exif_data) {
+        LOGE("Couldn't allocate new ExifData");
+        throw UnknownException("Memory allocation failed");
+    }
+
+    LOGD("Exif data type: %d", exif_data_get_data_type(exif_data) );
+    LOGD("Exif byte order: %d", exif_data_get_byte_order(exif_data) );
+    exif_data_set_option(exif_data, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION);
+
+    try {
+        //If we have created new ExifData there is nothing to remove
+        if(!exif_data_is_new) {
+            //Remove attributes that have been nulled
+            removeNulledAttributesFromExifData(exif_data);
+        }
+
+        updateAttributesInExifData(exif_data);
+
+        LOGD("Using JpegFile to save new Exif in: [%s]", file_path.c_str());
+        if(exif_data_is_new) {
+            jpg_file->setNewExifData(exif_data);
+        }
+
+        jpg_file->saveToFile(file_path);
+    }
+    catch (...) {
+        exif_data_unref(exif_data);
+        exif_data = NULL;
+        throw;
+    }
+
+    exif_data_unref(exif_data);
+    exif_data = NULL;
+}
+
+} // Exif
+} // DeviceAPI
diff --git a/src/Exif/ExifInformation.h b/src/Exif/ExifInformation.h
new file mode 100644 (file)
index 0000000..400dc86
--- /dev/null
@@ -0,0 +1,210 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_EXIF_EXIFINFORMATION_H_
+#define __TIZEN_EXIF_EXIFINFORMATION_H_
+
+#include <libexif/exif-loader.h>
+#include <string>
+
+#include <JSVector.h>
+#include <TimeDuration.h>
+
+#include "ExifGPSLocation.h"
+#include "ExifGPSTime.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+class ExifInformation;
+typedef std::shared_ptr<ExifInformation> ExifInformationPtr;
+
+extern const size_t EXIF_UNDEFINED_TYPE_LENGTH;
+extern const std::string EXIF_UNDEFINED_TYPE_ASCII;
+extern const std::string EXIF_UNDEFINED_TYPE_JIS;
+extern const std::string EXIF_UNDEFINED_TYPE_UNICODE;
+extern const std::string EXIF_UNDEFINED_TYPE_UNDEFINED;
+
+enum ExifInformationAttribute{
+    EXIF_INFORMATION_ATTRIBUTE_URI,
+    EXIF_INFORMATION_ATTRIBUTE_WIDTH,
+    EXIF_INFORMATION_ATTRIBUTE_HEIGHT,
+    EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER,
+    EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL,
+    EXIF_INFORMATION_ATTRIBUTE_ORIGINAL_TIME,
+    EXIF_INFORMATION_ATTRIBUTE_ORIENTATION,
+    EXIF_INFORMATION_ATTRIBUTE_FNUMBER,
+    EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS,
+    EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_TIME,
+    EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_PROGRAM,
+    EXIF_INFORMATION_ATTRIBUTE_FLASH,
+    EXIF_INFORMATION_ATTRIBUTE_FOCAL_LENGTH,
+    EXIF_INFORMATION_ATTRIBUTE_WHITE_BALANCE,
+    EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE,
+    EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE_REF,
+    EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD,
+    EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT,
+    EXIF_INFORMATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES
+};
+
+enum GpsAltitudeRef {
+    GPS_ALTITUDE_REF_ABOVE_SEA = 0,
+    GPS_ALTITUDE_REF_BELOW_SEA = 1
+};
+
+class ExifInformation
+{
+public:
+    ExifInformation();
+    ~ExifInformation();
+
+    static ExifInformationPtr loadFromURI(const std::string& uri);
+    void saveToFile(const std::string& file_path);
+
+    const std::string& getUri();
+    void setUri(const std::string& uri);
+
+    unsigned long getWidth() const;
+    void setWidth(unsigned long width);
+
+    unsigned long getHeight() const;
+    void setHeight(unsigned long height);
+
+    const std::string& getDeviceMaker();
+    void setDeviceMaker(const std::string& device_maker);
+
+    const std::string& getDeviceModel();
+    void setDeviceModel(const std::string& device_model);
+
+    time_t getOriginalTime() const;
+    void setOriginalTime(time_t original_time);
+
+    ImageOrientation getOrientation() const;
+    void setOrientation(ImageOrientation orientation);
+
+    const Rational& getFNumber() const;
+    void setFNumber(Rational f_number);
+
+    Common::JSLongLongVector getIsoSpeedRatings();
+    void setIsoSpeedRatings(const std::vector<long long int>& iso_speed_ratings);
+    void appendIsoSpeedRatings(long long int iso_speed_rating);
+
+    const Rational& getExposureTime();
+    void setExposureTime(const Rational& exposure_time);
+
+    ExposureProgram getExposureProgram();
+    void setExposureProgram(ExposureProgram exposure_program );
+
+    bool getFlash() const;
+    void setFlash(bool flash);
+
+    const Rational& getFocalLength() const;
+    void setFocalLength(Rational focal_length);
+
+    WhiteBalanceMode getWhiteBalanceMode() const;
+    void setWhiteBalanceMode(WhiteBalanceMode white_balance);
+
+    ExifGPSLocation& getGPSExifLocation();
+    Tizen::SimpleCoordinatesPtr getGPSLocation();
+    void setGPSLocation(Tizen::SimpleCoordinatesPtr gps_location);
+    void unsetGPSLocation();
+
+    const Rational& getGpsAltitude() const;
+    void setGpsAltitude(Rational gps_altitude);
+
+    GpsAltitudeRef getGpsAltitudeRef() const;
+    void setGpsAltitudeRef(const GpsAltitudeRef ref);
+
+    /**
+     * gps_altitude can be negative and positive:
+     * if gps_altitude < 0.0 GPS_ALTITUDE_REF_BELOW_SEA is set
+     * if gps_altitude >= 0.0 GPS_ALTITUDE_REF_ABOVE_SEA is set
+     */
+    void setGpsAltitudeWithRef(double gps_altitude);
+
+    /**
+     * Return gps altitude which can be negative (below sea level) and positive (above sea
+     * level)
+     */
+    double getGpsAltitudeWithRef() const;
+
+    const std::string& getGpsProcessingMethod() const;
+    const std::string& getGpsProcessingMethodType() const;
+    void setGpsProcessingMethod(const std::string& type,
+            const std::string& processing_method);
+
+    ExifGPSTime& getExifGpsTime();
+    const ExifGPSTime& getExifGpsTime() const;
+    Time::TZDatePtr getGpsTime();
+    void setGpsTime(Time::TZDatePtr new_time);
+    void unsetGPStime();
+
+    const std::string& getUserComment();
+    const std::string& getUserCommentType();
+    void setUserComment(const std::string& type,
+            const std::string& user_comment);
+
+    bool isSet(ExifInformationAttribute attribute) const;
+    void unset(ExifInformationAttribute attribute);
+
+private:
+    void processEntry(ExifEntry* entry, ExifData* exif_data);
+    static void contentForeachFunctionProxy(ExifEntry* entry, void* user_data);
+    static void dataForeachFunction(ExifContent* content, void* user_data);
+
+    void removeNulledAttributesFromExifData(ExifData* exif_data);
+    void updateAttributesInExifData(ExifData* exif_data);
+
+    std::string m_uri;
+    unsigned long m_width;
+    unsigned long m_height;
+    std::string m_device_maker;
+    std::string m_device_model;
+
+    time_t m_original_time;
+
+    ImageOrientation m_orientation;
+    Rational m_f_number;
+    Common::JSLongLongVector m_iso_speed_ratings;
+    Rational m_exposure_time;
+    ExposureProgram m_exposure_program;
+    bool m_flash;
+    Rational m_focal_length;
+    WhiteBalanceMode m_white_balance;
+
+    ExifGPSLocation m_exif_gps_location;
+    Tizen::SimpleCoordinatesPtr m_gps_location;
+
+    Rational m_gps_altitude;
+    GpsAltitudeRef m_gps_altitude_ref;
+
+    std::string m_gps_processing_method;
+    std::string m_gps_processing_method_type;
+
+    ExifGPSTime m_exif_gps_time;
+    Time::TZDatePtr m_gps_time;
+
+    std::string m_user_comment;
+    std::string m_user_comment_type;
+
+    bool m_is_set[EXIF_INFORMATION_ATTRIBUTE_NUMBER_OF_ATTRIBUTES];
+};
+
+} // Exif
+} // DeviceAPI
+
+#endif // __TIZEN_EXIF_EXIFINFORMATION_H_
diff --git a/src/Exif/ExifManager.cpp b/src/Exif/ExifManager.cpp
new file mode 100755 (executable)
index 0000000..5f6ef9a
--- /dev/null
@@ -0,0 +1,487 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ExifManager.h"
+
+#include <libexif/exif-loader.h>
+#include <system/device.h>
+
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+
+#include "ExifUtil.h"
+#include "JSExifInformation.h"
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+namespace DeviceAPI {
+namespace Exif {
+
+ExifManager::ExifManager()
+{
+}
+
+ExifManager::~ExifManager()
+{
+}
+
+ExifManager&  ExifManager::getInstance()
+{
+    static ExifManager instance;
+    return instance;
+}
+
+gboolean ExifManager::getExifInfoCompleted(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<ExifInfoCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef error_obj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                    context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(error_obj);
+        }
+        else {
+            JSValueRef js_value = JSExifInformation::makeJSObject(context,
+                    callback->getExifInfo());
+            callback->callSuccessCallback(js_value);
+        }
+    }
+    catch (const Common::BasePlatformException &error) {
+        LOGE("%s (%s)", (error.getName()).c_str(), (error.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occured when calling getExifInfo callback");
+    }
+
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+void verifyThatURIIsFile(const std::string& uri,
+        const std::string& req_permission)
+{
+    if(!ExifUtil::isValidAbsoluteURI(uri)) {
+            LOGE("URI [%s] is not valid absolute URI", uri.c_str());
+            throw InvalidValuesException("URI is not valid");
+    }
+
+    bool exists = false, granted = false;
+    Filesystem::NodeType type = Filesystem::NT_FILE;
+    ExifUtil::getURIInfo(uri, Filesystem::NT_FILE, req_permission, exists, type, granted);
+
+    if(!exists) {
+        LOGE("URI [%s] is not pointing at existing file", uri.c_str());
+        throw NotFoundException("URI is not pointing at existing file");
+    }
+
+    if(type != Filesystem::NT_FILE) {
+        LOGE("URI [%s] is not pointing at file", uri.c_str());
+        throw NotFoundException("URI is not pointing at file");
+    }
+
+    if(!granted) {
+        LOGE("URI [%s] is pointing at file which cannot be accesed (not: %s)",
+                uri.c_str(), req_permission.c_str());
+        throw IOException("URI is pointing at file which cannot be accessed"
+                " - not enough permissions");
+    }
+}
+
+void* ExifManager::getExifInfoThread(void* data)
+{
+    LOGD("Entered");
+    ExifInfoCallbackData* callback = NULL;
+
+    try {
+        callback = static_cast<ExifInfoCallbackData*>(data);
+        if (!callback) {
+            LOGE("Callback is NULL!");
+            return NULL;
+        }
+
+        verifyThatURIIsFile(callback->getUri(), "r");
+        callback->setExifInfo(ExifInformation::loadFromURI(callback->getUri()));
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch (...) {
+        LOGE("Get Exif from file failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Get Exif from file failed");
+    }
+
+    if (0 == g_idle_add(getExifInfoCompleted, static_cast<void*>(callback))) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+void ExifManager::getExifInfo(ExifInfoCallbackData* cbdata)
+{
+    LOGD("Entered");
+    if (!cbdata) {
+        LOGE("cbdata is NULL");
+        throw DeviceAPI::Common::UnknownException("NULL callback error");
+    }
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, getExifInfoThread,
+                static_cast<void*>(cbdata))) {
+        LOGE("Failed to create pthread for getExifInfo()");
+        throw UnknownException("Could not load Exif from file");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for getExifInfo()");
+    }
+}
+
+gboolean ExifManager::saveExifInfoFailed(void* data)
+{
+    LOGD("Entered");
+    std::string uriStr;         
+
+    auto callback = static_cast<CallbackUserData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+            LOGE("invalid uri");
+            JSObjectRef error_obj = Common::JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::INVALID_VALUES_ERROR,"Invalid URI");
+            callback->callErrorCallback(error_obj);
+    }
+    catch (const Common::BasePlatformException &error) {
+        LOGE("%s (%s)", (error.getName()).c_str(), (error.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occured when calling saveExifInfo callback");
+    }
+
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+
+gboolean ExifManager::saveExifInfoCompleted(void* data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<ExifInfoCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef error_obj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                    context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(error_obj);
+        }
+        else {
+            callback->callSuccessCallback();
+        }
+    }
+    catch (const Common::BasePlatformException &error) {
+        LOGE("%s (%s)", (error.getName()).c_str(), (error.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occured when calling saveExifInfo callback");
+    }
+
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+void* ExifManager::saveExifInfoThread(void* data)
+{
+    LOGD("Entered");
+    ExifInfoCallbackData* callback = NULL;
+
+    try {
+        callback = static_cast<ExifInfoCallbackData*>(data);
+        if (!callback) {
+            LOGE("Callback is NULL!");
+            return NULL;
+        }
+
+        verifyThatURIIsFile(callback->getUri(), "rw");
+
+        const std::string file_path = ExifUtil::convertUriToPath(callback->getUri());
+        callback->getExifInfo()->saveToFile(file_path);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch (...) {
+        LOGE("Save Exif to file failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Save Exif to file failed");
+    }
+
+    if (0 == g_idle_add(saveExifInfoCompleted, static_cast<void*>(callback))) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+    return NULL;
+}
+
+void ExifManager::saveExifInfoFailed(Common::CallbackUserData* callback)
+{
+    LOGD("Entered");
+    if (!callback) {
+        LOGE("callback is NULL");
+        throw DeviceAPI::Common::UnknownException("NULL callback error");
+    }
+
+    if (0 == g_idle_add(saveExifInfoFailed, static_cast<void*>(callback))) {
+        delete callback;
+        callback = NULL;
+        LOGE("g_idle addition failed");
+   }
+
+}
+
+void ExifManager::saveExifInfo(ExifInfoCallbackData* cbdata)
+{
+    LOGD("Entered");
+    if (!cbdata) {
+        LOGE("cbdata is NULL");
+        throw DeviceAPI::Common::UnknownException("NULL callback error");
+    }
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, saveExifInfoThread,
+                static_cast<void*>(cbdata))) {
+        LOGE("Failed to create pthread for saveExifInfo()");
+        throw UnknownException("Could not save Exif to file");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for saveExifInfo()");
+    }
+}
+
+gboolean ExifManager::getThumbnailCompleted(void* data)
+{
+    LOGD("Entered");
+    auto callback = static_cast<GetThumbnailCallbackUserData*>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            const std::string& thumbnail_uri = callback->getThumbnailUri();
+            JSValueRef js_result = NULL;
+            if (thumbnail_uri.empty()) {
+                js_result = JSValueMakeNull(context);
+            }
+            else {
+                js_result = JSUtil::toJSValueRef(context, thumbnail_uri);
+            }
+            callback->callSuccessCallback(js_result);
+        }
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Error while calling getThumbnail callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error occured when calling getThumbnail callback");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void* ExifManager::getThumbnailThread(void* data)
+{
+    LOGD("Entered");
+    GetThumbnailCallbackUserData* callback = NULL;
+    ExifLoader* exif_loader = NULL;
+    ExifData* exif_data = NULL;
+
+    try {
+        callback = static_cast<GetThumbnailCallbackUserData*>(data);
+        if (!callback) {
+            LOGE("Callback is NULL!");
+            return NULL;
+        }
+
+        verifyThatURIIsFile(callback->getUri(), "r");
+
+        exif_loader = exif_loader_new();
+        if (!exif_loader) {
+            LOGE("exif_loader_new failed -> returned NULL");
+            throw UnknownException("Could not get thumbnail from Exif");
+        }
+
+        const std::string file_path = ExifUtil::convertUriToPath(callback->getUri());
+        LOGD("Get thumbnail from Exif in file: [%s]", file_path.c_str());
+
+        exif_loader_write_file(exif_loader, file_path.c_str());
+        exif_data = exif_loader_get_data(exif_loader);
+        if (!exif_data) {
+            LOGE("exif_loader_get_data failed -> returned NULL");
+            throw UnknownException("Could not get thumbnail from Exif");
+        }
+
+        if (exif_data->data && exif_data->size) {
+            gchar* ch_uri = g_base64_encode(exif_data->data, exif_data->size);
+
+            std::string ext = file_path.substr(file_path.find_last_of(".") + 1);
+            std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
+
+            if ("jpg" == ext) {
+                ext = "jpeg";
+            }
+
+            if ("jpeg" == ext || "png" == ext || "gif" == ext) {
+                std::string uri ="data:image/"+ext+";base64," + ch_uri;
+                callback->setThumbnailUri(uri);
+            }
+            else {
+                LOGE("extension: %s is not valid (jpeg/jpg/png/gif is supported)");
+                throw InvalidValuesException("Invalid file type");
+            }
+        }
+        else {
+            callback->setThumbnailUri(std::string());
+        }
+
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch (...) {
+        LOGE("Get thumbnail from Exif failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Get thumbnail from Exif failed");
+    }
+
+    if (exif_loader) {
+        exif_loader_unref(exif_loader);
+        exif_loader = NULL;
+    }
+
+    if (exif_data) {
+        exif_data_unref(exif_data);
+        exif_data = NULL;
+    }
+
+    if (!g_idle_add(getThumbnailCompleted, static_cast<void*>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+
+    return NULL;
+}
+
+void ExifManager::getThumbnail(GetThumbnailCallbackUserData* cbdata)
+{
+    LOGD("Entered");
+    if (!cbdata) {
+        LOGE("cbdata is NULL");
+        throw DeviceAPI::Common::UnknownException("NULL callback error");
+    }
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, getThumbnailThread,
+                static_cast<void*>(cbdata))) {
+        LOGE("Failed to create pthread for getThumbnail()");
+        throw UnknownException("Could not get thumbnail from Exif");
+    }
+
+    if (pthread_detach(thread)) {
+        LOGE("Failed to detach the pthread for getThumbnail()");
+    }
+}
+
+} // Exif
+} // DeviceAPI
diff --git a/src/Exif/ExifManager.h b/src/Exif/ExifManager.h
new file mode 100755 (executable)
index 0000000..f51b871
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_EXIF_EXIFMANAGER_H_
+#define __TIZEN_EXIF_EXIFMANAGER_H_
+
+#include <libexif/exif-data.h>
+#include <glib.h>
+
+#include <SecurityAccessor.h>
+#include <CallbackUserData.h>
+
+#include "ExifManagerCallbacks.h"
+#include "ExifInformation.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+class ExifManager: public Common::SecurityAccessor
+{
+public:
+    static ExifManager& getInstance();
+    virtual ~ExifManager();
+
+    void getExifInfo(ExifInfoCallbackData* cbdata);
+    void saveExifInfo(ExifInfoCallbackData* cbdata);
+    void getThumbnail(GetThumbnailCallbackUserData* cbdata);
+    void saveExifInfoFailed(Common::CallbackUserData* callback);
+
+private:
+    ExifManager();
+    ExifManager(const ExifManager&);
+    ExifManager& operator=(const ExifManager&);
+
+    static gboolean getExifInfoCompleted(void* data);
+    static void* getExifInfoThread(void* data);
+
+    static gboolean saveExifInfoFailed(void* data);
+    static gboolean saveExifInfoCompleted(void* data);
+    static void* saveExifInfoThread(void* data);
+
+    static gboolean getThumbnailCompleted(void* data);
+    static void* getThumbnailThread(void* data);
+};
+
+} // Exif
+} // DeviceAPI
+
+#endif // __TIZEN_EXIF_EXIFMANAGER_H_
diff --git a/src/Exif/ExifManagerCallbacks.cpp b/src/Exif/ExifManagerCallbacks.cpp
new file mode 100644 (file)
index 0000000..5c0f43e
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ExifManagerCallbacks.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+///////////////// ExifManagerCallbackUserData ////////////////////////
+ExifManagerCallbackUserData::ExifManagerCallbackUserData(JSContextRef globalCtx,
+        std::string uri) :
+    CallbackUserData(globalCtx),
+    m_uri(uri),
+    m_is_error(false)
+{
+    LOGD("Entered");
+}
+
+ExifManagerCallbackUserData::~ExifManagerCallbackUserData()
+{
+}
+
+void ExifManagerCallbackUserData::setError(const std::string& err_name,
+const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+std::string& ExifManagerCallbackUserData::getUri()
+{
+    return m_uri;
+}
+
+void ExifManagerCallbackUserData::setUri(const std::string&  uri)
+{
+    m_uri = uri;
+}
+
+bool ExifManagerCallbackUserData::isError() const
+{
+    return m_is_error;
+}
+
+const std::string& ExifManagerCallbackUserData::getErrorName() const
+{
+    return m_err_name;
+}
+
+const std::string& ExifManagerCallbackUserData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+
+///////////////// ExifInfoCallbackData ////////////////////////
+ExifInfoCallbackData::ExifInfoCallbackData(
+        JSContextRef globalCtx, std::string uri):
+    ExifManagerCallbackUserData(globalCtx, uri)
+{
+    LOGD("Entered");
+}
+
+ExifInfoCallbackData::~ExifInfoCallbackData()
+{
+    LOGD("Entered");
+}
+
+void ExifInfoCallbackData::setExifInfo(ExifInformationPtr info)
+{
+    m_exif_info = info;
+}
+
+ExifInformationPtr ExifInfoCallbackData::getExifInfo() const
+{
+    return m_exif_info;
+}
+
+///////////////// GetThumbnailCallbackUserData ////////////////////////
+GetThumbnailCallbackUserData::GetThumbnailCallbackUserData(JSContextRef global_ctx,
+        std::string uri) :
+        ExifManagerCallbackUserData(global_ctx, uri)
+{
+}
+
+GetThumbnailCallbackUserData::~GetThumbnailCallbackUserData()
+{
+}
+
+std::string& GetThumbnailCallbackUserData::getThumbnailUri()
+{
+    return m_thumbnail_uri;
+}
+
+void GetThumbnailCallbackUserData::setThumbnailUri(const std::string& uri)
+{
+    m_thumbnail_uri = uri;
+}
+
+} // Exif
+} // DeviceAPI
diff --git a/src/Exif/ExifManagerCallbacks.h b/src/Exif/ExifManagerCallbacks.h
new file mode 100755 (executable)
index 0000000..380919e
--- /dev/null
@@ -0,0 +1,95 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_EXIF_EXIFMANAGER_CALLBACK_USER_DATA_H_
+#define __TIZEN_EXIF_EXIFMANAGER_CALLBACK_USER_DATA_H_
+
+#include <string>
+#include <memory>
+
+#include <CallbackUserData.h>
+
+#include "ExifInformation.h"
+
+
+namespace DeviceAPI {
+namespace Exif {
+
+///////////////// ExifManagerCallbackUserData ////////////////////////
+class ExifManagerCallbackUserData: public Common::CallbackUserData {
+public:
+    ExifManagerCallbackUserData(JSContextRef globalCtx,
+            std::string uri);
+    virtual ~ExifManagerCallbackUserData();
+
+    std::string& getUri();
+    void setUri(const std::string& uri);
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    const std::string& getErrorName() const;
+    const std::string& getErrorMessage() const;
+
+private:
+    std::string m_uri;
+
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+};
+
+
+///////////////// ExifInfoCallbackData ////////////////////////
+class ExifInfoCallbackData;
+typedef std::shared_ptr<ExifInfoCallbackData> ExifInfoCallbackDataPtr;
+
+struct ExifInfoCallbackDataHolder {
+    ExifInfoCallbackDataPtr ptr;
+};
+
+class ExifInfoCallbackData : public ExifManagerCallbackUserData
+{
+public:
+    ExifInfoCallbackData(JSContextRef globalCtx, std::string uri);
+    virtual ~ExifInfoCallbackData();
+
+    void setExifInfo(ExifInformationPtr info);
+    ExifInformationPtr getExifInfo() const;
+
+private:
+    ExifInformationPtr m_exif_info;
+};
+
+///////////////// GetThumbnailCallbackUserData ////////////////////////
+class GetThumbnailCallbackUserData: public ExifManagerCallbackUserData {
+public:
+    GetThumbnailCallbackUserData(JSContextRef global_ctx,
+            std::string uri);
+    virtual ~GetThumbnailCallbackUserData();
+
+    std::string& getThumbnailUri();
+    void setThumbnailUri(const std::string& uri);
+
+private:
+    std::string m_thumbnail_uri;
+};
+
+} // Exif
+} // DeviceAPI
+
+#endif // __TIZEN_EXIF_EXIFMANAGER_CALLBACK_USER_DATA_H_
diff --git a/src/Exif/ExifTagSaver.cpp b/src/Exif/ExifTagSaver.cpp
new file mode 100644 (file)
index 0000000..863ad7f
--- /dev/null
@@ -0,0 +1,441 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ExifTagSaver.h"
+
+#include <libexif/exif-format.h>
+#include <sstream>
+
+#include <PlatformException.h>
+
+#include "ExifUtil.h"
+
+namespace DeviceAPI {
+
+using namespace DeviceAPI::Common;
+
+namespace Exif {
+
+void ExifTagSaver::removeExifEntryWithTag(const ExifTag tag, ExifData* exif_data)
+{
+    LOGD("Entered tag:%d (0x%x)", tag, tag);
+    ExifEntry* exif_entry = exif_data_get_entry(exif_data, tag);
+    if (!exif_entry) {
+        LOGD("Exif entry with tag:%d (0x%x) is not present", tag, tag);
+        return;
+    }
+
+    exif_content_remove_entry(exif_entry->parent, exif_entry);
+    LOGD("Removed exif entry with tag:%d (0x%x)", tag, tag);
+}
+
+void ExifTagSaver::saveToExif(long int value, ExifTag tag, ExifData* exif_data)
+{
+    ExifEntry* entry = prepareEntry(exif_data, tag);
+    ExifByteOrder order = exif_data_get_byte_order(exif_data);
+
+    switch (entry->format) {
+        case EXIF_FORMAT_BYTE:
+            entry->data[0] = static_cast<unsigned char>(value);
+            break;
+        case EXIF_FORMAT_SHORT:
+            exif_set_short (entry->data, order, value);
+            break;
+        case EXIF_FORMAT_LONG:
+            exif_set_long (entry->data, order, value);
+            break;
+        case EXIF_FORMAT_SLONG:
+            exif_set_slong (entry->data, order, value);
+            break;
+        default:
+            LOGE("Error: wrong format: %d \n", entry->format );
+    }
+}
+
+void ExifTagSaver::saveToExif(const std::string& value, ExifTag tag, ExifData* exif_data,
+        bool add_zero_character)
+{
+    LOGD("Entered saving string:[%s] %s to tag: %d(0x%x)", value.c_str(),
+            add_zero_character ? "+ \\0" : "",
+            tag, tag);
+
+    ExifEntry* entry = prepareEntry(exif_data, tag);
+    if (!value.empty()) {
+
+        if (entry->data) {
+            free(entry->data);
+            entry->data = NULL;
+        }
+
+        size_t new_len = value.length();
+        if(add_zero_character) {
+            ++new_len;
+        }
+
+        if(EXIF_TAG_GPS_DATE_STAMP == tag) {
+            LOGD("Fixing tag: %d(0x%x) - GPS_DATE_STAMP tag format to ASCII, was:%d (%s)",
+                    EXIF_TAG_GPS_DATE_STAMP, EXIF_TAG_GPS_DATE_STAMP,
+                    entry->format,
+                    exif_format_get_name(entry->format));
+
+            entry->format = EXIF_FORMAT_ASCII;
+            if(new_len != 11) {
+                LOGW("EXIF_TAG_GPS_DATE_STAMP should be exactly 11 bytes long but is:%d!",
+                        new_len);
+            }
+        }
+
+        entry->size = new_len;
+        entry->components = new_len;
+
+        entry->data = static_cast<unsigned char*>(malloc(entry->size));
+        memcpy(entry->data, value.c_str(), value.length());
+        if(add_zero_character) {
+            entry->data[value.length()] = '\0';
+        }
+    }
+}
+
+void ExifTagSaver::saveToExif(const Rational& value, ExifTag tag, ExifData* exif_data)
+{
+    ExifEntry* entry = prepareEntry(exif_data, tag);
+    entry->format = EXIF_FORMAT_RATIONAL;
+
+    if (ExifTypeInfo::RationalSize != entry->size) {
+        if (entry->data) {
+            free(entry->data);
+            entry->data = NULL;
+        }
+
+        entry->size = ExifTypeInfo::RationalSize;
+        entry->data = static_cast<unsigned char*>(malloc(entry->size));
+        memset(entry->data, 0, entry->size);
+    }
+
+    entry->components = 1;
+
+    ExifByteOrder order = exif_data_get_byte_order(exif_data);
+    ExifRational r;
+    r.numerator = value.nominator;
+    r.denominator = value.denominator;
+    exif_set_rational(entry->data, order, r);
+}
+
+void ExifTagSaver::saveToExif(const Rationals& value, ExifTag tag, ExifData* exif_data)
+{
+    ExifEntry* entry = prepareEntry(exif_data, tag);
+    ExifByteOrder order = exif_data_get_byte_order(exif_data);
+    entry->format = EXIF_FORMAT_RATIONAL;
+
+    const unsigned int required_size = ExifTypeInfo::RationalSize * value.size();
+    if (required_size != entry->size) {
+        if (entry->data) {
+            free(entry->data);
+            entry->data = NULL;
+        }
+
+        entry->size = required_size;
+        entry->data = static_cast<unsigned char*>(malloc(entry->size));
+        memset(entry->data, 0, entry->size);
+    }
+
+    entry->components = value.size();
+    for(size_t i = 0; i < value.size(); ++i)
+    {
+        ExifRational r;
+        r.numerator = value[i].nominator;
+        r.denominator = value[i].denominator;
+        exif_set_rational(entry->data + i * ExifTypeInfo::RationalSize, order, r);
+    }
+}
+
+void ExifTagSaver::saveToExif(std::vector<long long int>& value, ExifFormat store_as,
+            ExifTag tag, ExifData* exif_data)
+{
+    ExifEntry* entry = prepareEntry(exif_data, tag);
+    const ExifByteOrder order = exif_data_get_byte_order(exif_data);
+
+    const size_t size_per_member = ExifUtil::getSizeOfExifFormatType(store_as);
+    switch (store_as) {
+        case EXIF_FORMAT_BYTE:
+        case EXIF_FORMAT_SHORT:
+        case EXIF_FORMAT_SSHORT:
+        case EXIF_FORMAT_LONG:
+        case EXIF_FORMAT_SLONG:
+            break;
+        default:
+            LOGE("output ExifFormat: %d is not supported!");
+            return;
+    }
+    entry->format = store_as;
+
+    const size_t num_elements = value.size();
+    const unsigned int required_size = size_per_member * num_elements;
+    if (required_size != entry->size) {
+        if (entry->data) {
+            free(entry->data);
+            entry->data = NULL;
+        }
+
+        entry->size = required_size;
+        entry->data = static_cast<unsigned char*>(malloc(entry->size));
+        memset(entry->data, 0, entry->size);
+    }
+    entry->components = num_elements;
+
+
+    switch (store_as) {
+        case EXIF_FORMAT_BYTE: {
+            for(size_t i = 0; i < num_elements; ++i) {
+                entry->data[i] = static_cast<ExifByte>(value[i]);
+            }
+            break;
+        }
+
+        case EXIF_FORMAT_SHORT: {
+            for(size_t i = 0; i < num_elements; ++i) {
+                exif_set_short(entry->data + i * size_per_member, order,
+                        static_cast<ExifShort>(value[i]));
+            }
+            break;
+        }
+
+        case EXIF_FORMAT_SSHORT: {
+            for(size_t i = 0; i < num_elements; ++i) {
+                exif_set_sshort(entry->data + i * size_per_member, order,
+                        static_cast<ExifSShort>(value[i]));
+            }
+            break;
+        }
+
+        case EXIF_FORMAT_LONG: {
+            for(size_t i = 0; i < num_elements; ++i) {
+                exif_set_long(entry->data + i * size_per_member, order,
+                        static_cast<ExifLong>(value[i]));
+            }
+            break;
+        }
+
+        case EXIF_FORMAT_SLONG: {
+            for(size_t i = 0; i < num_elements; ++i) {
+                exif_set_slong(entry->data + i * size_per_member, order,
+                        static_cast<ExifSLong>(value[i]));
+            }
+            break;
+        }
+    }
+
+
+    LOGD("entry after save:");
+    ExifUtil::printExifEntryInfo(entry, exif_data);
+}
+
+void ExifTagSaver::saveGpsLocationToExif(const ExifGPSLocation& gps_info,
+        ExifData* exif_data)
+{
+    if (gps_info.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE)) {
+        auto latitude = gps_info.getLatitude();
+        LOGD("Saving latitude: %s", latitude.toDebugString().c_str());
+        saveToExif(latitude.toRationalsVector(),
+                static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE), exif_data);
+    }
+
+    if (gps_info.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LATITUDE_REF)) {
+        std::string lat_ref =
+                (gps_info.getLatitudeRef() == GPS_LOCATION_NORTH) ? "N" : "S";
+        LOGD("Saving latitude ref: %s", lat_ref.c_str());
+        saveToExif(lat_ref, static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE_REF), exif_data);
+    }
+
+    if (gps_info.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE)) {
+
+        auto longitude = gps_info.getLongitude();
+        LOGD("Saving longitude: %s", longitude.toDebugString().c_str());
+        saveToExif(longitude.toRationalsVector(),
+                static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE), exif_data);
+    }
+
+    if (gps_info.isSet(EXIF_GPS_LOCATION_ATTRIBUTE_LONGITUDE_REF)) {
+        std::string long_ref =
+                (gps_info.getLongitudeRef() == GPS_LOCATION_WEST) ? "W" : "E";
+        LOGD("Saving longitude ref: %s", long_ref.c_str());
+        saveToExif(long_ref, static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE_REF), exif_data);
+    }
+}
+
+void ExifTagSaver::saveGpsTimeToExif(const ExifGPSTime& gps_time,
+            ExifData* exif_data)
+{
+    if (gps_time.isTimeSet()) {
+        const Rationals& time = gps_time.getTime();
+        LOGD("Saving gps time: [%s]h [%s]m [%s]d",
+                time[0].toString().c_str(),
+                time[1].toString().c_str(),
+                time[2].toString().c_str());
+
+        saveToExif(time, static_cast<ExifTag>(EXIF_TAG_GPS_TIME_STAMP), exif_data);
+    }
+
+    if (gps_time.isDateSet()) {
+        std::string date = gps_time.getDate();
+        LOGD("Saving gps date: [%s]", date.c_str());
+
+        saveToExif(date, static_cast<ExifTag>(EXIF_TAG_GPS_DATE_STAMP), exif_data);
+    }
+}
+
+ExifEntry* ExifTagSaver::prepareEntry(ExifData* exif_data, ExifTag tag)
+{
+    const ExifIfd ifd = deduceIfdSection(tag);
+    const ExifFormat format = deduceDataFormat(tag);
+    LOGD("Entered m_tag: %d (0x%x) | ifd:%d format:%d (%s)", tag, tag, ifd,
+            format, exif_format_get_name(format));
+
+    ExifEntry* exif_entry = exif_data_get_entry(exif_data, tag);
+    if (!exif_entry) {
+        exif_entry = createNewTag(exif_data, ifd, format, tag );
+    } else {
+        LOGD("Using existing entry with tag:%d (0x%x) format:%d (%s)",
+                exif_entry->tag, exif_entry->tag,
+                exif_entry->format, exif_format_get_name(exif_entry->format));
+    }
+
+    if (!exif_entry) {
+        LOGE("Couldn't create new Exif tag");
+        throw UnknownException("Could not save Exif to file");
+    }
+
+    exif_entry_initialize(exif_entry, tag);
+
+    if(exif_entry->format != format) {
+        LOGW("format should be: %d (%s) is: %d (%s)!",
+                format, exif_format_get_name(format),
+                exif_entry->format, exif_format_get_name(exif_entry->format));
+    }
+
+    return exif_entry;
+}
+
+ExifEntry* ExifTagSaver::createNewTag(ExifData* exif_data, ExifIfd ifd,
+        ExifFormat format, ExifTag tag)
+{
+    LOGD("Creating new tag: %d (0x%x) | ifd:%d format:%d (%s)", tag, tag, ifd,
+            format, exif_format_get_name(format));
+
+    ExifEntry* new_entry = exif_entry_new();
+    new_entry->tag = tag;
+    new_entry->format = format;
+    exif_content_add_entry(exif_data->ifd[ifd], new_entry);
+    exif_entry_initialize(new_entry, tag);
+    return new_entry;
+}
+
+ExifIfd ExifTagSaver::deduceIfdSection(ExifTag tag)
+{
+    switch (static_cast<unsigned int>(tag)) {
+        //Tags in IFD_0 Section
+        case EXIF_TAG_MAKE:
+        case EXIF_TAG_MODEL:
+        case EXIF_TAG_IMAGE_WIDTH:
+        case EXIF_TAG_IMAGE_LENGTH:
+        case EXIF_TAG_ORIENTATION:
+            return EXIF_IFD_0;
+
+        //Tags in IFD_EXIF Section
+        case EXIF_TAG_USER_COMMENT:
+        case EXIF_TAG_DATE_TIME_ORIGINAL:
+        case EXIF_TAG_EXPOSURE_TIME:
+        case EXIF_TAG_FNUMBER:
+        case EXIF_TAG_EXPOSURE_PROGRAM:
+        case EXIF_TAG_ISO_SPEED_RATINGS:
+        case EXIF_TAG_WHITE_BALANCE:
+        case EXIF_TAG_FLASH:
+        case EXIF_TAG_FOCAL_LENGTH:
+            return EXIF_IFD_EXIF;
+
+        //Tags in IFD_GPS Section
+        case EXIF_TAG_GPS_LATITUDE_REF:
+        case EXIF_TAG_GPS_LONGITUDE_REF:
+        case EXIF_TAG_GPS_LATITUDE:
+        case EXIF_TAG_GPS_LONGITUDE:
+        case EXIF_TAG_GPS_ALTITUDE:
+        case EXIF_TAG_GPS_ALTITUDE_REF:
+        case EXIF_TAG_GPS_TIME_STAMP:
+        case EXIF_TAG_GPS_PROCESSING_METHOD:
+        case EXIF_TAG_GPS_DATE_STAMP:
+            return EXIF_IFD_GPS;
+
+        //Tags in other sections
+        default:
+            LOGE("Unsupported tag: %d", tag);
+            throw UnknownException("Unsupported tag");
+    }
+}
+
+ExifFormat ExifTagSaver::deduceDataFormat(ExifTag tag)
+{
+    switch (static_cast<unsigned int>(tag)) {
+        //Tags with byte type:
+        case EXIF_TAG_GPS_ALTITUDE_REF:
+            return EXIF_FORMAT_BYTE;
+
+        //Tags with long type:
+        case EXIF_TAG_IMAGE_WIDTH:
+        case EXIF_TAG_IMAGE_LENGTH:
+            return EXIF_FORMAT_LONG;
+
+        //Tags with short type:
+        case EXIF_TAG_ORIENTATION:
+        case EXIF_TAG_EXPOSURE_PROGRAM:
+        case EXIF_TAG_WHITE_BALANCE:
+        case EXIF_TAG_FLASH:
+            return EXIF_FORMAT_SHORT;
+
+        //Tags with ASCII type:
+        case EXIF_TAG_MAKE:
+        case EXIF_TAG_MODEL:
+        case EXIF_TAG_DATE_TIME_ORIGINAL:
+        case EXIF_TAG_GPS_LATITUDE_REF:
+        case EXIF_TAG_GPS_LONGITUDE_REF:
+        case EXIF_TAG_GPS_DATE_STAMP:
+            return EXIF_FORMAT_ASCII;
+
+        //Tags with rational type:
+        case EXIF_TAG_EXPOSURE_TIME:
+        case EXIF_TAG_FNUMBER:
+        case EXIF_TAG_FOCAL_LENGTH:
+        case EXIF_TAG_GPS_LATITUDE:
+        case EXIF_TAG_GPS_LONGITUDE:
+        case EXIF_TAG_GPS_ALTITUDE:
+        case EXIF_TAG_GPS_TIME_STAMP:
+        case EXIF_TAG_ISO_SPEED_RATINGS:
+            return EXIF_FORMAT_RATIONAL;
+
+        //Tags with undefined type:
+        case EXIF_TAG_USER_COMMENT:
+        case EXIF_TAG_GPS_PROCESSING_METHOD:
+            return EXIF_FORMAT_UNDEFINED;
+
+        //Unsupported tags:
+        default:
+            LOGE("Unsupported tag: %d", tag);
+            throw UnknownException("Unsupported tag");
+    }
+}
+
+} // Exif
+} // DeviceAPI
diff --git a/src/Exif/ExifTagSaver.h b/src/Exif/ExifTagSaver.h
new file mode 100644 (file)
index 0000000..e1c7c4d
--- /dev/null
@@ -0,0 +1,62 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file    ExifTagSaver.h
+ */
+
+#ifndef __TIZEN_EXIF_EXIF_TAG_SAVER_H__
+#define __TIZEN_EXIF_EXIF_TAG_SAVER_H__
+
+#include <string>
+#include <libexif/exif-data.h>
+
+#include "ExifGPSLocation.h"
+#include "ExifGPSTime.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+class ExifTagSaver
+{
+public:
+    static void removeExifEntryWithTag(const ExifTag tag, ExifData* exif_data);
+
+    static void saveToExif(long int value, ExifTag tag, ExifData* exif_data);
+    static void saveToExif(const std::string& value, ExifTag tag, ExifData* exif_data,
+            bool add_zero_character = true);
+    static void saveToExif(const Rational& value, ExifTag tag, ExifData* exif_data);
+    static void saveToExif(const Rationals& value, ExifTag tag, ExifData* exif_data);
+    static void saveToExif(std::vector<long long int>& value, ExifFormat store_as,
+            ExifTag tag, ExifData* exif_data);
+    static void saveGpsLocationToExif(const ExifGPSLocation& gps_info,
+            ExifData* exif_data);
+    static void saveGpsTimeToExif(const ExifGPSTime& gps_time,
+            ExifData* exif_data);
+
+private:
+    static ExifEntry* prepareEntry(ExifData* exif_data, ExifTag tag);
+    static ExifIfd deduceIfdSection(ExifTag tag);
+    static ExifFormat deduceDataFormat(ExifTag tag);
+    static ExifEntry* createNewTag(ExifData* exif_data, ExifIfd ifd,
+        ExifFormat format, ExifTag tag);
+};
+
+} // Exif
+} // DeviceAPI
+
+#endif // __TIZEN_EXIF_EXIF_TAG_SAVER_H__
diff --git a/src/Exif/ExifUtil.cpp b/src/Exif/ExifUtil.cpp
new file mode 100644 (file)
index 0000000..53e6690
--- /dev/null
@@ -0,0 +1,431 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ExifUtil.h"
+
+#include <iomanip>
+#include <sstream>
+
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+
+using namespace DeviceAPI::Common;
+
+namespace Exif {
+
+namespace {
+const std::string ORIENTATION_NORMAL = "NORMAL";
+const std::string ORIENTATION_FLIP_HORIZONTAL = "FLIP_HORIZONTAL";
+const std::string ORIENTATION_ROTATE_180 = "ROTATE_180";
+const std::string ORIENTATION_FLIP_VERTICAL = "FLIP_VERTICAL";
+const std::string ORIENTATION_TRANSPOSE = "TRANSPOSE";
+const std::string ORIENTATION_ROTATE_90 = "ROTATE_90";
+const std::string ORIENTATION_TRANSVERSE = "TRANSVERSE";
+const std::string ORIENTATION_ROTATE_270 = "ROTATE_270";
+
+const std::string WHITE_BALANCE_MODE_AUTO = "AUTO";
+const std::string WHITE_BALANCE_MODE_MANUAL = "MANUAL";
+
+const std::string EXPOSURE_PROGRAM_NOT_DEFINED = "NOT_DEFINED";
+const std::string EXPOSURE_PROGRAM_MANUAL = "MANUAL";
+const std::string EXPOSURE_PROGRAM_NORMAL = "NORMAL";
+const std::string EXPOSURE_PROGRAM_APERTURE_PRIORITY = "APERTURE_PRIORITY";
+const std::string EXPOSURE_PROGRAM_SHUTTER_PRIORITY = "SHUTTER_PRIORITY";
+const std::string EXPOSURE_PROGRAM_CREATIVE_PROGRAM = "CREATIVE_PROGRAM";
+const std::string EXPOSURE_PROGRAM_ACTION_PROGRAM = "ACTION_PROGRAM";
+const std::string EXPOSURE_PROGRAM_PORTRAIT_MODE = "PORTRAIT_MODE";
+const std::string EXPOSURE_PROGRAM_LANDSCAPE_MODE = "LANDSCAPE_MODE";
+
+const std::string DUMMY = ""; // For unexpected input handling
+
+const std::string URI_PREFIX = "file://";
+const std::string URI_ABSOLUTE_PREFIX = "file:///";
+}
+
+const size_t ExifTypeInfo::ByteSize = 1;
+const size_t ExifTypeInfo::ASCIISize = 1;
+const size_t ExifTypeInfo::ShortSize = 2;
+const size_t ExifTypeInfo::LongSize = 4;
+const size_t ExifTypeInfo::RationalSize = 8;
+const size_t ExifTypeInfo::UndefinedSize = 1;
+const size_t ExifTypeInfo::SLongSize = 4;
+const size_t ExifTypeInfo::SRationalSize = 8;
+
+const ExifByte ExifTypeInfo::ByteId = 1;
+const ExifByte ExifTypeInfo::ASCIIId = 2;
+const ExifByte ExifTypeInfo::ShortId = 3;
+const ExifByte ExifTypeInfo::LongId = 4;
+const ExifByte ExifTypeInfo::RationalId = 5;
+const ExifByte ExifTypeInfo::UndefinedId = 7;
+const ExifByte ExifTypeInfo::SLongId = 9;
+const ExifByte ExifTypeInfo::SRationalId = 10;
+
+ExifUtil::ExifUtil()
+{
+}
+
+ExifUtil::~ExifUtil()
+{
+}
+
+ImageOrientation ExifUtil::stringToOrientation(const std::string& orientation)
+{
+    LOGD("Entered");
+    if (ORIENTATION_NORMAL == orientation) {
+        return ImageOrientation::EXIF_ORIENTATION_NORMAL;
+    }
+    if (ORIENTATION_FLIP_HORIZONTAL == orientation) {
+        return ImageOrientation::EXIF_ORIENTATION_FLIP_HORIZONTAL;
+    }
+    if (ORIENTATION_ROTATE_180 == orientation) {
+        return ImageOrientation::EXIF_ORIENTATION_ROTATE_180;
+    }
+    if (ORIENTATION_FLIP_VERTICAL == orientation) {
+        return ImageOrientation::EXIF_ORIENTATION_FLIP_VERTICAL;
+    }
+    if (ORIENTATION_TRANSPOSE == orientation) {
+        return ImageOrientation::EXIF_ORIENTATION_TRANSPOSE;
+    }
+    if (ORIENTATION_ROTATE_90 == orientation) {
+        return ImageOrientation::EXIF_ORIENTATION_ROTATE_90;
+    }
+    if (ORIENTATION_TRANSVERSE == orientation) {
+        return ImageOrientation::EXIF_ORIENTATION_TRANSVERSE;
+    }
+    if (ORIENTATION_ROTATE_270 == orientation) {
+        return ImageOrientation::EXIF_ORIENTATION_ROTATE_270;
+    }
+    return ImageOrientation::EXIF_ORIENTATION_NOT_VALID;
+}
+
+const std::string& ExifUtil::orientationToString(ImageOrientation orientation)
+{
+    LOGD("Entered");
+    switch (orientation) {
+        case ImageOrientation::EXIF_ORIENTATION_NORMAL:
+            return ORIENTATION_NORMAL;
+        case ImageOrientation::EXIF_ORIENTATION_FLIP_HORIZONTAL:
+            return ORIENTATION_FLIP_HORIZONTAL;
+        case ImageOrientation::EXIF_ORIENTATION_ROTATE_180:
+            return ORIENTATION_ROTATE_180;
+        case ImageOrientation::EXIF_ORIENTATION_FLIP_VERTICAL:
+            return ORIENTATION_FLIP_VERTICAL;
+        case ImageOrientation::EXIF_ORIENTATION_TRANSPOSE:
+            return ORIENTATION_TRANSPOSE;
+        case ImageOrientation::EXIF_ORIENTATION_ROTATE_90:
+            return ORIENTATION_ROTATE_90;
+        case ImageOrientation::EXIF_ORIENTATION_TRANSVERSE:
+            return ORIENTATION_TRANSVERSE;
+        case ImageOrientation::EXIF_ORIENTATION_ROTATE_270:
+            return ORIENTATION_ROTATE_270;
+        default:
+            return DUMMY;
+    }
+}
+
+WhiteBalanceMode ExifUtil::stringToWhiteBalance(const std::string& white_balance)
+{
+    LOGD("Entered");
+    if (WHITE_BALANCE_MODE_AUTO == white_balance) {
+        return WhiteBalanceMode::EXIF_WHITE_BALANCE_MODE_AUTO;
+    }
+    if (WHITE_BALANCE_MODE_MANUAL == white_balance) {
+        return WhiteBalanceMode::EXIF_WHITE_BALANCE_MODE_MANUAL;
+    }
+    return WhiteBalanceMode::EXIF_WHITE_BALANCE_MODE_NOT_VALID;
+}
+
+const std::string& ExifUtil::whiteBalanceToString(WhiteBalanceMode value)
+{
+    LOGD("Entered");
+    switch (value) {
+        case WhiteBalanceMode::EXIF_WHITE_BALANCE_MODE_AUTO:
+            return WHITE_BALANCE_MODE_AUTO;
+        case WhiteBalanceMode::EXIF_WHITE_BALANCE_MODE_MANUAL:
+            return WHITE_BALANCE_MODE_MANUAL;
+        default:
+            return DUMMY;
+    }
+}
+
+ExposureProgram ExifUtil::stringToExposureProgram(
+        const std::string& exposure_program)
+{
+    LOGD("Entered");
+    if (EXPOSURE_PROGRAM_NOT_DEFINED == exposure_program) {
+        return EXIF_EXPOSURE_PROGRAM_NOT_DEFINED;
+    }
+    if (EXPOSURE_PROGRAM_MANUAL == exposure_program) {
+        return EXIF_EXPOSURE_PROGRAM_MANUAL;
+    }
+    if (EXPOSURE_PROGRAM_NORMAL == exposure_program) {
+        return EXIF_EXPOSURE_PROGRAM_NORMAL;
+    }
+    if (EXPOSURE_PROGRAM_APERTURE_PRIORITY == exposure_program) {
+        return EXIF_EXPOSURE_PROGRAM_APERTURE_PRIORITY;
+    }
+    if (EXPOSURE_PROGRAM_SHUTTER_PRIORITY == exposure_program) {
+        return EXIF_EXPOSURE_PROGRAM_SHUTTER_PRIORITY;
+    }
+    if (EXPOSURE_PROGRAM_CREATIVE_PROGRAM == exposure_program) {
+        return EXIF_EXPOSURE_PROGRAM_CREATIVE_PROGRAM;
+    }
+    if (EXPOSURE_PROGRAM_ACTION_PROGRAM == exposure_program) {
+        return EXIF_EXPOSURE_PROGRAM_ACTION_PROGRAM;
+    }
+    if (EXPOSURE_PROGRAM_PORTRAIT_MODE == exposure_program) {
+        return EXIF_EXPOSURE_PROGRAM_PORTRAIT_MODE;
+    }
+    if (EXPOSURE_PROGRAM_LANDSCAPE_MODE == exposure_program) {
+        return EXIF_EXPOSURE_PROGRAM_LANDSCAPE_MODE;
+    }
+    return EXIF_EXPOSURE_PROGRAM_NOT_VALID;
+}
+
+const std::string& ExifUtil::exposureProgramToString(ExposureProgram value)
+{
+    LOGD("Entered");
+    switch (value) {
+        case ExposureProgram::EXIF_EXPOSURE_PROGRAM_NOT_DEFINED:
+            return EXPOSURE_PROGRAM_NOT_DEFINED;
+        case ExposureProgram::EXIF_EXPOSURE_PROGRAM_MANUAL:
+            return EXPOSURE_PROGRAM_MANUAL;
+        case ExposureProgram::EXIF_EXPOSURE_PROGRAM_NORMAL:
+            return EXPOSURE_PROGRAM_NORMAL;
+        case ExposureProgram::EXIF_EXPOSURE_PROGRAM_APERTURE_PRIORITY:
+            return EXPOSURE_PROGRAM_APERTURE_PRIORITY;
+        case ExposureProgram::EXIF_EXPOSURE_PROGRAM_SHUTTER_PRIORITY:
+            return EXPOSURE_PROGRAM_SHUTTER_PRIORITY;
+        case ExposureProgram::EXIF_EXPOSURE_PROGRAM_CREATIVE_PROGRAM:
+            return EXPOSURE_PROGRAM_CREATIVE_PROGRAM;
+        case ExposureProgram::EXIF_EXPOSURE_PROGRAM_ACTION_PROGRAM:
+            return EXPOSURE_PROGRAM_ACTION_PROGRAM;
+        case ExposureProgram::EXIF_EXPOSURE_PROGRAM_PORTRAIT_MODE:
+            return EXPOSURE_PROGRAM_PORTRAIT_MODE;
+        case ExposureProgram::EXIF_EXPOSURE_PROGRAM_LANDSCAPE_MODE:
+            return EXPOSURE_PROGRAM_LANDSCAPE_MODE;
+        default:
+            return DUMMY;
+    }
+}
+
+bool ExifUtil::isValidAbsoluteURI(const std::string& uri)
+{
+    return 0 == uri.find(URI_ABSOLUTE_PREFIX);
+}
+
+void ExifUtil::getURIInfo(const std::string& uri,
+        const Filesystem::NodeType expected_type,
+        const std::string& required_permission,
+        bool& out_exists,
+        Filesystem::NodeType& out_type,
+        bool& out_permission_granted)
+{
+    const std::string absolute_path = ExifUtil::convertUriToPath(uri);
+    out_exists = false;
+    out_permission_granted = false;
+
+    try {
+        Filesystem::PathPtr path = Filesystem::Path::create(absolute_path);
+        Filesystem::NodePtr node = Filesystem::Node::resolve(path);
+        out_type = node->getType();
+        out_exists = true;
+
+        if(expected_type == out_type) {
+            out_permission_granted = node->checkPermission(path, required_permission,
+                    expected_type);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Couldn't resolve path: %s, got:%s (%s)", absolute_path.c_str(),
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Couldn't resolve path: %s", absolute_path.c_str());
+    }
+}
+
+std::string ExifUtil::convertUriToPath(const std::string& str)
+{
+    std::string path = ltrim(str);
+    std::string prefix = path.substr(0, URI_PREFIX.size());
+
+    if (prefix == URI_PREFIX) {
+        return path.substr(URI_PREFIX.size());
+    }
+    else {
+        return path;
+    }
+}
+
+std::string ExifUtil::ltrim(const std::string& s)
+{
+    std::string str = s;
+    std::string::iterator i;
+    for (i = str.begin(); i != str.end(); i++) {
+        if (!isspace(*i)) {
+            break;
+        }
+    }
+    if (i == str.end()) {
+        str.clear();
+    }
+    else {
+        str.erase(str.begin(), i);
+    }
+    return str;
+}
+
+time_t ExifUtil::exifDateTimeOriginalToTimeT(const char* string)
+{
+    int year, month, day, hour, min, sec;
+    if (sscanf(string, "%d:%d:%d %d:%d:%d",
+                &year, &month, &day, &hour, &min, &sec) >= 6) {
+        return convertToTimeT(year, month, day, hour, min, sec);
+    }
+
+    return 0;
+}
+
+std::string ExifUtil::timeTToExifDateTimeOriginal(time_t time)
+{
+    int year, month, day, hour, min, sec;
+    extractFromTimeT(time, year, month, day, hour, min, sec);
+
+    std::ostringstream ss;
+    ss << std::setfill('0') << std::setw(4) << year << ':' ;
+    ss << std::setfill('0') << std::setw(2) << month << ':' ;
+    ss << std::setfill('0') << std::setw(2) << day << ' ' ;
+
+    ss << std::setfill('0') << std::setw(2) << hour << ':' ;
+    ss << std::setfill('0') << std::setw(2) << min << ':' ;
+    ss << std::setfill('0') << std::setw(2) << sec;
+    return ss.str();
+}
+
+size_t  ExifUtil::getSizeOfExifFormatType(ExifFormat format)
+{
+    size_t size_per_member = 0;
+    switch (format) {
+        case EXIF_FORMAT_BYTE:
+            size_per_member = 1;
+            break;
+
+        case EXIF_FORMAT_SHORT:
+        case EXIF_FORMAT_SSHORT:
+            size_per_member = 2;
+            break;
+
+        case EXIF_FORMAT_LONG:
+        case EXIF_FORMAT_SLONG:
+            size_per_member = 4;
+            break;
+
+        case EXIF_FORMAT_RATIONAL:
+        case EXIF_FORMAT_SRATIONAL:
+            size_per_member = 8;
+            break;
+
+        default:
+            LOGE("output ExifFormat: %d is not supported!");
+            return 0;
+    }
+
+    return size_per_member;
+}
+
+void ExifUtil::printExifEntryInfo(ExifEntry* entry, ExifData* exif_data)
+{
+    char buf[2000];
+    std::stringstream ss;
+
+    if (!entry) {
+        LOGE("entry is null");
+        return;
+    }
+
+    if (!entry->data) {
+        LOGE("entry data is null");
+        return;
+    }
+
+    unsigned char* read_buf_ptr = entry->data;
+
+    size_t size_per_member = getSizeOfExifFormatType(entry->format);
+    if (0 == size_per_member) {
+        size_per_member = 1;    //display as array of bytes
+    }
+
+    for(unsigned long compi = 0; compi < entry->components; ++compi) {
+
+        if (compi > 0) {
+            ss << " ";
+        }
+
+        for(size_t i = 0; i < size_per_member; ++i) {
+            unsigned int value = read_buf_ptr[i];
+            ss << std::hex << std::setw(2) << std::setfill('0') << value;
+        }
+
+        read_buf_ptr += size_per_member;
+    }
+
+    LOGD("Entry{name:%s type:%s size:%d components:%d value:%s RAW DATA:[%s]}",
+            exif_tag_get_name(entry->tag),
+            exif_format_get_name(entry->format),
+            (int)entry->size,
+            (int)entry->components,
+            exif_entry_get_value(entry, buf, sizeof(buf)),
+            ss.str().c_str());
+}
+
+void ExifUtil::extractFromTimeT(const time_t time,
+            int& out_year, int& out_month, int& out_day,
+            int& out_hour, int& out_min, int& out_sec)
+{
+    struct tm* utc = gmtime(&time);
+
+    out_year = utc->tm_year + 1900;
+    out_month = utc->tm_mon + 1;
+    out_day = utc->tm_mday;
+    out_hour = utc->tm_hour;
+    out_min = utc->tm_min;
+    out_sec = utc->tm_sec;
+}
+
+time_t ExifUtil::convertToTimeT(int year, int month, int day,
+            int hour, int min, int sec)
+{
+    time_t tmp_time = 0;
+    struct tm* timeinfo = localtime(&tmp_time);
+    timeinfo->tm_year = year - 1900;
+    timeinfo->tm_mon = month - 1;
+    timeinfo->tm_mday = day;
+
+    timeinfo->tm_hour = hour;
+    timeinfo->tm_min = min;
+    timeinfo->tm_sec = sec;
+
+    //From mktime documentation:
+    //"The values of the members tm_wday and tm_yday of timeptr are ignored"
+    return timegm(timeinfo);
+}
+
+} // Exif
+} // DeviceAPI
diff --git a/src/Exif/ExifUtil.h b/src/Exif/ExifUtil.h
new file mode 100644 (file)
index 0000000..b687c62
--- /dev/null
@@ -0,0 +1,153 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_EXIF_EXIFUTIL_H_
+#define __TIZEN_EXIF_EXIFUTIL_H_
+
+#include <libexif/exif-data.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-utils.h>
+#include <string>
+#include <vector>
+
+#include <Node.h>
+#include <Path.h>
+#include <TZDate.h>
+
+#include "Rational.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+enum ImageOrientation {
+    EXIF_ORIENTATION_NORMAL = 1,
+    EXIF_ORIENTATION_FLIP_HORIZONTAL = 2,
+    EXIF_ORIENTATION_ROTATE_180 = 3,
+    EXIF_ORIENTATION_FLIP_VERTICAL = 4,
+    EXIF_ORIENTATION_TRANSPOSE = 5,
+    EXIF_ORIENTATION_ROTATE_90 = 6,
+    EXIF_ORIENTATION_TRANSVERSE = 7,
+    EXIF_ORIENTATION_ROTATE_270 = 8,
+    EXIF_ORIENTATION_NOT_VALID,
+};
+
+enum WhiteBalanceMode {
+    EXIF_WHITE_BALANCE_MODE_AUTO = 0,
+    EXIF_WHITE_BALANCE_MODE_MANUAL = 1,
+    EXIF_WHITE_BALANCE_MODE_NOT_VALID
+};
+
+enum ExposureProgram {
+    EXIF_EXPOSURE_PROGRAM_NOT_DEFINED = 0,
+    EXIF_EXPOSURE_PROGRAM_MANUAL = 1,
+    EXIF_EXPOSURE_PROGRAM_NORMAL = 2,
+    EXIF_EXPOSURE_PROGRAM_APERTURE_PRIORITY = 3,
+    EXIF_EXPOSURE_PROGRAM_SHUTTER_PRIORITY = 4,
+    EXIF_EXPOSURE_PROGRAM_CREATIVE_PROGRAM = 5,
+    EXIF_EXPOSURE_PROGRAM_ACTION_PROGRAM = 6,
+    EXIF_EXPOSURE_PROGRAM_PORTRAIT_MODE = 7,
+    EXIF_EXPOSURE_PROGRAM_LANDSCAPE_MODE = 8,
+    EXIF_EXPOSURE_PROGRAM_NOT_VALID
+};
+
+/**
+ * From Exif 2.2 specification:
+ *  The following types are used in Exif:
+ *  1 = BYTE An 8-bit unsigned integer.,
+ *  2 = ASCII An 8-bit byte containing one 7-bit ASCII code. The final byte is terminated
+ *      with NULL.,
+ *  3 = SHORT A 16-bit (2-byte) unsigned integer,
+ *  4 = LONG A 32-bit (4-byte) unsigned integer,
+ *  5 = RATIONAL Two LONGs. The first LONG is the numerator and the second LONG expresses
+ *      the denominator.,
+ *  7 = UNDEFINED An 8-bit byte that can take any value depending on the field definition,
+ *  9 = SLONG A 32-bit (4-byte) signed integer (2's complement notation),
+ * 10 = SRATIONAL Two SLONGs. The first SLONG is the numerator and the second SLONG is the
+ *      denominator.
+ */
+struct ExifTypeInfo {
+
+    /**
+     * Number of bytes used by each exif type
+     */
+    static const size_t ByteSize;       //1 byte
+    static const size_t ASCIISize;      //1 byte (*N)
+    static const size_t ShortSize;      //2 bytes
+    static const size_t LongSize;       //4 bytes
+    static const size_t RationalSize;   //8 bytes
+    static const size_t UndefinedSize;  //1 byte (*N)
+    static const size_t SLongSize;      //4 bytes
+    static const size_t SRationalSize;  //8 bytes
+
+    /**
+     * Id values used by Exif to identify type
+     */
+    static const ExifByte ByteId;         // 1
+    static const ExifByte ASCIIId;        // 2
+    static const ExifByte ShortId;        // 3
+    static const ExifByte LongId;         // 4
+    static const ExifByte RationalId;     // 5
+    static const ExifByte UndefinedId;    // 7
+    static const ExifByte SLongId;        // 9
+    static const ExifByte SRationalId;    //10
+};
+
+class ExifUtil
+{
+public:
+    ExifUtil();
+    virtual ~ExifUtil();
+
+    static ImageOrientation stringToOrientation(const std::string& orientation);
+    static const std::string& orientationToString(ImageOrientation value);
+
+    static WhiteBalanceMode stringToWhiteBalance(const std::string& white_balance);
+    static const std::string& whiteBalanceToString(WhiteBalanceMode value);
+
+    static ExposureProgram stringToExposureProgram(const std::string& exposure_program);
+    static const std::string& exposureProgramToString(ExposureProgram value);
+
+    static bool isValidAbsoluteURI(const std::string& uri);
+    static void getURIInfo(const std::string& uri,
+            const Filesystem::NodeType expected_type,
+            const std::string& required_permission,
+            bool& out_exists,
+            Filesystem::NodeType& out_type,
+            bool& out_permission_granted);
+
+    static std::string convertUriToPath(const std::string& str);
+    static std::string ltrim(const std::string& s);
+
+    static time_t exifDateTimeOriginalToTimeT(const char* string);
+    static std::string timeTToExifDateTimeOriginal(time_t time);
+
+    static size_t getSizeOfExifFormatType(ExifFormat format);
+    static void  printExifEntryInfo(ExifEntry* entry, ExifData* exif_data);
+
+    static void extractFromTimeT(const time_t time,
+            int& out_year, int& out_month, int& out_day,
+            int& out_hour, int& out_min, int& out_sec);
+
+    static time_t convertToTimeT(int year, int month, int day,
+            int hour, int min, int sec);
+};
+
+} // EXIF
+} // DeviceApi
+
+#endif // __TIZEN_EXIF_EXIFUTIL_H_
diff --git a/src/Exif/JSExifInformation.cpp b/src/Exif/JSExifInformation.cpp
new file mode 100644 (file)
index 0000000..38c6adb
--- /dev/null
@@ -0,0 +1,1372 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file    JSExifInformation.cpp
+ */
+
+#include "JSExifInformation.h"
+
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <GlobalContextManager.h>
+#include <JSSimpleCoordinates.h>
+#include <JSTZDate.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+#include "ExifUtil.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Time;
+
+struct ExifInformationHolder{
+    ExifInformationPtr ptr;
+};
+
+namespace {
+const char* TIZEN_INTERFACE_EXIF_INFORMATION = "ExifInformation";
+
+const char* EXIF_PROPERTY_URI = "uri";
+const char* EXIF_PROPERTY_WIDTH = "width";
+const char* EXIF_PROPERTY_HEIGHT = "height";
+const char* EXIF_PROPERTY_DEVICE_MAKER = "deviceMaker";
+const char* EXIF_PROPERTY_DEVICE_MODEL = "deviceModel";
+const char* EXIF_PROPERTY_ORIGINAL_TIME = "originalTime";
+const char* EXIF_PROPERTY_ORIENTATION = "orientation";
+const char* EXIF_PROPERTY_FNUMBER = "fNumber";
+const char* EXIF_PROPERTY_ISO_SPEED_RATINGS = "isoSpeedRatings";
+const char* EXIF_PROPERTY_EXPOSURE_TIME = "exposureTime";
+const char* EXIF_PROPERTY_EXPOSURE_PROGRAM = "exposureProgram";
+const char* EXIF_PROPERTY_FLASH = "flash";
+const char* EXIF_PROPERTY_FOCAL_LENGTH = "focalLength";
+const char* EXIF_PROPERTY_WHITE_BALANCE = "whiteBalance";
+const char* EXIF_PROPERTY_GPS_LOCATION = "gpsLocation";
+const char* EXIF_PROPERTY_GPS_ALTITUDE = "gpsAltitude";
+const char* EXIF_PROPERTY_GPS_PROCESSING_METHOD = "gpsProcessingMethod";
+const char* EXIF_PROPERTY_GPS_TIME = "gpsTime";
+const char* EXIF_PROPERTY_USER_COMMENT = "userComment";
+}
+
+JSClassDefinition JSExifInformation::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_INTERFACE_EXIF_INFORMATION,
+        0, //ParentClass
+        m_property, //StaticValues
+        NULL,
+        initialize,
+        finalize,
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL //ConvertToType
+};
+
+JSStaticValue JSExifInformation::m_property[] = {
+    { EXIF_PROPERTY_URI, getUri, setUri, kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_WIDTH, getWidth, setWidth, kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_HEIGHT, getHeight, setHeight, kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_DEVICE_MAKER, getDeviceMaker, setDeviceMaker,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_DEVICE_MODEL, getDeviceModel, setDeviceModel,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_ORIGINAL_TIME, getOriginalTime, setOriginalTime,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_ORIENTATION, getOrientation, setOrientation,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_FNUMBER, getFNumber, setFNumber, kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_ISO_SPEED_RATINGS, getIsoSpeedRatings, setIsoSpeedRatings,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_EXPOSURE_TIME, getExposureTime, setExposureTime,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_EXPOSURE_PROGRAM, getExposureProgram, setExposureProgram,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_FLASH, getFlash, setFlash, kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_FOCAL_LENGTH, getFocalLength, setFocalLength,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_WHITE_BALANCE, getWhiteBalance, setWhiteBalance,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_GPS_LOCATION, getGpsLocation, setGpsLocation,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_GPS_ALTITUDE, getGpsAltitude, setGpsAltitude,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_GPS_PROCESSING_METHOD, getGpsProcessingMethod, setGpsProcessingMethod,
+                kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_GPS_TIME, getGpsTime, setGpsTime, kJSPropertyAttributeDontDelete },
+    { EXIF_PROPERTY_USER_COMMENT, getUserComment, setUserComment,
+                kJSPropertyAttributeDontDelete },
+    {0,0,0,0}
+};
+
+JSClassRef JSExifInformation::m_jsClassRef = JSClassCreate(JSExifInformation::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSExifInformation::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSExifInformation::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+ExifInformationPtr JSExifInformation::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    ExifInformationHolder* priv = static_cast<ExifInformationHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+    return priv->ptr;
+}
+
+JSObjectRef JSExifInformation::makeJSObject(JSContextRef context, ExifInformationPtr native)
+{
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    ExifInformationHolder* priv = new (std::nothrow) ExifInformationHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (!obj) {
+        LOGE("Object creation failed");
+        delete priv;
+        priv = NULL;
+        throw UnknownException("Object creation failed");
+    }
+    return obj;
+}
+
+void JSExifInformation::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSExifInformation::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    ExifInformationHolder* priv =
+            static_cast<ExifInformationHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+
+}
+
+JSObjectRef DLL_EXPORT JSExifInformation::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        ExifInformationPtr priv = ExifInformationPtr(new (std::nothrow) ExifInformation());
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        if (!validator.isOmitted(0) && !validator.isNull(0)) {
+            JSObjectRef dictionary = NULL;
+            dictionary = validator.toObject(0, true);
+            if (dictionary) {
+                JSValueRef uri = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_URI);
+
+                JSValueRef width = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_WIDTH);
+
+                JSValueRef height = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_HEIGHT);
+
+                JSValueRef device_maker = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_DEVICE_MAKER);
+
+                JSValueRef device_model = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_DEVICE_MODEL);
+
+                JSValueRef original_time = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_ORIGINAL_TIME);
+
+                JSValueRef orientation = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_ORIENTATION);
+
+                JSValueRef f_number = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_FNUMBER);
+
+                JSValueRef iso_speed_ratings = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_ISO_SPEED_RATINGS);
+
+                JSValueRef exposure_time = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_EXPOSURE_TIME);
+
+                JSValueRef exposure_program = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_EXPOSURE_PROGRAM);
+
+                JSValueRef flash = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_FLASH);
+
+                JSValueRef focal_length = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_FOCAL_LENGTH);
+
+                JSValueRef white_balance = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_WHITE_BALANCE);
+
+                JSValueRef gps_location = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_GPS_LOCATION);
+
+                JSValueRef gps_altitude = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_GPS_ALTITUDE);
+
+                JSValueRef processing_method = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_GPS_PROCESSING_METHOD);
+
+                JSValueRef gps_time = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_GPS_TIME);
+
+                JSValueRef user_comment = JSUtil::getProperty(context,
+                    dictionary, EXIF_PROPERTY_USER_COMMENT);
+
+
+                if (!JSValueIsUndefined(context, uri)
+                        && !JSValueIsNull(context, uri)) {
+                    priv->setUri(JSUtil::JSValueToString(context, uri));
+                }
+
+                if (!JSValueIsUndefined(context, width)
+                        && !JSValueIsNull(context, width)) {
+                    priv->setWidth(JSUtil::JSValueToULong(context, width));
+                }
+
+                if (!JSValueIsUndefined(context, height)
+                        && !JSValueIsNull(context, height)) {
+                    priv->setHeight(JSUtil::JSValueToULong(context, height));
+                }
+
+                if (!JSValueIsUndefined(context, device_maker)
+                        && !JSValueIsNull(context, device_maker)) {
+                    priv->setDeviceMaker(
+                            JSUtil::JSValueToString(context, device_maker));
+                }
+
+                if (!JSValueIsUndefined(context, device_model)
+                        && !JSValueIsNull(context, device_model)) {
+                    priv->setDeviceModel(
+                            JSUtil::JSValueToString(context, device_model));
+                }
+
+                if (!JSValueIsUndefined(context, original_time)
+                        && !JSValueIsNull(context, original_time)) {
+                    priv->setOriginalTime(JSUtil::JSValueToTimeT(context, original_time));
+                }
+
+                if (!JSValueIsUndefined(context, orientation)
+                        && !JSValueIsNull(context, orientation)) {
+                    priv->setOrientation(ExifUtil::stringToOrientation(
+                            JSUtil::JSValueToString(context, orientation)));
+                }
+
+                if (!JSValueIsUndefined(context, f_number)
+                        && !JSValueIsNull(context, f_number)) {
+                    const double fnumber = JSUtil::JSValueToDouble(context, f_number);
+                    priv->setFNumber(Rational::createFromDouble(fnumber));
+                }
+
+                if (!JSValueIsUndefined(context, iso_speed_ratings)
+                        && !JSValueIsNull(context, iso_speed_ratings)) {
+                    priv->setIsoSpeedRatings(JSUtil::JSArrayToType_<long long int>(
+                        context, iso_speed_ratings, JSUtil::JSValueToLongLong));
+                }
+
+                if (!JSValueIsUndefined(context, exposure_time)
+                        && !JSValueIsNull(context, exposure_time)) {
+                    std::string exp_s = JSUtil::JSValueToString(context, exposure_time);
+                    priv->setExposureTime(Rational::createFromExposureTimeString(exp_s));
+                }
+
+                if (!JSValueIsUndefined(context, exposure_program)
+                        && !JSValueIsNull(context, exposure_program)) {
+                    priv->setExposureProgram(ExifUtil::stringToExposureProgram(
+                            JSUtil::JSValueToString(context, exposure_program)));
+                }
+
+                if (!JSValueIsUndefined(context, flash)
+                        && !JSValueIsNull(context, flash)) {
+                    priv->setFlash(JSUtil::JSValueToBoolean(context, flash));
+                }
+
+                if (!JSValueIsUndefined(context, focal_length)
+                        && !JSValueIsNull(context, focal_length)) {
+                    const double flength = JSUtil::JSValueToDouble(context, focal_length);
+                    priv->setFocalLength(Rational::createFromDouble(flength));
+                }
+
+                if (!JSValueIsUndefined(context, white_balance)
+                        && !JSValueIsNull(context, white_balance)) {
+                    priv->setWhiteBalanceMode(ExifUtil::stringToWhiteBalance(
+                            JSUtil::JSValueToString(context, white_balance)));
+                }
+
+                if (!JSValueIsUndefined(context, gps_location)
+                        && !JSValueIsNull(context, gps_location)) {
+                    priv->setGPSLocation(Tizen::JSSimpleCoordinates::getPrivateObject(
+                            context, gps_location));
+                }
+
+                if (!JSValueIsUndefined(context, gps_altitude)
+                        && !JSValueIsNull(context, gps_altitude)) {
+                    const double altitude = JSUtil::JSValueToDouble(context, gps_altitude);
+                    priv->setGpsAltitude(Rational::createFromDouble(altitude));
+                }
+
+                if (!JSValueIsUndefined(context, processing_method)
+                        && !JSValueIsNull(context, processing_method)) {
+                    priv->setGpsProcessingMethod(EXIF_UNDEFINED_TYPE_ASCII,
+                            JSUtil::JSValueToString(context, processing_method));
+                }
+
+                if (!JSValueIsUndefined(context, gps_time)
+                        && !JSValueIsNull(context, gps_time)) {
+                    Time::TZDatePtr new_tz_date = Time::JSTZDate::getPrivateObject(context, gps_time);
+                    priv->getExifGpsTime().setDateAndTime(new_tz_date);
+                }
+
+                if (!JSValueIsUndefined(context, user_comment)
+                        && !JSValueIsNull(context, user_comment)) {
+                    priv->setUserComment(EXIF_UNDEFINED_TYPE_ASCII,
+                            JSUtil::JSValueToString(context, user_comment));
+                }
+            }
+        }
+
+        ExifInformationHolder* holder = new (std::nothrow) ExifInformationHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(jsObjRef, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("ExifInformation creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("ExifInformation creation failed");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSExifInformation::getUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_URI)) {
+            return JSUtil::toJSValueRef(context, priv->getUri());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSExifInformation::setUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value) || JSValueIsUndefined(context, value)) {
+            //According to WIDL specification uri is not nullable
+            return true;
+        }
+
+        const std::string uri = JSUtil::JSValueToString(context, value);
+        priv->setUri(uri);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getWidth(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_WIDTH)) {
+            return JSUtil::toJSValueRef(context, priv->getWidth());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setWidth(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_WIDTH);
+            return true;
+        }
+
+        priv->setWidth(JSUtil::JSValueToULong(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getHeight(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_HEIGHT)) {
+            return JSUtil::toJSValueRef(context, priv->getHeight());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setHeight(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_HEIGHT);
+            return true;
+        }
+
+        priv->setHeight(JSUtil::JSValueToULong(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getDeviceMaker(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER)) {
+            return JSUtil::toJSValueRef(context, priv->getDeviceMaker());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setDeviceMaker(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MAKER);
+            return true;
+        }
+
+        priv->setDeviceMaker(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getDeviceModel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL)) {
+            return JSUtil::toJSValueRef(context, priv->getDeviceModel());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setDeviceModel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_DEVICE_MODEL);
+            return true;
+        }
+
+        priv->setDeviceModel(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getOriginalTime(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_ORIGINAL_TIME)) {
+            return JSUtil::makeDateObject(context, priv->getOriginalTime());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setOriginalTime(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_ORIGINAL_TIME);
+            return true;
+        }
+
+        priv->setOriginalTime(JSUtil::JSValueToTimeT(context, value));
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+JSValueRef JSExifInformation::getOrientation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_ORIENTATION)) {
+            return JSUtil::toJSValueRef(context,
+                ExifUtil::orientationToString(priv->getOrientation()));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setOrientation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_ORIENTATION);
+            return true;
+        }
+
+        const std::string orient_str = JSUtil::JSValueToString(context, value);
+        const ImageOrientation orient = ExifUtil::stringToOrientation(orient_str);
+        priv->setOrientation(orient);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+JSValueRef JSExifInformation::getFNumber(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_FNUMBER)) {
+            return JSUtil::toJSValueRef(context, priv->getFNumber().toDouble());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setFNumber(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_FNUMBER);
+            return true;
+        }
+
+        const double fnumber = JSUtil::JSValueToDouble(context, value);
+        priv->setFNumber(Rational::createFromDouble(fnumber));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getIsoSpeedRatings(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS)) {
+            auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+            return priv->getIsoSpeedRatings().getJSArray(g_ctx);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setIsoSpeedRatings(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_ISO_SPEED_RATINGS);
+            return true;
+        }
+
+        std::vector<long long int> ratings = JSUtil::JSArrayToType_<long long int>(
+            context, value, JSUtil::JSValueToLongLong);
+        priv->setIsoSpeedRatings(ratings);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+JSValueRef JSExifInformation::getExposureTime(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_TIME)) {
+            return JSUtil::toJSValueRef(context,
+                    priv->getExposureTime().toExposureTimeString());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setExposureTime(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_TIME);
+            return true;
+        }
+
+        const std::string exp_time_string = JSUtil::JSValueToString(context, value);
+        const Rational exp_time = Rational::createFromExposureTimeString(exp_time_string);
+        priv->setExposureTime(exp_time);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getExposureProgram(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_PROGRAM)) {
+            return JSUtil::toJSValueRef(context,
+                    ExifUtil::exposureProgramToString(priv->getExposureProgram()));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setExposureProgram(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_EXPOSURE_PROGRAM);
+            return true;
+        }
+
+        const std::string exp_prog_str = JSUtil::JSValueToString(context, value);
+        ExposureProgram exp_prog = ExifUtil::stringToExposureProgram(exp_prog_str);
+        priv->setExposureProgram(exp_prog);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getFlash(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_FLASH)) {
+            return JSUtil::toJSValueRef(context, priv->getFlash());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setFlash(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_FLASH);
+            return true;
+        }
+
+        priv->setFlash(JSUtil::JSValueToBoolean(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getFocalLength(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_FOCAL_LENGTH)) {
+            return JSUtil::toJSValueRef(context, priv->getFocalLength().toDouble());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setFocalLength(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_FOCAL_LENGTH);
+            return true;
+        }
+
+        const double flength = JSUtil::JSValueToDouble(context, value);
+        priv->setFocalLength(Rational::createFromDouble(flength));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getWhiteBalance(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_WHITE_BALANCE)) {
+            return JSUtil::toJSValueRef(context,
+                ExifUtil::whiteBalanceToString(priv->getWhiteBalanceMode()));
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setWhiteBalance(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_WHITE_BALANCE);
+            return true;
+        }
+
+        const std::string wb_mode_str = JSUtil::JSValueToString(context, value);
+        const WhiteBalanceMode wb_mode = ExifUtil::stringToWhiteBalance(wb_mode_str);
+        priv->setWhiteBalanceMode(wb_mode);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+JSValueRef JSExifInformation::getGpsLocation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        Tizen::SimpleCoordinatesPtr scoords = priv->getGPSLocation();
+        if (scoords) {
+            LOGD("Got: lat:%f long:%f", scoords->getLatitude(), scoords->getLongitude());
+            return Tizen::JSSimpleCoordinates::makeJSObject(context, scoords);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setGpsLocation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unsetGPSLocation();
+            return true;
+        }
+
+        auto scoords = Tizen::JSSimpleCoordinates::getPrivateObject(context, value);
+        if (scoords) {
+            LOGD("setGpsLocation: long:%f lat:%f", scoords->getLongitude(),
+                    scoords->getLatitude());
+            priv->setGPSLocation(scoords);
+        } else {
+            LOGW("Couldn't get SimpleCoordinates from JS value");
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getGpsAltitude(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE)) {
+            return JSUtil::toJSValueRef(context, priv->getGpsAltitudeWithRef());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setGpsAltitude(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE);
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_GPS_ALTITUDE_REF);
+            return true;
+        }
+
+        priv->setGpsAltitudeWithRef(JSUtil::JSValueToDouble(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getGpsProcessingMethod(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD)) {
+            return JSUtil::toJSValueRef( context, priv->getGpsProcessingMethod());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setGpsProcessingMethod(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_GPS_PROCESSING_METHOD);
+            return true;
+        }
+
+        priv->setGpsProcessingMethod(EXIF_UNDEFINED_TYPE_ASCII,
+                JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSExifInformation::getGpsTime(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        auto tzdate = priv->getGpsTime();
+        if (tzdate) {
+            return Time::JSTZDate::makeJSObject(context, tzdate);
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setGpsTime(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            LOGD("Nulled exif gps time");
+            priv->unsetGPStime();
+            return true;
+        }
+
+        Time::TZDatePtr new_tz_date = Time::JSTZDate::getPrivateObject(context, value);
+        priv->setGpsTime(new_tz_date);
+    }
+    catch (const BasePlatformException& ex) {
+        LOGE("Exception: %s", ex.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error");
+    }
+
+    return true;
+}
+
+JSValueRef JSExifInformation::getUserComment(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (priv->isSet(EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT)) {
+            //TODO: what to do with not ASCII coding: JIS/UNICODE/UNDEFINED ?
+            return JSUtil::toJSValueRef(context, priv->getUserComment());
+        }
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeNull(context);
+}
+
+bool JSExifInformation::setUserComment(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        ExifInformationPtr priv = JSExifInformation::getPrivateObject(context, object);
+        if (JSValueIsNull(context, value)) {
+            priv->unset(EXIF_INFORMATION_ATTRIBUTE_USER_COMMENT);
+            return true;
+        }
+
+        priv->setUserComment(EXIF_UNDEFINED_TYPE_ASCII,
+                JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+} // Exif
+} // DeviceAPI
diff --git a/src/Exif/JSExifInformation.h b/src/Exif/JSExifInformation.h
new file mode 100644 (file)
index 0000000..041be83
--- /dev/null
@@ -0,0 +1,399 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file    JSExifInformation.h
+ */
+
+#ifndef __TIZEN_JS_EXIF_INFORMATION_H__
+#define __TIZEN_JS_EXIF_INFORMATION_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "ExifInformation.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+class JSExifInformation {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static ExifInformationPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static JSObjectRef makeJSObject(JSContextRef context, ExifInformationPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared property.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * getUri operation.
+     */
+    static JSValueRef getUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setUri operation.
+     */
+    static bool setUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getWidth operation.
+     */
+    static JSValueRef getWidth(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setWidth operation.
+     */
+    static bool setWidth(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getHeight operation.
+     */
+    static JSValueRef getHeight(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setHeight operation.
+     */
+    static bool setHeight(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getDeviceMaker operation.
+     */
+    static JSValueRef getDeviceMaker(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setDeviceMaker operation.
+     */
+    static bool setDeviceMaker(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getDeviceModel operation.
+     */
+    static JSValueRef getDeviceModel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setDeviceModel operation.
+     */
+    static bool setDeviceModel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getOriginalTime operation.
+     */
+    static JSValueRef getOriginalTime(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setOriginalTime operation.
+     */
+    static bool setOriginalTime(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getOrientation operation.
+     */
+    static JSValueRef getOrientation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setOrientation operation.
+     */
+    static bool setOrientation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getFNumber operation.
+     */
+    static JSValueRef getFNumber(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setFNumber operation.
+     */
+    static bool setFNumber(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getIsoSpeedRatings operation.
+     */
+    static JSValueRef getIsoSpeedRatings(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setIsoSpeedRatings operation.
+     */
+    static bool setIsoSpeedRatings(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getExposureTime operation.
+     */
+    static JSValueRef getExposureTime(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setExposureTime operation.
+     */
+    static bool setExposureTime(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getExposureProgram operation.
+     */
+    static JSValueRef getExposureProgram(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setExposureProgram operation.
+     */
+    static bool setExposureProgram(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getFlash operation.
+     */
+    static JSValueRef getFlash(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setFlash operation.
+     */
+    static bool setFlash(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getFocalLength operation.
+     */
+    static JSValueRef getFocalLength(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setFocalLength operation.
+     */
+    static bool setFocalLength(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getWhiteBalance operation.
+     */
+    static JSValueRef getWhiteBalance(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setWhiteBalance operation.
+     */
+    static bool setWhiteBalance(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getGpsLocation operation.
+     */
+    static JSValueRef getGpsLocation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setGpsLocation operation.
+     */
+    static bool setGpsLocation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getGpsAltitude operation.
+     */
+    static JSValueRef getGpsAltitude(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setGpsAltitude operation.
+     */
+    static bool setGpsAltitude(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getGpsProcessingMethod operation.
+     */
+    static JSValueRef getGpsProcessingMethod(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setGpsProcessingMethod operation.
+     */
+    static bool setGpsProcessingMethod(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getGpsTime operation.
+     */
+    static JSValueRef getGpsTime(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setGpsTime operation.
+     */
+    static bool setGpsTime(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * getUserComment operation.
+     */
+    static JSValueRef getUserComment(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * setUserComment operation.
+     */
+    static bool setUserComment(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+};
+
+} // Exif
+} // DeviceAPI
+
+#endif // __TIZEN_JS_EXIF_INFORMATION_H__
diff --git a/src/Exif/JSExifManager.cpp b/src/Exif/JSExifManager.cpp
new file mode 100755 (executable)
index 0000000..55770fa
--- /dev/null
@@ -0,0 +1,276 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file    JSExifManager.cpp
+ */
+
+#include "JSExifManager.h"
+
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <SecurityExceptions.h>
+#include <TimeTracer.h>
+
+#include "ExifManager.h"
+#include "ExifUtil.h"
+#include "JSExifInformation.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace {
+const char* TIZEN_INTERFACE_EXIF_MANAGER = "ExifManager";
+
+const char* EXIF_FUNCTION_API_GET_EXIF_INFO = "getExifInfo";
+const char* EXIF_FUNCTION_API_SAVE_EXIF_INFO = "saveExifInfo";
+const char* EXIF_FUNCTION_API_GET_THUMBNAIL = "getThumbnail";
+}
+
+JSClassDefinition JSExifManager::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_INTERFACE_EXIF_MANAGER,
+        NULL, //ParentClass
+        NULL, //StaticValues
+        m_function,
+        initialize,
+        finalize,
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //HasInstance,
+        NULL //ConvertToType
+};
+
+JSStaticFunction JSExifManager::m_function[] = {
+        { EXIF_FUNCTION_API_GET_EXIF_INFO, getExifInfo,
+                kJSPropertyAttributeNone },
+        { EXIF_FUNCTION_API_SAVE_EXIF_INFO, saveExifInfo,
+                kJSPropertyAttributeNone },
+        { EXIF_FUNCTION_API_GET_THUMBNAIL, getThumbnail,
+                        kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+JSClassRef JSExifManager::m_jsClassRef = JSClassCreate(JSExifManager::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSExifManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSExifManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSExifManager::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+    JSObjectSetPrivate(object, static_cast<void*>(&ExifManager::getInstance()));
+}
+
+void JSExifManager::finalize(JSObjectRef object)
+{
+}
+
+JSValueRef JSExifManager::getExifInfo(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(1);
+    LOGD("Entered");
+
+    ExifInfoCallbackData* callback = NULL;
+    try {
+        //void getExifInfo (DOMString uri,
+        //                  ExifInformationSuccessCallback successCallback,
+        //                  optional ErrorCallback? errorCallback)
+        ArgumentValidator validator(context, argumentCount, arguments);
+        const std::string uri = validator.toString(0);
+
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new (std::nothrow) ExifInfoCallbackData(g_ctx, uri);
+        if (!callback) {
+            LOGE("Couldn't allocate callback - ExifInfoCallbackData");
+            throw Common::UnknownException("Memory allocation failed");
+        }
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        ExifManager::getInstance().getExifInfo(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error, cannot get exif information");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSExifManager::saveExifInfo(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(1);
+    LOGD("Entered");
+
+    ExifInfoCallbackData* callback = NULL;
+    Common::CallbackUserData* invalidUriCallback = NULL;
+       
+    try {
+        //void saveExifInfo(ExifInformation exifInfo,
+        //                  optional SuccessCallback? successCallback,
+        //                  optional ErrorCallback? errorCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        ExifInformationPtr exif_info = JSExifInformation::getPrivateObject(context,
+                validator.toObject(0));
+
+        if (!exif_info->isSet(EXIF_INFORMATION_ATTRIBUTE_URI)) {
+            LOGE("URI is not set!");
+            throw InvalidValuesException("URI in exifInfo is not set");
+        }
+
+       auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        if(!ExifUtil::isValidAbsoluteURI(exif_info->getUri())) {
+               LOGE("URI is not valid absolute URI: %s", exif_info->getUri().c_str());
+
+               invalidUriCallback = new Common::CallbackUserData(g_ctx);
+               if (!invalidUriCallback) {
+                   LOGE("Couldn't allocate callback - ExifInfoCallbackData");
+                   throw Common::UnknownException("Memory allocation failed");
+               }
+
+               invalidUriCallback->setSuccessCallback(validator.toFunction(1, true));
+               invalidUriCallback->setErrorCallback(validator.toFunction(2, true));
+               ExifManager::getInstance().saveExifInfoFailed(invalidUriCallback);
+
+        }else{
+               LOGE("URI is valid absolute URI: %s", exif_info->getUri().c_str());
+
+               callback = new (std::nothrow) ExifInfoCallbackData(g_ctx, exif_info->getUri());
+               if (!callback) {
+                   LOGE("Couldn't allocate callback - ExifInfoCallbackData");
+                   throw Common::UnknownException("Memory allocation failed");
+               }
+               callback->setExifInfo(exif_info);
+               callback->setSuccessCallback(validator.toFunction(1, true));
+               callback->setErrorCallback(validator.toFunction(2, true));
+               ExifManager::getInstance().saveExifInfo(callback);
+        }
+
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error, cannot save exif information");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSExifManager::getThumbnail(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(1);
+    LOGD("Entered");
+
+    GetThumbnailCallbackUserData* callback = NULL;
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        //void getThumbnail(DOMString uri,
+        //                  ExifThumbnailSuccessCallback successCallback,
+        //                  optional ErrorCallback? errorCallback);
+
+        // contentURI
+        const std::string uri = validator.toString(0);
+
+        auto g_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new (std::nothrow) GetThumbnailCallbackUserData(g_ctx, uri);
+        if (!callback) {
+            LOGE("Couldn't allocate callback - GetThumbnailCallbackUserData");
+            throw Common::UnknownException("Memory allocation failed");
+        }
+
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        ExifManager::getInstance().getThumbnail(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown Error, cannot get thumbnail");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // Exif
+} // DeviceAPI
diff --git a/src/Exif/JSExifManager.h b/src/Exif/JSExifManager.h
new file mode 100644 (file)
index 0000000..cacc60f
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file    JSExifManger.h
+ */
+
+#ifndef __TIZEN_JS_EXIF_MANAGER_H__
+#define __TIZEN_JS_EXIF_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Exif {
+
+class JSExifManager {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * getExifInfo operation.
+     */
+    static JSValueRef getExifInfo(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * saveExifInfo  operation.
+     */
+    static JSValueRef saveExifInfo(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * getThumbnail  operation.
+     */
+    static JSValueRef getThumbnail(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // Exif
+} // DeviceAPI
+
+#endif // __TIZEN_JS_EXIF_MANAGER_H__
diff --git a/src/Exif/JpegFile.cpp b/src/Exif/JpegFile.cpp
new file mode 100644 (file)
index 0000000..a03272e
--- /dev/null
@@ -0,0 +1,733 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+//
+// For details of JPEG file format see:
+// http://www.media.mit.edu/pia/Research/deepview/exif.html
+
+#include "JpegFile.h"
+
+#include <iomanip>
+#include <limits>
+#include <stdio.h>
+#include <sstream>
+
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+
+using namespace DeviceAPI::Common;
+
+namespace Exif {
+
+/**
+ * Size of maximal JPEG's section data length
+ * (since it is stored as unsigned short limit is 2^16 -1)
+ */
+const unsigned int MAX_JPEG_SECTION_DATA_SIZE = 65535;
+
+/**
+ * JPEG's section data length includes 2 bytes for length therefore we need to
+ * substract 2 from MAX_JPEG_SECTION_DATA_SIZE
+ */
+const unsigned int MAX_AVAILABLE_JPEG_SECTION_DATA_SIZE = MAX_JPEG_SECTION_DATA_SIZE - 2;
+
+bool isJpegMarker(const int value)
+{
+    return value >= JPEG_MARKER_LOWEST_ID && value <= JPEG_MARKER_HIGHEST_ID;
+}
+
+JpegMarker castToJpegMarker(const unsigned char byte)
+{
+    if (byte < JPEG_MARKER_LOWEST_ID || byte > JPEG_MARKER_HIGHEST_ID) {
+        return JPEG_MARKER_UNKNOWN;
+    }
+
+    return static_cast<JpegMarker>(byte);
+}
+
+long readUShortBE(unsigned char* src)
+{
+    return ((static_cast<long>(src[0]) << 8) | static_cast<long>(src[1]));
+}
+
+void writeUShortBE(unsigned short value, unsigned char* buffer)
+{
+    buffer[0] = static_cast<unsigned char>(value >> 8);
+    buffer[1] = static_cast<unsigned char>(value);
+}
+
+struct CArrayDeleter {
+  void operator()(void* buffer) { free(buffer); }
+};
+
+JpegFile::JpegFile() :
+    m_in_data(NULL),
+    m_in_data_size(0),
+    m_image_data(NULL),
+    m_image_size(0),
+    m_padding_data(NULL),
+    m_padding_data_size(0),
+    m_in_file(NULL),
+    m_out_file(NULL)
+{
+
+}
+
+JpegFile::~JpegFile()
+{
+    delete [] m_in_data;
+    m_in_data = NULL;
+    m_in_data_size = 0;
+
+    m_padding_data = NULL;
+    m_padding_data_size = 0;
+
+    for(SectionsVec::iterator it = m_sections.begin(); it != m_sections.end(); ++it) {
+        JpegFileSectionPtr cur = *it;
+
+        if (cur->exif_data) {
+            exif_data_unref(cur->exif_data);
+            cur->exif_data = NULL;
+        }
+
+        cur->data_ptr = NULL;
+        cur->size = 0;
+        cur->type = JPEG_MARKER_UNKNOWN;
+    }
+
+    m_image_data = NULL;
+    m_image_size = 0;
+
+    if (m_in_file) {
+        fclose(m_in_file);
+        m_in_file = NULL;
+    }
+
+    if (m_out_file) {
+        fclose(m_out_file);
+        m_out_file = NULL;
+    }
+}
+
+JpegFilePtr JpegFile::loadFile(const std::string& path)
+{
+    JpegFile* new_jpg = new (std::nothrow) JpegFile();
+    if (!new_jpg) {
+        LOGE("Couldn't allocate Jpegfile!");
+        throw UnknownException("Memory allocation failed");
+    }
+
+    JpegFilePtr jpg_ptr(new_jpg);
+    jpg_ptr->load(path);
+    return jpg_ptr;
+}
+
+void JpegFile::load(const std::string& path)
+{
+    LOGD("Entered file:%s", path.c_str());
+
+    m_source_file_path = path;
+
+    m_in_file = fopen(path.c_str(), "rb");
+    if (!m_in_file) {
+        LOGE("Couldn't open Jpeg file: [%s]", path.c_str());
+        throw NotFoundException("Could not open JPG file");
+    }
+
+    fseek(m_in_file, 0, SEEK_END);
+    const size_t in_file_size = static_cast<size_t>(ftell(m_in_file));
+    fseek(m_in_file, 0, SEEK_SET);
+    LOGD("JPEG file: [%s] size:%d", path.c_str(), in_file_size);
+    if (0 == in_file_size) {
+        LOGE("Input file [%s] is empty!", path.c_str());
+        throw UnknownException("JPEG file is invalid");
+    }
+
+    m_in_data = new (std::nothrow) unsigned char[in_file_size];
+    if (!m_in_data) {
+        LOGE("Couldn't allocate buffer with size: %d", in_file_size);
+        throw UnknownException("Memory allocation failed");
+    }
+
+    m_in_data_size = in_file_size;
+
+    const size_t read_bytes = fread(m_in_data, 1, m_in_data_size, m_in_file);
+    if (read_bytes != m_in_data_size) {
+        LOGE("Couldn't read all: %d bytes. Read only: %d bytes!", m_in_data_size,
+                read_bytes);
+        throw UnknownException("Could not read JPEG file");
+    }
+
+    if (fclose(m_in_file) == EOF) {
+        LOGE("Couldn't close input file: %s!", path.c_str());
+    }
+    m_in_file = NULL;
+
+    generateListOfSections();
+}
+
+std::string JpegFile::getPartOfFile(const size_t offset,
+        const size_t num_bytes_before,
+        const size_t num_bytes_after)
+{
+    long long int start = static_cast<long long int>(offset) - num_bytes_before;
+    if (start < 0) {
+        start = 0;
+    }
+
+    long long int end = static_cast<long long int>(offset) + num_bytes_after;
+    if (end >= m_in_data_size) {
+        end = m_in_data_size - 1;
+    }
+
+    std::stringstream ss;
+    ss << std::setfill('0') << std::setw(2) << std::hex;
+    for(long long int i = start; i <= end; ++i) {
+        ss << static_cast<int>(m_in_data[i]);
+    }
+    return ss.str();
+}
+
+
+void JpegFile::generateListOfSections()
+{
+    LOGD("Entered");
+
+    //JPEG starts with:
+    //FFD8 (2 bytes) - SOI Marker
+    //
+    //then:
+    //N sections - format of section:
+    //0xFF(1 byte) + Marker Number(1 byte) + Data size(2 bytes) + Data
+    //
+    //then:
+    //SOS 0xFF(1 byte) + Marker Number(1 byte) + Data size(2 bytes) + Data
+    //
+    //Image data
+    //
+    //FFD9 (2 bytes) - EOI Marker
+    //
+    //Warning: some images taken on Android contains some extra data at the end
+    //we will keep it in m_padding_data
+
+    m_padding_data = NULL;
+    m_padding_data_size = 0;
+
+    for(size_t offset = 0, iterration = 0; offset < m_in_data_size;++iterration) {
+
+        LOGD("offset:%d | Starting iteration: %d", offset, iterration);
+        const size_t search_len = 10;
+        size_t search_offset = 0;
+        for(search_offset = 0; search_offset < search_len; ++search_offset) {
+            //Skip bytes until first no 0xff
+            unsigned char& tmp_marker = m_in_data[offset + search_offset];
+            if (tmp_marker != 0xff) {
+                break;
+            }
+        }
+
+        if (search_len == search_offset) {
+            LOGE("offset:%d | Couldn't find marker! RAW DATA:{%s}", offset,
+                    getPartOfFile(offset, 0, 10).c_str());
+            throw UnknownException("JPEG file is invalid");
+        }
+
+        const size_t section_offset = offset + search_offset - 1;
+        unsigned char* section_begin = m_in_data + section_offset;
+
+        offset = section_offset;    //Move to section begin
+        LOGD("offset:%d | Moved to section begin", offset);
+
+        if (!isJpegMarker(section_begin[1])) {
+            LOGE("offset:%d | Is not valid marker: 0x%x RAW DATA:{%s}", offset,
+                    section_begin[1], getPartOfFile(section_offset,0,4).c_str());
+            throw UnknownException("JPEG file is invalid");
+        }
+
+        const JpegMarker cur_marker = castToJpegMarker(section_begin[1]);
+        LOGD("offset:%d | Found valid marker: 0x%x RAW DATA:{%s}", offset,
+                cur_marker,
+                getPartOfFile(section_offset,0,4).c_str());
+
+        offset += 2;    //Read 0xffxx marker tag - 2 bytes
+
+        JpegFileSectionPtr section;
+        {
+            JpegFileSection* sec = new (std::nothrow) JpegFileSection();
+            if (!sec) {
+                LOGE("Couldn't allocate JpegFileSection");
+                throw UnknownException("Memory allocation failed");
+            }
+
+            section = JpegFileSectionPtr(sec);
+        }
+
+        section->type = cur_marker;
+        m_sections.push_back(section);
+        if (cur_marker == JPEG_MARKER_SOI ||
+            cur_marker == JPEG_MARKER_EOI) {
+            LOGD("offset:%d | Found: %s marker, moving to next marker at:%d",
+                    section_offset, ((cur_marker == JPEG_MARKER_SOI) ? "SOI" : "EOI"),
+                    offset);
+
+            if(cur_marker == JPEG_MARKER_EOI && m_padding_data != NULL) {
+                LOGW("Padding data have been found - do not try to parse end of file");
+                break;
+            }
+        }
+        else {
+            //From JPEG/EXIF info:
+            // Please notice that "Data" contains Data size descriptor, if there is
+            // a Marker like this;
+            //
+            // FF C1 00 0C
+            // It means this Marker(0xFFC1) has 0x000C(equal 12)bytes of data. But the
+            // data size '12' includes "Data size" descriptor, it follows only 10 bytes of
+            // data after 0x000C.
+            //
+
+            const long total_section_len = readUShortBE(section_begin + 2); //Include data
+                                                                            //size 2 bytes
+
+            const long section_data_len = total_section_len - 2;            //Exclude data
+                                                                            //size 2 bytes
+
+            LOGD("offset:%d tag:0x%x | Read total_section_len:%d (data len:%d)",
+                    section_offset, cur_marker, total_section_len, section_data_len);
+
+            offset += 2;    //Read data size - 2 bytes
+
+            if (total_section_len < 0) {
+                LOGE("offset:%d tag:0x%x | Error: total_section_len is: %d < 0", offset,
+                        cur_marker, total_section_len);
+                throw UnknownException("JPEG file is invalid");
+            }
+
+            if (section_offset + 2 + total_section_len > m_in_data_size) {
+                LOGE("offset:%d tag:0x%x | Error: current section offset:%d"
+                        " + 2 + total_section_len:%d = %d is greater then file size:%d",
+                        offset, cur_marker,
+                        section_offset, total_section_len,
+                        section_offset + total_section_len, m_in_data_size);
+                throw UnknownException("JPEG file is invalid");
+            }
+
+            if (JPEG_MARKER_APP1 == cur_marker) {
+                //TODO: verify this
+                //-4 --> 0xFF(1 byte)+Marker Number(1 byte)+Data size(2 bytes))
+                //const unsigned int exif_data_size = section_length - 4;
+
+                const unsigned int exif_data_size = total_section_len + 2;
+                section->exif_data = exif_data_new_from_data (section_begin,
+                        exif_data_size);
+
+                LOGD("offset:%d tag:0x%x | Loading exif from offset:%d"
+                        " len:%d exif_data_new_from_data returned: %p",
+                        offset, cur_marker, section_offset, exif_data_size,
+                        section->exif_data);
+
+                if (!section->exif_data) {
+                    LOGW("offset:%d tag:0x%x | Couldn't load Exif!", offset, cur_marker);
+                }
+            }
+
+            //This just saves pointer not copying data
+            section->data_ptr = section_begin + 2 + 2; //2 bytes marker + 2 bytes data size
+            section->size = section_data_len;  //Exclude data size
+
+            if (JPEG_MARKER_SOS == cur_marker) {
+                //Calculate offset of first image data which is just after this SOS section
+                const size_t image_data_offset = section_offset + 2 + total_section_len;
+
+                //Calculate size of image data from start to expected EOI at end of file.
+                //
+                //-2 (exclude ending EOI marker (2 bytes)
+                size_t image_size = m_in_data_size - image_data_offset - 2;
+                LOGW("offset:%d tag:0x%x | Image data offset:%d Estimated image size:%d",
+                        offset, cur_marker, image_data_offset, image_size);
+
+                m_image_data = m_in_data + image_data_offset;
+
+                size_t eoi_tag_index = 0;
+                bool found_eoi_tag = searchForTagInBuffer(m_in_data + image_data_offset,
+                        m_in_data + m_in_data_size, JPEG_MARKER_EOI, eoi_tag_index);
+                if(!found_eoi_tag) {
+                    LOGE("Could not find EOI tag! Assume that there is no EOI and rest of "
+                            "JPEG file contains image data stream: image_size+= 2");
+                    image_size += 2; //Skip expected EOI tag which is not present
+                } else {
+                    LOGD("EOI tag found at offset: %d from SOS data", eoi_tag_index);
+
+                    if(eoi_tag_index != image_size) {
+                        LOGW("Estimated image size:%d doesn't match EOI tag index:%d"
+                                " delta:%d", image_size, eoi_tag_index,
+                                image_size - eoi_tag_index);
+
+                        LOGW("Setting image_size to EOI tag: %d", eoi_tag_index);
+                        image_size = eoi_tag_index;
+
+                        m_padding_data = m_image_data + image_size + 2; //(skip EOI tag)
+                        m_padding_data_size = (m_in_data + m_in_data_size) - m_padding_data;
+                        LOGW("Saving padding data from offset:%d with size:%d",
+                            m_padding_data - m_in_data, m_padding_data_size);
+                    }
+                }
+
+                m_image_size = image_size;
+
+                offset = image_data_offset + image_size;
+                LOGD("offset:%d tag:0x%x | SOS Offset moved to next marker", offset,
+                        cur_marker);
+            }
+            else {
+                offset += section_data_len;
+                LOGD("offset:%d tag:0x%x | Offset moved to next marker", offset, cur_marker);
+            }
+        }
+    }
+}
+
+bool JpegFile::searchForTagInBuffer(const unsigned char* buffer_start,
+        const unsigned char* buffer_end,
+        const JpegMarker marker,
+        size_t& out_index)
+{
+    LOGD("Entered start:%p end:%p marker:0x%x", buffer_start, buffer_end, marker);
+
+    if(!buffer_start) {
+        LOGE("buffer_start is NULL");
+        return false;
+    }
+
+    if(!buffer_end) {
+        LOGE("buffer_end is NULL");
+        return false;
+    }
+
+    if(buffer_end <= buffer_start) {
+        LOGE("buffer_end: %p <= buffer_start: %p", buffer_end, buffer_start);
+        return false;
+    }
+
+    LOGD("Bytes to scan: %d", static_cast<size_t>(buffer_end - buffer_start));
+    const unsigned char marker_uchar = static_cast<unsigned char>(marker);
+
+    for(const unsigned char* ptr = buffer_start; ptr < buffer_end; ++ptr) {
+
+        if((0xff == *ptr) && (ptr+1 < buffer_end)) {
+            if(marker_uchar == *(ptr+1)) {
+                out_index = static_cast<size_t>(ptr - buffer_start);
+                return true;
+            }
+        }
+    }
+
+    out_index = 0;
+    return false;
+}
+
+void JpegFile::setNewExifData(ExifData* new_exif_data)
+{
+    if (!new_exif_data) {
+        LOGE("Trying to set NULL exif_data!");
+        throw UnknownException("Could not save Exif in JPEG file");
+    }
+
+    JpegFileSectionPtr exif = getExifSection();
+    if (!exif) {
+        LOGW("Could't find Exif section - creating new one");
+        {
+            JpegFileSection* new_sec = new (std::nothrow) JpegFileSection();
+            if (!new_sec) {
+                LOGE("Couldn't allocate JpegFileSection");
+                throw UnknownException("Memory allocation failed");
+            }
+            new_sec->type = JPEG_MARKER_APP1;
+
+            exif = JpegFileSectionPtr(new_sec);
+        }
+
+        SectionsVec::iterator insert_it = m_sections.begin();
+        bool soi_is_present = false;
+
+        if (insert_it != m_sections.end()) {
+            if ((*insert_it)->type != JPEG_MARKER_SOI) {
+                LOGW("First section is not SOI - Start Of Image!");
+            }
+            else {
+                soi_is_present = true;
+            }
+        }
+
+        if (!soi_is_present) {
+            LOGW("SOI section is missing");
+            throw UnknownException("JPEG file is invalid");
+        }
+
+        //Insert new Exif sections just after SOI
+        ++insert_it;
+        if (insert_it != m_sections.begin()) {
+            m_sections.insert(insert_it, exif);
+        }
+        else {
+            //This shouldn't happen since we at lest need SOS and EOI sections
+            m_sections.push_back(exif);
+        }
+    }
+
+    //We don't want to save old data
+    exif->data_ptr = NULL;
+    exif->size = 0;
+
+    exif_data_unref(exif->exif_data);
+    exif_data_ref (new_exif_data);
+    exif->exif_data = new_exif_data;
+}
+
+ExifData* JpegFile::getExifData()
+{
+    JpegFileSectionPtr exif = getExifSection();
+    if (!exif) {
+        return NULL;
+    }
+
+    exif_data_ref(exif->exif_data);
+    return exif->exif_data;
+}
+
+void JpegFile::saveToFile(const std::string& out_path)
+{
+    LOGD("Entered out_path:%s", out_path.c_str());
+    try {
+        saveToFilePriv(out_path);
+    }
+    catch (...) {
+        LOGE("Exception occured during saveToFilePriv "
+                "original file: [%] new: [%s]",
+                m_source_file_path.c_str(),
+                out_path.c_str());
+
+        if (out_path == m_source_file_path) {
+
+            LOGD("Trying to recover broken JPEG file: [%s]", out_path.c_str());
+            //We were writing to source file and since something went wrong let's
+            //restore old file - we have it in m_in_data
+
+            FILE* outf = fopen(out_path.c_str(), "wb");
+            if (!outf) {
+                LOGE("Couldn't open output file: [%s] - JPEG file will not be restored!");
+            }
+            else {
+                size_t bytes_wrote = fwrite(m_in_data, 1, m_in_data_size, outf);
+                if (bytes_wrote != m_in_data_size) {
+                    LOGE("Couldn't restore whole JPEG! "
+                            "Only %d of %d bytes have been wrote!",
+                            bytes_wrote, m_in_data_size);
+                }
+                if (EOF == fclose(outf)) {
+                    LOGE("Couldn't close restore output file: [%s]", out_path.c_str());
+                }
+            }
+        }
+
+        throw;
+    }
+}
+
+void JpegFile::saveToFilePriv(const std::string& out_path)
+{
+    LOGD("Entered out_path:%s", out_path.c_str());
+
+    m_out_file = fopen(out_path.c_str(), "wb");
+    if (!m_out_file) {
+        LOGE("Couldn't open output file: %s", out_path.c_str());
+        throw UnknownException("Could not write JPEG file");
+    }
+
+    unsigned char tmp_buf[128];
+    size_t offset = 0;
+
+    int section_index = 0;
+    for(SectionsVec::iterator it = m_sections.begin();
+            it != m_sections.end();
+            ++it, ++ section_index) {
+
+        JpegFileSectionPtr cur = *it;
+        const JpegMarker cur_marker = cur->type;
+
+        LOGD("offset:%d | Section: %d marker 0x%x", offset, section_index, cur_marker);
+
+        size_t bytes_to_write = 0;
+        size_t bytes_wrote = 0;
+
+        tmp_buf[0] = 0xff;
+        tmp_buf[1] = cur_marker;
+        bytes_to_write += 2;
+
+        bool write_section_data = false;
+
+        bool write_exif_data = false;
+
+        std::unique_ptr<unsigned char, CArrayDeleter> exif_output_data;
+        unsigned int exif_output_size = 0;
+
+        if (cur_marker != JPEG_MARKER_SOI &&
+                cur_marker != JPEG_MARKER_EOI) {
+
+            unsigned short section_size = 2;
+            if (JPEG_MARKER_APP1 && cur->exif_data) {
+
+                unsigned char* tmp = NULL;
+                exif_data_save_data (cur->exif_data, &tmp, &exif_output_size);
+                if (!tmp || 0 == exif_output_size) {
+                    LOGE("Couldn't generate RAW Exif data!");
+                    throw UnknownException("Could not save Exif in JPEG file");
+                }
+
+                LOGD("offset:%d | Generated Exif RAW Data length:%d", offset,
+                        exif_output_size);
+
+                exif_output_data.reset(tmp);
+
+                if (exif_output_size > MAX_AVAILABLE_JPEG_SECTION_DATA_SIZE) {
+                    LOGE("exif_output_size:%d is greater then maximum JPEG section"
+                            "data block size: %d", exif_output_size,
+                            MAX_AVAILABLE_JPEG_SECTION_DATA_SIZE);
+                    throw UnknownException("Exif data is to big to be saved in JPEG file");
+                }
+                section_size += exif_output_size;
+                write_exif_data = true;
+            }
+            else {
+                section_size += cur->size;
+                write_section_data = true;
+            }
+
+            writeUShortBE(section_size, tmp_buf + bytes_to_write);
+            bytes_to_write += 2;
+        }
+
+        LOGD("offset:%d | Writing section: marker:0x%x size:%d", offset, cur_marker,
+                cur->size);
+
+        bytes_wrote = fwrite(tmp_buf, 1, bytes_to_write, m_out_file);
+        offset += bytes_wrote;
+
+        if (bytes_wrote != bytes_to_write) {
+            LOGE("Couldn't wrote %d bytes! Only %d bytes wrote", bytes_to_write,
+                    bytes_wrote);
+            throw UnknownException("Could not write JPEG file");
+        }
+
+        if (write_section_data && cur->size > 0) {
+            LOGD("offset:%d | Writing data with length:%d", offset, cur->size);
+
+            bytes_to_write = cur->size;
+            bytes_wrote = fwrite(cur->data_ptr, 1, bytes_to_write, m_out_file);
+            offset += bytes_wrote;
+
+            if (bytes_wrote != bytes_to_write) {
+                LOGE("Couldn't wrote %d bytes! Only %d bytes wrote", bytes_to_write,
+                        bytes_wrote);
+                throw UnknownException("Could not write JPEG file");
+            }
+        }
+
+        if (write_exif_data && exif_output_data && exif_output_size > 0) {
+            LOGD("offset:%d | Writing new exif data with length:%d", offset,
+                    exif_output_size);
+
+            bytes_to_write = exif_output_size;
+            bytes_wrote = fwrite(exif_output_data.get(), 1, bytes_to_write, m_out_file);
+            offset += bytes_wrote;
+
+            if (bytes_wrote != bytes_to_write) {
+                LOGE("Couldn't wrote %d bytes! Only %d bytes wrote", bytes_to_write,
+                        bytes_wrote);
+                throw UnknownException("Could not write JPEG file");
+            }
+        }
+
+        if (JPEG_MARKER_SOS == cur_marker) {
+            LOGD("offset:%d | Writing image data stream with lenght:%d", offset,
+                    m_image_size);
+
+            bytes_to_write = m_image_size;
+            bytes_wrote = fwrite(m_image_data, 1, bytes_to_write, m_out_file);
+            offset += bytes_wrote;
+
+            if (bytes_wrote != bytes_to_write) {
+                LOGE("Couldn't wrote %d bytes! Only %d bytes wrote", bytes_to_write,
+                        bytes_wrote);
+                throw UnknownException("Could not write JPEG file");
+            }
+        }
+    }
+
+    if(m_padding_data && m_padding_data_size > 0) {
+        LOGD("Padding data exists and contains:%d bytes saving to JPEG file");
+        const size_t bytes_wrote = fwrite(m_image_data, 1, m_padding_data_size,
+                m_out_file);
+
+        if (bytes_wrote != m_padding_data_size) {
+            LOGE("Couldn't wrote %d bytes! Only %d bytes wrote", m_padding_data_size,
+                    bytes_wrote);
+            throw UnknownException("Could not write JPEG file");
+        }
+    }
+
+    if (fclose(m_out_file) == EOF) {
+        LOGE("Couldn't close output file: %s", out_path.c_str());
+        m_out_file = NULL;
+    }  else {
+        m_out_file = NULL;
+        LOGD("Closed output file: %s wrote:%d bytes: %d", out_path.c_str(), offset);
+    }
+}
+
+JpegFileSectionPtr JpegFile::getExifSection()
+{
+    size_t num_exif_sections = 0;
+    JpegFileSectionPtr first_exif_section;
+
+    for(SectionsVec::iterator it = m_sections.begin(); it != m_sections.end(); ++it) {
+        JpegFileSectionPtr cur = *it;
+
+        if (JPEG_MARKER_APP1 == cur->type) {
+            if (!cur->exif_data) {
+                LOGW("Warning: found APP1 section but exif_data is NULL (Not Exif?)");
+                continue;
+            }
+
+            ++num_exif_sections;
+            if (!first_exif_section) {
+                first_exif_section = cur;
+            }
+            else {
+                LOGW("Warning: found %d APP1/Exif sections - only first is currently supported!");
+            }
+        }
+    }
+
+    return first_exif_section;
+}
+
+
+} // namespace Exif
+} // namespace DeviceAPI
diff --git a/src/Exif/JpegFile.h b/src/Exif/JpegFile.h
new file mode 100644 (file)
index 0000000..bde6959
--- /dev/null
@@ -0,0 +1,138 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_EXIF_JPEG_FILE_H_
+#define __TIZEN_EXIF_JPEG_FILE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+#include <stdio.h>
+#include <map>
+#include <libexif/exif-data.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-utils.h>
+
+namespace DeviceAPI {
+namespace Exif {
+
+enum JpegMarker{
+    JPEG_MARKER_UNKNOWN     = 0x00,
+    JPEG_MARKER_LOWEST_ID   = 0xc0,
+    JPEG_MARKER_SOI         = 0xd8, //Start Of Image
+    JPEG_MARKER_EOI         = 0xd9, //End Of Image
+    JPEG_MARKER_SOS         = 0xda, //Start Of Stream
+    JPEG_MARKER_APP1        = 0xe1, //Application Data 1 - for Exif
+    JPEG_MARKER_HIGHEST_ID  = 0xfe
+};
+
+struct JpegFileSection;
+typedef std::shared_ptr<JpegFileSection> JpegFileSectionPtr;
+
+struct JpegFileSection
+{
+    JpegFileSection() :
+        type(JPEG_MARKER_UNKNOWN),
+        data_ptr(NULL),
+        size(0),
+        exif_data(NULL) {};
+
+    JpegMarker type;
+    unsigned char* data_ptr;
+    unsigned short size;
+
+    ExifData* exif_data;
+};
+
+
+class JpegFile;
+typedef std::shared_ptr<JpegFile> JpegFilePtr;
+
+class JpegFile {
+public:
+    static JpegFilePtr loadFile(const std::string& path);
+    ~JpegFile();
+
+    void setNewExifData(ExifData* new_exif_data);
+
+    /**
+     * You are responsible to unreference returned data with: exif_data_unref(...)
+     * Example:
+     *     ExifData* ed = jpeg.getExifData();
+     *     if(ed) {
+     *         doSth(ed);
+     *         exif_data_unref(ed);
+     *     }
+     */
+    ExifData* getExifData();
+
+    void saveToFile(const std::string& out_path);
+
+private:
+    JpegFile();
+    void load(const std::string& path);
+    void generateListOfSections();
+
+    std::string getPartOfFile(const size_t offset,
+            const size_t num_bytes_before = 10,
+            const size_t num_bytes_after = 10);
+
+    JpegFileSectionPtr getExifSection();
+    void saveToFilePriv(const std::string& out_path);
+
+    /**
+     * Search for first occurence of specific tag inside buffer.
+     *
+     * buffer_end is the first byte that should not be checked:
+     * [buffer_start ... buffer_end)
+     *
+     * For example EOI - search for first 'ffd9' in buffer
+     */
+    static bool searchForTagInBuffer(const unsigned char* buffer_start,
+            const unsigned char* buffer_end,
+            const JpegMarker marker,
+            size_t& out_index);
+
+    std::string m_source_file_path;
+
+    unsigned char* m_in_data;
+    size_t m_in_data_size;
+
+    unsigned char* m_image_data;
+    size_t m_image_size;
+
+    /**
+     * This contains any bytes after EOI.
+     * Usually there should be no extra bytes after EOI unfortunately
+     * some cameras saves extra bytes (for example Android).
+     */
+    unsigned char* m_padding_data;
+    size_t m_padding_data_size;
+
+    FILE* m_in_file;
+    FILE* m_out_file;
+
+    typedef std::vector<JpegFileSectionPtr> SectionsVec;
+    SectionsVec m_sections;
+};
+
+
+} // namespace Exif
+} // namespace DeviceApi
+
+#endif // __TIZEN_EXIF_JPEG_FILE_H_
diff --git a/src/Exif/Rational.cpp b/src/Exif/Rational.cpp
new file mode 100644 (file)
index 0000000..3b7c49f
--- /dev/null
@@ -0,0 +1,270 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "Rational.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Exif {
+
+namespace {
+const double DOUBLE_ERROR_REPRESENTATION = static_cast<double>(0x7FFFFFFF);
+} //anonymous namespace
+
+Rational::Rational() :
+        nominator(0),
+        denominator(0)
+{
+}
+
+Rational::Rational(ExifLong nom, ExifLong denom) :
+        nominator(nom),
+        denominator(denom)
+{
+}
+
+Rational::Rational(const ExifRational& exif_rational) :
+        nominator(exif_rational.numerator),
+        denominator(exif_rational.denominator)
+{
+}
+
+Rational Rational::createFromDouble(const double value, const long precision)
+{
+    LOGD("Entered value:%f precision:%d", value, precision);
+    if (value < 0.0) {
+        LOGW("Trying to create negative Rational: %f!", value);
+        return Rational();
+    }
+
+    if (value < 0.000000001) {
+        LOGD("Skipping calculation returning: Rational(0,1)");
+        return Rational(0,1);
+    }
+
+    long m[2][2];
+    double x, startx;
+    long ai;
+
+    startx = x = value;
+
+    // initialize matrix
+    m[0][0] = m[1][1] = 1;
+    m[0][1] = m[1][0] = 0;
+
+    //loop finding terms until denom gets too big
+    do {
+        ai = static_cast<long>(x);
+        if(m[1][0] * ai + m[1][1] > precision) {
+            break;
+        }
+
+        long t = m[0][0] * ai + m[0][1];
+        m[0][1] = m[0][0];
+        m[0][0] = t;
+
+        t = m[1][0] * ai + m[1][1];
+        m[1][1] = m[1][0];
+        m[1][0] = t;
+
+        if (x == static_cast<double>(ai)) {
+            break;     // AF: division by zero
+        }
+
+        x = 1 / (x - static_cast<double>(ai));
+        if (x > DOUBLE_ERROR_REPRESENTATION) {
+            break;  // AF: representation failure
+        }
+    } while(1);
+
+    // now remaining x is between 0 and 1/ai
+    // approx as either 0 or 1/m where m is max that will fit in precision
+    // first try zero
+    const double error0 = startx - ((double) m[0][0] / (double) m[1][0]);
+    const long numerator0 = m[0][0];
+    const long denominator0 = m[1][0];
+
+    LOGD("%ld/%ld, error = %e\n", numerator0, denominator0, error0);
+
+    /* now try other possibility */
+    ai = (precision - m[1][1]) / m[1][0];
+    m[0][0] = m[0][0] * ai + m[0][1];
+    m[1][0] = m[1][0] * ai + m[1][1];
+
+    double error1m = startx -
+            (static_cast<double>(m[0][0]) / static_cast<double>(m[1][0]));
+    LOGD("%ld/%ld, error = %e\n", m[0][0], m[1][0], error1m );
+
+    long result_numerator = 0;
+    long result_denominator = 0;
+
+    if (error0 < error1m ) {
+        result_numerator = numerator0;
+        result_denominator = denominator0;
+    }
+    else {
+        result_numerator = m[0][0];
+        result_denominator = m[1][0];
+    }
+
+    if (result_numerator < 0) {
+        result_numerator *= -1;
+    }
+    if (result_denominator < 0) {
+        result_denominator *= -1;
+    }
+
+    LOGD("Rational(%d, %d) error0 < error1m:%d", result_numerator, result_denominator,
+            error0 < error1m);
+
+    return Rational(numerator0, denominator0);
+}
+
+Rational Rational::createInvalid()
+{
+    return Rational(0,0);
+}
+
+bool Rational::isValid() const
+{
+    if (0 == denominator) {
+        return false;
+    }
+    else {
+        return true;
+    }
+}
+
+double Rational::toDouble() const
+{
+    if (!isValid()) {
+        return NAN;
+    }
+
+    return (double)nominator / (double)denominator;
+}
+
+Rational Rational::createFromExposureTimeString(const std::string& exp_time)
+{
+    LOGD("Entered");
+    if (exp_time.length() == 0) {
+        return Rational::createInvalid();  //lets assume that empty string means 0,
+                                           //however exposure time = 0 is not valid value
+    }
+
+    std::string integer_part;
+    std::string fraction_part;
+
+    int first_space_at = -1;
+    int first_slash_at = -1;
+
+    for(size_t i=0; i < exp_time.size(); ++i) {
+
+        const char& cur = exp_time[i];
+        if (first_space_at < 0 && ' ' == cur) {
+            first_space_at = i;
+        }
+        if (first_slash_at < 0 && '/' == cur) {
+            first_slash_at = i;
+        }
+    }
+
+    if (first_slash_at > 0) {
+        if (first_space_at > 0) {
+            integer_part = exp_time.substr(0,first_space_at);
+            fraction_part = exp_time.substr(first_space_at+1,
+                    exp_time.size() - (first_space_at+1));
+        }
+        else {
+            fraction_part = exp_time;
+        }
+    }
+    else {
+        integer_part = exp_time;
+    }
+
+    LOGD("first_space_at: %d first_slash_at:%d int: [%s] , frac: [%s]",
+            first_space_at, first_slash_at, integer_part.c_str(), fraction_part.c_str());
+
+    long integer_value = 0;
+    long nominator = 0;
+    long denominator = 1;
+
+    if (integer_part.length() > 0) {
+        integer_value = atol(integer_part.c_str());
+    }
+
+    if (fraction_part.length() > 0) {
+        if (sscanf(fraction_part.c_str(), "%ld/%ld", &nominator, &denominator) != 2) {
+            LOGD("Failed to parse nominator/denominator string: [%s]",
+                    fraction_part.c_str());
+            return Rational::createInvalid();
+        }
+    }
+
+    nominator += denominator * integer_value;
+    LOGD("%d/%d -> %f", nominator, denominator, (float)nominator / denominator);
+
+    if (0 == nominator) {
+        //Exposure time = 0 is invalid value
+        return Rational::createInvalid();
+    }
+
+    return Rational(nominator, denominator);
+}
+
+std::string Rational::toString() const
+{
+    std::stringstream ss;
+    ss << nominator << "/" << denominator;
+    return ss.str();
+}
+
+std::string Rational::toExposureTimeString() const
+{
+    LOGD("Entered");
+    if (!isValid() || 0 == nominator) {
+        return std::string();
+    }
+
+    std::string output_str;
+
+    if (nominator < denominator) {
+        output_str = toString();
+    }
+    else if (nominator % denominator == 0) {
+        std::stringstream ss;
+        ss << nominator / denominator;
+        output_str = ss.str();
+    }
+    else {
+        ExifLong new_nominator = nominator % denominator;
+        ExifLong new_denominator = denominator;
+        ExifLong integer_value = nominator / denominator;
+
+        std::stringstream ss;
+        ss << integer_value << " ";
+        ss << new_nominator << "/" << new_denominator;
+        output_str = ss.str();
+    }
+
+    return output_str;
+}
+
+} // Exif
+} // DeviceAPI
\ No newline at end of file
diff --git a/src/Exif/Rational.h b/src/Exif/Rational.h
new file mode 100644 (file)
index 0000000..4903759
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_EXIF_RATIONAL_H_
+#define __TIZEN_EXIF_RATIONAL_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+
+#include <libexif/exif-utils.h>
+#include <libexif/exif-entry.h>
+#include <libexif/exif-data.h>
+
+#include "ExifUtil.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+class Rational;
+typedef std::vector<Rational> Rationals;
+typedef std::shared_ptr<Rationals> RationalsPtr;
+
+/**
+ * This class represents fraction as nominator/denominator - two ExifLong values
+ * Rational type is present in Exif specification - used for example in GPS coordinates
+ */
+class Rational
+{
+public:
+    /**
+     * Default constructor sets to 0/0 - invalud rational number
+     */
+    Rational();
+
+    Rational(ExifLong nom, ExifLong denom);
+    Rational(const ExifRational& exif_rational);
+
+    static Rational createFromDouble(const double value, const long precision = 1000);
+    static Rational createInvalid();
+
+    /**
+     * Returns true if denominator is valid (!= 0) and therefore whole Rational is valid
+     */
+    bool isValid() const;
+
+    double toDouble() const;
+
+    /**
+     * Returns string in format: nominator/denominator,
+     * for example: "1/4", "1/1", "5/3".
+     *
+     */
+    std::string toString() const;
+
+    /**
+     * Create rational number from exposure string
+     * Accepted format "(integer) (nominator/denominator)"
+     * for example:
+     * "1/5", "4/5" - just fraction part
+     * "1", "5" - just integer part
+     * "1 1/5", "4 1/4" - integer + fraction part
+     */
+    static Rational createFromExposureTimeString(const std::string& exp_time);
+
+    /**
+     * Return time exposure string in following format:
+     *
+     * nominator < denominator                               : "1/5", "4/5"
+     * nominator == x*denominator                            : "1", "5"
+     * nominator > denominator && nominator != x*denominator : "1 1/5", "4 1/4"
+     */
+    std::string toExposureTimeString() const;
+
+    ExifLong nominator;
+    ExifLong denominator;
+};
+
+} // Exif
+} // DeviceApi
+
+#endif // __TIZEN_EXIF_RATIONAL_H_
\ No newline at end of file
diff --git a/src/Exif/config.xml b/src/Exif/config.xml
new file mode 100644 (file)
index 0000000..d4e3591
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-exif.so</library-name>
+    <feature-install-uri>exif.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/exif</name>
+    </api-feature>
+</plugin-properties>
diff --git a/src/Exif/plugin_config.cpp b/src/Exif/plugin_config.cpp
new file mode 100644 (file)
index 0000000..a6130b8
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+
+#include <iostream>
+#include <map>
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Exif {
+
+static FunctionMapping createExifFunctions();
+
+static FunctionMapping ExifFunctions =
+    createExifFunctions();
+
+#pragma GCC visibility push(default)
+DEFINE_FUNCTION_GETTER(Exif, ExifFunctions);
+#pragma GCC visibility pop
+
+static FunctionMapping createExifFunctions()
+{
+    /**
+     * Functions
+     */
+    FunctionMapping exifMapping;
+
+    return exifMapping;
+}
+
+}
+}
diff --git a/src/Exif/plugin_config.h b/src/Exif/plugin_config.h
new file mode 100644 (file)
index 0000000..eee5527
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _EXIF_PLUGIN_CONFIG_H_
+#define _EXIF_PLUGIN_CONFIG_H_
+
+#include <string>
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Exif {
+
+DECLARE_FUNCTION_GETTER(Exif);
+
+#define EXIF_CHECK_ACCESS(functionName)                          \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(      \
+        getExifFunctionData,                                     \
+        functionName)
+
+}
+}
+#endif // _EXIF_PLUGIN_CONFIG_H_
+
diff --git a/src/Exif/plugin_config_impl.h b/src/Exif/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..1f07ee5
--- /dev/null
@@ -0,0 +1,25 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _EXIF_PLUGIN_CONFIG_IMPL_H_
+#define _EXIF_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_EXIF_MANAGER_CLASS "exif"
+#define TIZEN_EXIF_EXIF_INFORMATION_INTERFACE "ExifInformation"
+
+#endif //_EXIF_PLUGIN_CONFIG_IMPL_H_
+
diff --git a/src/Exif/plugin_initializer.cpp b/src/Exif/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..0061b31
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+
+#include "JSExifInformation.h"
+#include "JSExifManager.h"
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Exif {
+
+class_definition_options_t ConstructorClassOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED,
+    NULL,
+    NULL,
+    NULL
+};
+
+class_definition_options_t ClassOptions =
+{
+    JS_CLASS,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    IGNORED,
+    NULL,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Exif] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Exif] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "Exif";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Exif] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Exif] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START (on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP (on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD (on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD (on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_EXIF_MANAGER_CLASS,
+        (js_class_template_getter) JSExifManager::getClassRef,
+        &ClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_EXIF_EXIF_INFORMATION_INTERFACE,
+        (js_class_template_getter)JSExifInformation::getClassRef,
+        (js_class_constructor_cb_t)JSExifInformation::constructor,
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_END
+}}
diff --git a/src/FMRadio/CMakeLists.txt b/src/FMRadio/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..18a2c1c
--- /dev/null
@@ -0,0 +1,52 @@
+
+SET(TARGET_NAME ${fmradio_target})
+SET(DESTINATION_NAME ${fmradio_dest})
+SET(TARGET_IMPL_NAME ${fmradio_impl})
+
+PKG_CHECK_MODULES(fmradio REQUIRED capi-media-radio capi-system-runtime-info)
+
+INCLUDE_DIRECTORIES(
+    ${TOP}/Common
+    ${fmradio_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${timeutil_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSFMRadioManager.cpp
+    FMRadioManager.cpp
+    FMRadioCallback.cpp
+    FMRadioUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${timeutil_impl}
+    ${fmradio_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/fmradio
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/FMRadio/FMRadioCallback.cpp b/src/FMRadio/FMRadioCallback.cpp
new file mode 100755 (executable)
index 0000000..eff9cca
--- /dev/null
@@ -0,0 +1,165 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSUtil.h>
+#include <Logger.h>
+#include <string>
+
+#include "FMRadioCallback.h"
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+FMRadioScanCallback::FMRadioScanCallback(JSContextRef context, JSObjectRef eventCbObj,
+        JSObjectRef errorCbObj)
+{
+    mCallbackUserData = new MultiCallbackUserData(context);
+
+    mContext = context;
+
+    if (!mFrequencies.empty()) {
+        mFrequencies.clear();
+    }
+
+    //onfrequencyfound
+    JSValueRef onfrequencyfoundCb = JSUtil::getProperty(context, eventCbObj, "onfrequencyfound");
+    if (!JSValueIsUndefined(context, onfrequencyfoundCb)) {
+        JSObjectRef onfrequencyfoundCbObj = JSUtil::JSValueToObject(context, onfrequencyfoundCb);
+        mCallbackUserData->setCallback("onfrequencyfound", onfrequencyfoundCbObj);
+    }
+
+    //onfinished
+    JSValueRef onfinishedCb = JSUtil::getProperty(context, eventCbObj, "onfinished");
+    if (!JSValueIsUndefined(context, onfinishedCb)) {
+        JSObjectRef onfinishedCbObj = JSUtil::JSValueToObject(context, onfinishedCb);
+        mCallbackUserData->setCallback("onfinished", onfinishedCbObj);
+    }
+
+    //onerror
+    if (errorCbObj != NULL) {
+        mCallbackUserData->setCallback("onerror", errorCbObj);
+    }
+}
+
+FMRadioScanCallback::~FMRadioScanCallback()
+{
+    if (mCallbackUserData != NULL) {
+        delete mCallbackUserData;
+    }
+}
+
+void FMRadioScanCallback::setFreqeuncy(int frequency)
+{
+    mFrequency = frequency;
+}
+
+int FMRadioScanCallback::getFrequency()
+{
+    return mFrequency;
+}
+
+void FMRadioScanCallback::onfrequencyfound()
+{
+    LOGD("Enter");
+    double freq = 0.0;
+    freq = (double) mFrequency / 1000;
+    mFrequencies.push_back(freq);
+
+    JSValueRef frequencyObj = JSUtil::toJSValueRef(mCallbackUserData->getContext(), freq);
+
+    mCallbackUserData->invokeCallback("onfrequencyfound", frequencyObj);
+
+}
+
+void FMRadioScanCallback::onfinished()
+{
+    LOGD("Enter");
+    JSValueRef jsResult = JSUtil::toJSValueRef(mCallbackUserData->getContext(), mFrequencies);
+
+    mCallbackUserData->invokeCallback("onfinished", jsResult);
+}
+
+void FMRadioScanCallback::onerror(JSValueRef errorObj)
+{
+    LOGD("Enter");
+    mCallbackUserData->invokeCallback("onerror", errorObj);
+}
+
+JSContextRef FMRadioScanCallback::getContext()
+{
+    return mContext;
+}
+
+FMRadioInterruptcallback::FMRadioInterruptcallback(JSContextRef context, JSObjectRef eventCbObj)
+{
+    LOGD("Enter");
+    mCallbackUserData = new MultiCallbackUserData(context);
+    mContext = context;
+
+    //oninterrupted
+    JSValueRef oninterruptedCb = JSUtil::getProperty(context, eventCbObj, "oninterrupted");
+    if (!JSValueIsUndefined(context, oninterruptedCb)) {
+        JSObjectRef oninterruptedObj = JSUtil::JSValueToObject(context, oninterruptedCb);
+        mCallbackUserData->setCallback("oninterrupted", oninterruptedObj);
+    }
+
+    //oninterruptfinished
+    JSValueRef oninterruptfinishedCb = JSUtil::getProperty(context, eventCbObj,
+            "oninterruptfinished");
+    if (!JSValueIsUndefined(context, oninterruptfinishedCb)) {
+        JSObjectRef oninterruptfinishedCbObj = JSUtil::JSValueToObject(context,
+                oninterruptfinishedCb);
+        mCallbackUserData->setCallback("oninterruptfinished", oninterruptfinishedCbObj);
+    }
+}
+
+FMRadioInterruptcallback::~FMRadioInterruptcallback()
+{
+    if (mCallbackUserData != NULL) {
+        delete mCallbackUserData;
+    }
+}
+
+void FMRadioInterruptcallback::oninterrupted(std::string message)
+{
+
+    JSValueRef jsResult = JSUtil::toJSValueRef(mCallbackUserData->getContext(), message);
+    mCallbackUserData->invokeCallback("oninterrupted", jsResult);
+}
+
+void FMRadioInterruptcallback::oninterruptfinished()
+{
+    mCallbackUserData->invokeCallback("oninterruptfinished");
+}
+
+JSContextRef FMRadioInterruptcallback::getContext()
+{
+    return mContext;
+}
+
+void FMRadioInterruptcallback::setCode(radio_interrupted_code_e code)
+{
+    mCode = code;
+}
+
+radio_interrupted_code_e FMRadioInterruptcallback::getCode()
+{
+    return mCode;
+}
+
+}
+}
diff --git a/src/FMRadio/FMRadioCallback.h b/src/FMRadio/FMRadioCallback.h
new file mode 100755 (executable)
index 0000000..210373c
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_FMRADIO_CALLBACK_H_
+#define __TIZEN_FMRADIO_CALLBACK_H_
+
+#include <MultiCallbackUserData.h>
+#include <vector>
+#include <radio.h>
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+using namespace DeviceAPI::Common;
+
+class FMRadioScanCallback;
+class FMRadioInterruptcallback;
+
+typedef std::shared_ptr<MultiCallbackUserData> FMRadiocallbackPtr;
+typedef std::shared_ptr<FMRadioScanCallback> FMRadioScanCallbackPtr;
+typedef std::shared_ptr<FMRadioInterruptcallback> FMRadioInterruptcallbackPtr;
+
+struct FMRadiocallbackHolder {
+    FMRadiocallbackPtr ptr;
+};
+
+struct FMRadioScanCallbackHolder {
+    FMRadioScanCallbackPtr ptr;
+};
+
+struct FMRadioInterruptcallbackHolder {
+    FMRadioInterruptcallbackPtr ptr;
+};
+
+class FMRadioScanCallback {
+public:
+    FMRadioScanCallback(JSContextRef context, JSObjectRef eventCbObj, JSObjectRef errorCbObj);
+    ~FMRadioScanCallback();
+
+    void onfrequencyfound();
+    void onfinished();
+    void onerror(JSValueRef errorObj);
+    JSContextRef getContext();
+
+    void setFreqeuncy(int frequency);
+    int getFrequency();
+
+private:
+    JSContextRef mContext;
+    std::vector<double> mFrequencies;
+    int mFrequency;
+    MultiCallbackUserData *mCallbackUserData;
+};
+
+class FMRadioInterruptcallback {
+public:
+    FMRadioInterruptcallback(JSContextRef context, JSObjectRef eventCbObj);
+    ~FMRadioInterruptcallback();
+
+    void oninterrupted(std::string message);
+    void oninterruptfinished();
+    JSContextRef getContext();
+
+    void setCode(radio_interrupted_code_e code);
+    radio_interrupted_code_e getCode();
+
+private:
+    JSContextRef mContext;
+    radio_interrupted_code_e mCode;
+    MultiCallbackUserData *mCallbackUserData;
+};
+
+}
+}
+#endif /* __TIZEN_FMRADIO_CALLBACK_H_ */
diff --git a/src/FMRadio/FMRadioManager.cpp b/src/FMRadio/FMRadioManager.cpp
new file mode 100755 (executable)
index 0000000..87a8a67
--- /dev/null
@@ -0,0 +1,808 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <string>
+
+#include "FMRadioManager.h"
+#include "FMRadioUtil.h"
+
+#define FREQUENCY_LOWER_BOUND 87.5
+#define FREQUENCY_UPPER_BOUND 108
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+using namespace DeviceAPI::Common;
+
+FMRadioManager::FMRadioManager() :
+                m_frequency(0.0),
+                m_frequencyUpperBound(FREQUENCY_UPPER_BOUND),
+                m_frequencyLowerBound(FREQUENCY_LOWER_BOUND),
+                m_signalStrength(0),
+                m_mute(false),
+                m_isAntennaConnected(false)
+{
+    LOGD("Enter");
+    m_radio = NULL;
+    radio_h radio_handle;
+
+    int ret = radio_create(&radio_handle);
+    if (ret == RADIO_ERROR_NONE) {
+        m_radio = radio_handle;
+    } else {
+        LOGE("It's failed to create radio handle, %d, %s", ret,
+                FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+    }
+}
+
+FMRadioManager::~FMRadioManager()
+{
+    if (m_radio != NULL) {
+        radio_destroy(m_radio);
+    }
+}
+
+FMRadioManager* FMRadioManager::getInstance()
+{
+    static FMRadioManager instance;
+    return &instance;
+}
+
+double FMRadioManager::getFrequency()
+{
+    LOGD("Enter");
+    int ret = 0;
+    int freq;
+
+    if (m_radio != NULL) {
+        ret = radio_get_frequency(m_radio, &freq);
+        if (ret == RADIO_ERROR_NONE) {
+            m_frequency = (double) freq / 1000;
+        } else {
+            //It does not throw exception
+            LOGE("It's failed to get frequency, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+        }
+    } else {
+        //It does not throw exception
+        LOGE("radio handle is not initialized");
+    }
+
+    return m_frequency;
+}
+
+void FMRadioManager::setFrequency(double frequency)
+{
+    m_frequency = frequency;
+}
+
+double FMRadioManager::getFrequencyUpperBound() const
+{
+    return m_frequencyUpperBound;
+}
+
+void FMRadioManager::setFrequencyUpperBound(double frequencyUpperBound)
+{
+    m_frequencyUpperBound = frequencyUpperBound;
+}
+
+double FMRadioManager::getFrequencyLowerBound() const
+{
+    return m_frequencyLowerBound;
+}
+
+void FMRadioManager::setFrequencyLowerBound(double frequencyLowerBound)
+{
+    m_frequencyLowerBound = frequencyLowerBound;
+}
+
+long FMRadioManager::getSignalStrength()
+{
+    LOGD("Enter");
+    int ret = 0;
+    int signalStrength;
+
+    if (m_radio != NULL) {
+        ret = radio_get_signal_strength(m_radio, &signalStrength);
+        if (ret == RADIO_ERROR_NONE) {
+            m_signalStrength = static_cast<long>(signalStrength);
+        } else {
+            //It does not throw exception
+            LOGE("It's failed to get signal strength, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+        }
+    } else {
+        //It does not throw exception
+        LOGE("radio handle is not initialized");
+    }
+
+    return m_signalStrength;
+}
+
+void FMRadioManager::setSignalStrength(long signalStrength)
+{
+    m_signalStrength = signalStrength;
+}
+
+std::string FMRadioManager::getState()
+{
+    LOGD("Enter");
+    int ret = 0;
+    radio_state_e state;
+
+    if (m_radio != NULL) {
+        ret = radio_get_state(m_radio, &state);
+        if (ret == RADIO_ERROR_NONE) {
+            if (state == RADIO_STATE_READY) {
+                m_state = "READY";
+            } else if (state == RADIO_STATE_PLAYING) {
+                m_state = "PLAYING";
+            } else if (state == RADIO_STATE_SCANNING) {
+                m_state = "SCANNING";
+            } else {
+                LOGE("It's failed to get state");
+                m_state = "";
+            }
+        } else {
+            //It does not throw exception
+            LOGE("It's failed to get state, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+        }
+    } else {
+        //It does not throw exception
+        LOGE("radio handle is not initialized");
+    }
+
+    return m_state;
+}
+
+void FMRadioManager::setState(std::string state)
+{
+    m_state = state;
+}
+
+bool FMRadioManager::getMute()
+{
+    LOGD("Enter");
+    int ret = 0;
+    bool muted;
+
+    if (m_radio != NULL) {
+        ret = radio_is_muted(m_radio, &muted);
+        if (ret == RADIO_ERROR_NONE) {
+            m_mute = muted;
+        } else {
+            //It does not throw exception
+            LOGE("It's failed to get mute status, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+        }
+    } else {
+        //It does not throw exception
+        LOGE("radio handle is not initialized");
+    }
+
+    return m_mute;
+}
+
+void FMRadioManager::setMute(bool mute)
+{
+    LOGD("Enter");
+    int ret = 0;
+
+    if (m_radio != NULL) {
+        ret = radio_set_mute(m_radio, mute);
+        if (ret == RADIO_ERROR_NONE) {
+            m_mute = mute;
+        } else {
+            //It does not throw exception
+            LOGE("It's failed to set mute status, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+        }
+    } else {
+        //It does not throw exception
+        LOGE("radio handle is not initialized");
+    }
+}
+
+bool FMRadioManager::getAntennaConnected()
+{
+    LOGD("Enter");
+    bool isAntennaConnected = false;
+
+    int ret = runtime_info_get_value_bool(RUNTIME_INFO_KEY_AUDIO_JACK_CONNECTED,
+            &isAntennaConnected);
+    if (ret == RUNTIME_INFO_ERROR_NONE) {
+        m_isAntennaConnected = isAntennaConnected;
+    } else {
+        //It does not throw exception
+        LOGE("It is failed to get runtime antenna info, %d, %s", ret,
+                FMRadioUtil::getRuntimeErrorMessage(ret).c_str());
+    }
+
+    return m_isAntennaConnected;
+}
+
+void FMRadioManager::setAntennaConnected(bool isAntennaConnected)
+{
+    m_isAntennaConnected = isAntennaConnected;
+}
+
+void FMRadioManager::scanUpdatedCallback(int frequency, void *data)
+{
+    LOGD("Enter");
+
+    FMRadioScanCallbackHolder *holder = static_cast<FMRadioScanCallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return;
+    }
+    FMRadioScanCallbackPtr callback = holder->ptr;
+
+    callback->setFreqeuncy(frequency);
+
+    if (!g_idle_add(invokeScanUpdateCB, holder)) {
+        delete holder;
+        holder = NULL;
+        LOGE("g_idle addition failed");
+    }
+}
+
+void FMRadioManager::scanStoppedCallback(void *data)
+{
+    LOGD("Enter");
+
+    FMRadiocallbackHolder *holder = static_cast<FMRadiocallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return;
+    }
+
+    if (!g_idle_add(invokeSuccessCB, holder)) {
+        delete holder;
+        holder = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+}
+
+void FMRadioManager::scanCompletedCallback(void *data)
+{
+    LOGD("Enter");
+
+    FMRadioScanCallbackHolder *holder = static_cast<FMRadioScanCallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return;
+    }
+
+    if (!g_idle_add(invokeScanCompleteCB, holder)) {
+        delete holder;
+        holder = NULL;
+        LOGE("g_idle addition failed");
+    }
+}
+
+void FMRadioManager::seekCompletedCallback(int frequency, void *data)
+{
+    LOGD("Enter");
+
+    FMRadiocallbackHolder *holder = static_cast<FMRadiocallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return;
+    }
+
+    if (!g_idle_add(invokeSuccessCB, holder)) {
+        delete holder;
+        holder = NULL;
+        LOGE("g_idle addition failed");
+    }
+}
+
+void FMRadioManager::interruptedCallback(radio_interrupted_code_e code, void *data)
+{
+    LOGD("Enter");
+
+    FMRadioInterruptcallbackHolder *holder = static_cast<FMRadioInterruptcallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return;
+    }
+
+    FMRadioInterruptcallbackPtr callback = holder->ptr;
+    callback->setCode(code);
+
+    if (!g_idle_add(invokeInterruptCB, holder)) {
+        delete holder;
+        holder = NULL;
+        LOGE("g_idle addition failed");
+    }
+
+}
+
+void FMRadioManager::start(double frequency)
+{
+    LOGD("Enter");
+    int ret = 0;
+    int freq = 0;
+    radio_state_e state;
+
+    LOGD("frequency: %.2lf", frequency);
+    if ((frequency > FREQUENCY_UPPER_BOUND) || (frequency < FREQUENCY_LOWER_BOUND)) {
+        LOGE("The frequency value is out of range");
+        FMRadioUtil::throwFMRadioException<InvalidValuesException>(ret,
+                "The value is out of range");
+    }
+
+    if (m_radio == NULL) {
+        ret = radio_create(&m_radio);
+        if (ret != RADIO_ERROR_NONE) {
+            LOGE("It is failed to create radio handle, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to create radio handle.");
+        }
+    }
+
+    if (m_radio != NULL) {
+        freq = frequency * 1000;
+        LOGD("frequency(int): %d", freq);
+
+        ret = radio_set_frequency(m_radio, freq);
+        if (ret != RADIO_ERROR_NONE) {
+            LOGE("It is failed to change frequency, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to change frequency.");
+        }
+
+        ret = radio_get_state(m_radio, &state);
+        if (ret != RADIO_ERROR_NONE) {
+            LOGE("It is failed to get state, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to get state");
+        }
+
+        if (state == RADIO_STATE_PLAYING) {
+            LOGE("The radio is already running.");
+        } else {
+            ret = radio_start(m_radio);
+            LOGE("start : %d", ret);
+            if (ret != RADIO_ERROR_NONE) {
+                if (ret == RADIO_ERROR_INVALID_STATE) {
+                    LOGE("invalid state");
+                    FMRadioUtil::throwFMRadioException<InvalidStateException>(ret,
+                            "InvalidStateError");
+                }
+                if (ret == RADIO_ERROR_INVALID_OPERATION) {
+                    LOGE("The radio already used by other application");
+                    FMRadioUtil::throwFMRadioException<ServiceNotAvailableException>(ret,
+                            "The radio is not available.");
+                } else {
+                    LOGE("It is failed to start radio, %d, %s", ret,
+                            FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+                    FMRadioUtil::throwFMRadioException(ret, "It is failed to start radio.");
+                }
+            }
+        }
+    } else {
+        FMRadioUtil::throwFMRadioException(ret, "radio handle is not initialized");
+    }
+}
+void FMRadioManager::stop()
+{
+    LOGD("Enter");
+    int ret = 0;
+
+    if (m_radio != NULL) {
+        ret = radio_stop(m_radio);
+        if (ret != RADIO_ERROR_NONE) {
+            if (ret == RADIO_ERROR_INVALID_STATE) {
+                LOGE("invalid state");
+                FMRadioUtil::throwFMRadioException<InvalidStateException>(ret, "InvalidStateError");
+            } else {
+                LOGE("It is failed to stop radio, %d, %s", ret,
+                        FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+                FMRadioUtil::throwFMRadioException(ret, "It is failed to stop radio.");
+            }
+        }
+    } else {
+        FMRadioUtil::throwFMRadioException(ret, "radio handle is not initialized");
+    }
+}
+void FMRadioManager::seekUp(FMRadiocallbackPtr callback)
+{
+    LOGD("Enter");
+    int ret = 0;
+    JSValueRef jsError = NULL;
+
+    if (m_radio != NULL) {
+
+        FMRadiocallbackHolder* holder = new FMRadiocallbackHolder();
+        if (!holder) {
+            LOGE("It is failed to allocate memory");
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to allocate memory");
+        }
+        holder->ptr = callback;
+
+        ret = radio_seek_up(m_radio, FMRadioManager::seekCompletedCallback, holder);
+        if (ret != RADIO_ERROR_NONE) {
+            if (ret == RADIO_ERROR_INVALID_STATE) {
+                LOGE("invalid state");
+                jsError = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                        JSWebAPIErrorFactory::INVALID_STATE_ERROR, "invalid state");
+                callback->invokeCallback("onerror", jsError);
+            } else {
+                LOGE("It is failed to seek, %d, %s", ret,
+                        FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+                jsError = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+                callback->invokeCallback("onerror", jsError);
+            }
+        }
+    } else {
+        LOGE("radio handle is not initialized");
+        jsError = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+        callback->invokeCallback("onerror", jsError);
+    }
+}
+void FMRadioManager::seekDown(FMRadiocallbackPtr callback) //async
+{
+    LOGD("Enter");
+    int ret = 0;
+    JSValueRef jsError = NULL;
+
+    if (m_radio != NULL) {
+
+        FMRadiocallbackHolder* holder = new FMRadiocallbackHolder();
+        if (!holder) {
+            LOGE("It is failed to allocate memory");
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to allocate memory");
+        }
+        holder->ptr = callback;
+
+        ret = radio_seek_down(m_radio, FMRadioManager::seekCompletedCallback, holder);
+        if (ret != RADIO_ERROR_NONE) {
+            if (ret == RADIO_ERROR_INVALID_STATE) {
+                LOGE("invalid state");
+                jsError = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                        JSWebAPIErrorFactory::INVALID_STATE_ERROR, "invalid state");
+                callback->invokeCallback("onerror", jsError);
+            } else {
+                LOGE("It is failed to seek, %d, %s", ret,
+                        FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+                jsError = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+                callback->invokeCallback("onerror", jsError);
+            }
+        }
+    } else {
+        LOGE("radio handle is not initialized");
+        jsError = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+        callback->invokeCallback("onerror", jsError);
+    }
+}
+void FMRadioManager::scanStart(FMRadioScanCallbackPtr radioScanCallback)
+{
+    LOGD("Enter");
+    int ret = 0;
+    JSValueRef jsError = NULL;
+
+    if (m_radio != NULL) {
+
+        FMRadioScanCallbackHolder* holder = new FMRadioScanCallbackHolder();
+        if (!holder) {
+            LOGE("It is failed to allocate memory");
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to allocate memory");
+        }
+        holder->ptr = radioScanCallback;
+
+        ret = radio_set_scan_completed_cb(m_radio, FMRadioManager::scanCompletedCallback, holder);
+        if (ret != RADIO_ERROR_NONE) {
+            LOGE("It is failed to set complete callback for scanning, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+            jsError = JSWebAPIErrorFactory::makeErrorObject(radioScanCallback->getContext(),
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+            radioScanCallback->onerror(jsError);
+        }
+
+        ret = radio_scan_start(m_radio, FMRadioManager::scanUpdatedCallback, holder);
+        if (ret != RADIO_ERROR_NONE) {
+            LOGE("It is failed to start scanning");
+            radio_unset_scan_completed_cb(m_radio);
+            if (ret == RADIO_ERROR_INVALID_STATE) {
+                LOGE("invalid state");
+                jsError = JSWebAPIErrorFactory::makeErrorObject(radioScanCallback->getContext(),
+                        JSWebAPIErrorFactory::INVALID_STATE_ERROR, "invalid state");
+                radioScanCallback->onerror(jsError);
+            } else {
+                LOGE("It is failed to start scanning, %d, %s", ret,
+                        FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+                jsError = JSWebAPIErrorFactory::makeErrorObject(radioScanCallback->getContext(),
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+                radioScanCallback->onerror(jsError);
+            }
+        }
+    } else {
+        LOGE("radio handle is not initialized");
+        jsError = JSWebAPIErrorFactory::makeErrorObject(radioScanCallback->getContext(),
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+        radioScanCallback->onerror(jsError);
+    }
+}
+
+void FMRadioManager::scanStop(FMRadiocallbackPtr callback)
+{
+    LOGD("Enter");
+    int ret = 0;
+    JSValueRef jsError = NULL;
+
+    if (m_radio != NULL) {
+
+        FMRadiocallbackHolder* holder = new FMRadiocallbackHolder();
+        if (!holder) {
+            LOGE("It is failed to allocate memory");
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to allocate memory");
+        }
+        holder->ptr = callback;
+
+        ret = radio_scan_stop(m_radio, FMRadioManager::scanStoppedCallback, holder);
+        if (ret != RADIO_ERROR_NONE) {
+            LOGE("It is failed to stop scanning");
+            if (ret == RADIO_ERROR_INVALID_STATE) {
+                LOGE("invalid state");
+                jsError = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                        JSWebAPIErrorFactory::INVALID_STATE_ERROR, "invalid state");
+                callback->invokeCallback("onerror", jsError);
+            } else {
+                LOGE("It is failed to stop scanning, %d, %s", ret,
+                        FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+                jsError = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+                callback->invokeCallback("onerror", jsError);
+            }
+        }
+    } else {
+        LOGE("radio handle is not initialized");
+        jsError = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+        callback->invokeCallback("onerror", jsError);
+    }
+}
+
+void FMRadioManager::setFMRadioInterruptedListener(FMRadioInterruptcallbackPtr interruptCallback)
+{
+    LOGD("Enter");
+    int ret = 0;
+
+    if (m_radio != NULL) {
+
+        FMRadioInterruptcallbackHolder* holder = new FMRadioInterruptcallbackHolder();
+        if (!holder) {
+            LOGE("It is failed to allocate memory");
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to allocate memory");
+        }
+        holder->ptr = interruptCallback;
+
+        ret = radio_set_interrupted_cb(m_radio, FMRadioManager::interruptedCallback, holder);
+        if (ret != RADIO_ERROR_NONE) {
+            LOGE("It is failed to set interrupt listener, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to set interrupt listener.");
+        }
+    } else {
+        FMRadioUtil::throwFMRadioException(ret, "radio handle is not initialized");
+    }
+}
+
+void FMRadioManager::unsetFMRadioInterruptedListener()
+{
+    LOGD("Enter");
+    int ret = 0;
+
+    if (m_radio != NULL) {
+        ret = radio_unset_interrupted_cb(m_radio);
+        if (ret != RADIO_ERROR_NONE) {
+            LOGE("It is failed to unset interrupt listener, %d, %s", ret,
+                    FMRadioUtil::getFMRadioErrorMessage(ret).c_str());
+            FMRadioUtil::throwFMRadioException(ret, "It is failed to unset interrupt listener.");
+        }
+    } else {
+        FMRadioUtil::throwFMRadioException(ret, "radio handle is not initialized");
+    }
+}
+
+void FMRadioManager::setAntennaChangeListener(FMRadiocallbackPtr callback)
+{
+    LOGD("Enter");
+    int ret = 0;
+
+    FMRadiocallbackHolder* holder = new FMRadiocallbackHolder();
+    if (!holder) {
+        LOGE("It is failed to allocate memory");
+        FMRadioUtil::throwFMRadioException(ret, "It is failed to allocate memory");
+    }
+    holder->ptr = callback;
+
+    ret = runtime_info_set_changed_cb(RUNTIME_INFO_KEY_AUDIO_JACK_CONNECTED,
+            FMRadioManager::antennaChangeCallback, holder);
+    if (ret != RUNTIME_INFO_ERROR_NONE) {
+        LOGE("It is failed to set antenna change listener, %d, %s", ret,
+                FMRadioUtil::getRuntimeErrorMessage(ret).c_str());
+        FMRadioUtil::throwRuntimeException(ret, "It is failed to set antenna change listener.");
+    }
+}
+void FMRadioManager::antennaChangeCallback(runtime_info_key_e key, void *data)
+{
+    LOGD("Enter");
+
+    FMRadiocallbackHolder *holder = static_cast<FMRadiocallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return;
+    }
+    FMRadiocallbackPtr callback = holder->ptr;
+
+    bool isAntennaConnected = FMRadioManager::getInstance()->getAntennaConnected();
+
+    JSValueRef frequencyObj = JSUtil::toJSValueRef(callback->getContext(), isAntennaConnected);
+    callback->invokeCallback("onchange", frequencyObj);
+}
+
+void FMRadioManager::unsetAntennaChangeListener()
+{
+    LOGD("Enter");
+
+    int ret = runtime_info_unset_changed_cb(RUNTIME_INFO_KEY_AUDIO_JACK_CONNECTED);
+    if (ret != RUNTIME_INFO_ERROR_NONE) {
+        LOGE("It is failed to set antenna change listener, %d, %s", ret,
+                FMRadioUtil::getRuntimeErrorMessage(ret).c_str());
+        FMRadioUtil::throwRuntimeException(ret, "It is failed to unset antenna change listener.");
+    }
+}
+
+gboolean FMRadioManager::invokeSuccessCB(void* data)
+{
+    LOGD("Enter");
+
+    FMRadiocallbackHolder *holder = static_cast<FMRadiocallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return false;
+    }
+    FMRadiocallbackPtr callback = holder->ptr;
+
+    callback->invokeCallback("onsuccess");
+
+    return false;
+}
+
+gboolean FMRadioManager::invokeInterruptCB(void* data)
+{
+    LOGD("Enter");
+
+    FMRadioInterruptcallbackHolder *holder = static_cast<FMRadioInterruptcallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return false;
+    }
+    FMRadioInterruptcallbackPtr callback = holder->ptr;
+    radio_interrupted_code_e code = callback->getCode();
+
+    std::string message = "";
+
+    switch (code) {
+        case RADIO_INTERRUPTED_COMPLETED: {
+            message = "The radio interruption completes";
+            LOGD("%s", message.c_str());
+            callback->oninterruptfinished();
+            break;
+        }
+        case RADIO_INTERRUPTED_BY_MEDIA: {
+            message = "The radio is interrupted by media";
+            LOGD("%s", message.c_str());
+            callback->oninterrupted(message);
+            break;
+        }
+        case RADIO_INTERRUPTED_BY_CALL: {
+            message = "The radio is interrupted by call";
+            LOGD("%s", message.c_str());
+            callback->oninterrupted(message);
+            break;
+        }
+        case RADIO_INTERRUPTED_BY_EARJACK_UNPLUG: {
+            message = "The radio is interrupted by earjack unplugging";
+            LOGD("%s", message.c_str());
+            callback->oninterrupted(message);
+            break;
+        }
+        case RADIO_INTERRUPTED_BY_RESOURCE_CONFLICT: {
+            message = "The radio is interrupted by resource conflict";
+            LOGD("%s", message.c_str());
+            callback->oninterrupted(message);
+            break;
+        }
+        case RADIO_INTERRUPTED_BY_ALARM: {
+            message = "The radio is interrupted by alarm";
+            LOGD("%s", message.c_str());
+            callback->oninterrupted(message);
+            break;
+        }
+        case RADIO_INTERRUPTED_BY_EMERGENCY: {
+            message = "The radio is interrupted by emergency";
+            LOGD("%s", message.c_str());
+            callback->oninterrupted(message);
+            break;
+        }
+        case RADIO_INTERRUPTED_BY_RESUMABLE_MEDIA: {
+            message = "The radio is interrupted by resumable media";
+            LOGD("%s", message.c_str());
+            callback->oninterrupted(message);
+            break;
+        }
+        case RADIO_INTERRUPTED_BY_NOTIFICATION: {
+            message = "The radio is interrupted by notification";
+            LOGD("%s", message.c_str());
+            callback->oninterrupted(message);
+            break;
+        }
+        default:
+            message = "The radio is interrupted by unknow error";
+            LOGD("%s", message.c_str());
+            callback->oninterrupted(message);
+    }
+    return false;
+}
+
+gboolean FMRadioManager::invokeScanUpdateCB(void* data)
+{
+    LOGD("Enter");
+
+    FMRadioScanCallbackHolder *holder = static_cast<FMRadioScanCallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return false;
+    }
+    FMRadioScanCallbackPtr callback = holder->ptr;
+
+    callback->onfrequencyfound();
+
+    return false;
+}
+
+gboolean FMRadioManager::invokeScanCompleteCB(void* data)
+{
+    LOGD("Enter");
+
+    FMRadioScanCallbackHolder *holder = static_cast<FMRadioScanCallbackHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return false;
+    }
+    FMRadioScanCallbackPtr callback = holder->ptr;
+
+    callback->onfinished();
+
+    return false;
+}
+
+} // FMRadio
+} // DeviceAPI
diff --git a/src/FMRadio/FMRadioManager.h b/src/FMRadio/FMRadioManager.h
new file mode 100755 (executable)
index 0000000..1e25db4
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_FMRADIO_MANAGER_H__
+#define __TIZEN_FMRADIO_MANAGER_H__
+
+#include <radio.h>
+#include <string.h>
+#include <runtime_info.h>
+#include <glib.h>
+
+#include "FMRadioCallback.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+class FMRadioManager {
+public:
+    FMRadioManager();
+    virtual ~FMRadioManager();
+    static FMRadioManager* getInstance();
+
+    double getFrequency();
+    void setFrequency(double frequency);
+
+    double getFrequencyUpperBound() const;
+    void setFrequencyUpperBound(double frequencyUpperBound);
+
+    double getFrequencyLowerBound() const;
+    void setFrequencyLowerBound(double frequencyLowerBound);
+
+    long getSignalStrength();
+    void setSignalStrength(long signalStrength);
+
+    std::string getState();
+    void setState(std::string signalStrength);
+
+    bool getMute();
+    void setMute(bool mute);
+
+    bool getAntennaConnected();
+    void setAntennaConnected(bool isAntennaConnected);
+
+    void start(double frequency);
+    void stop();
+
+    void seekUp(FMRadiocallbackPtr callback);
+    void seekDown(FMRadiocallbackPtr callback);
+
+    void scanStart(FMRadioScanCallbackPtr radioScanCallback);
+    void scanStop(FMRadiocallbackPtr callback);
+
+    void setFMRadioInterruptedListener(FMRadioInterruptcallbackPtr interruptCallback);
+    void unsetFMRadioInterruptedListener();
+
+    void setAntennaChangeListener(FMRadiocallbackPtr callback);
+    void unsetAntennaChangeListener();
+
+    static void seekCompletedCallback(int frequency, void *data);
+
+    static void scanCompletedCallback(void *data);
+    static void scanStoppedCallback(void *data);
+    static void scanUpdatedCallback(int frequency, void *data);
+
+    static void interruptedCallback(radio_interrupted_code_e code, void *data);
+
+    static void antennaChangeCallback(runtime_info_key_e key, void *data);
+
+    static gboolean invokeSuccessCB(void* data);
+    static gboolean invokeScanUpdateCB(void* data);
+    static gboolean invokeScanCompleteCB(void* data);
+    static gboolean invokeInterruptCB(void* data);
+
+private:
+    radio_h m_radio;
+    std::string m_state;
+    double m_frequency;
+    double m_frequencyUpperBound;
+    double m_frequencyLowerBound;
+    long m_signalStrength;
+    bool m_mute;
+    bool m_isAntennaConnected;
+};
+
+} // FMRadio
+} // DeviceAPI
+
+#endif // __TIZEN_FMRADIO_MANAGER_H__
diff --git a/src/FMRadio/FMRadioUtil.cpp b/src/FMRadio/FMRadioUtil.cpp
new file mode 100755 (executable)
index 0000000..d132786
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <radio.h>
+#include <runtime_info.h>
+#include <Logger.h>
+
+#include "FMRadioUtil.h"
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+using namespace DeviceAPI::Common;
+
+std::string FMRadioUtil::getFMRadioErrorMessage(const int errorCode)
+{
+    switch (errorCode) {
+        case RADIO_ERROR_NONE:
+            return "";
+        case RADIO_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case RADIO_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case RADIO_ERROR_INVALID_OPERATION:
+            return "Invalid Operation";
+        case RADIO_ERROR_INVALID_STATE:
+            return "Invalid state";
+        case RADIO_ERROR_SOUND_POLICY:
+            return "Sound policy";
+        case RADIO_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case RADIO_ERROR_NOT_SUPPORTED:
+            return "Not supported";
+        default:
+            return "Unknown error";
+    }
+}
+
+std::string FMRadioUtil::getRuntimeErrorMessage(const int errorCode)
+{
+    switch (errorCode) {
+        case RUNTIME_INFO_ERROR_NONE:
+            return "";
+        case RUNTIME_INFO_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case RUNTIME_INFO_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case RUNTIME_INFO_ERROR_IO_ERROR:
+            return "IO error";
+        case RUNTIME_INFO_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        default:
+            return "Unknown error";
+    }
+
+}
+
+} //FMRadio
+} //DeviceAPI
diff --git a/src/FMRadio/FMRadioUtil.h b/src/FMRadio/FMRadioUtil.h
new file mode 100755 (executable)
index 0000000..1333cc2
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_FMRADIO_UTIL_H__
+#define __TIZEN_FMRADIO_UTIL_H__
+
+#include <string>
+#include <sstream>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+class FMRadioUtil {
+public:
+
+    static std::string getFMRadioErrorMessage(const int errorCode);
+    static std::string getRuntimeErrorMessage(const int errorCode);
+
+    template<class T = DeviceAPI::Common::UnknownException>
+    static void throwFMRadioException(const int errorCode, const std::string &hint)
+    {
+        std::stringstream ss;
+        ss << hint << " : " << getFMRadioErrorMessage(errorCode);
+        LOGE("%s", ss.str().c_str());
+
+        throw T(ss.str().c_str());
+    }
+
+    template<class T = DeviceAPI::Common::UnknownException>
+    static void throwRuntimeException(const int errorCode, const std::string &hint)
+    {
+        std::stringstream ss;
+        ss << hint << " : " << getRuntimeErrorMessage(errorCode);
+        LOGE("%s", ss.str().c_str());
+
+        throw T(ss.str().c_str());
+    }
+};
+
+} //FMRadio
+} //DeviceAPI
+
+#endif // __TIZEN_FMRADIO_UTIL_H__
diff --git a/src/FMRadio/JSFMRadioManager.cpp b/src/FMRadio/JSFMRadioManager.cpp
new file mode 100755 (executable)
index 0000000..66b0815
--- /dev/null
@@ -0,0 +1,550 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+
+#include "JSFMRadioManager.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+JSClassDefinition JSFMRadioManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "FMRadioManager",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSFMRadioManager::m_property[] = {
+        { FMRADIO_MANAGER_STATE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { FMRADIO_MANAGER_FREQUENCY, getProperty, setProperty, kJSPropertyAttributeNone },
+        { FMRADIO_MANAGER_FREQUENCY_UPPER_BOUND, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { FMRADIO_MANAGER_FREQUENCY_LOWER_BOUND, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { FMRADIO_MANAGER_SIGNAL_STRENGTH, getProperty, NULL, kJSPropertyAttributeReadOnly },
+        { FMRADIO_MANAGER_MUTE, getProperty, setProperty, kJSPropertyAttributeNone },
+        { FMRADIO_MANAGER_IS_ANTENNA_CONNECTED, getProperty, NULL, kJSPropertyAttributeNone },
+        { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSFMRadioManager::m_function[] = {
+    { FMRADIO_MANAGER_API_START, start, kJSPropertyAttributeNone },
+    { FMRADIO_MANAGER_API_STOP, stop, kJSPropertyAttributeNone },
+    { FMRADIO_MANAGER_API_SEEK_UP, seekUp, kJSPropertyAttributeNone },
+    { FMRADIO_MANAGER_API_SEEK_DOWN, seekDown, kJSPropertyAttributeNone },
+    { FMRADIO_MANAGER_API_SCAN_START, scanStart, kJSPropertyAttributeNone },
+    { FMRADIO_MANAGER_API_SCAN_STOP, scanStop, kJSPropertyAttributeNone },
+    { FMRADIO_MANAGER_API_SET_FMRADIO_INTERRUPTED_LISTENER, setFMRadioInterruptedListener, kJSPropertyAttributeNone },
+    { FMRADIO_MANAGER_API_UNSET_FMRADIO_INTERRUPTED_LISTENER, unsetFMRadioInterruptedListener, kJSPropertyAttributeNone },
+    { FMRADIO_MANAGER_API_SET_ANTENNA_CHANGE_LISTENER, setAntennaChangeListener, kJSPropertyAttributeNone },
+    { FMRADIO_MANAGER_API_UNSET_ANTENNA_CHANGE_LISTENER, unsetAntennaChangeListener, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSFMRadioManager::m_jsClassRef = NULL;
+
+const JSClassRef JSFMRadioManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSFMRadioManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSFMRadioManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        FMRadioManager *priv = FMRadioManager::getInstance();
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    }
+}
+
+void JSFMRadioManager::finalize(JSObjectRef object)
+{
+    FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSFMRadioManager::start(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // frequency
+        double frequency = validator.toDouble(0, true, 87.5); //TODO
+
+        // perform
+        priv->start(frequency);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.start().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::stop(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        // perform
+        priv->stop();
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.stop().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::seekUp(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        FMRadiocallbackPtr callback(new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(0, true);
+        if (successCallbackObj) {
+            callback->setCallback("onsuccess", successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(1, true);
+        if (errorCallbackObj) {
+            callback->setCallback("onerror", errorCallbackObj);
+        }
+
+        // perform
+        priv->seekUp(callback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.seekUp().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::seekDown(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        FMRadiocallbackPtr callback(new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(0, true);
+        if (successCallbackObj) {
+            callback->setCallback("onsuccess", successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(1, true);
+        if (errorCallbackObj) {
+            callback->setCallback("onerror", errorCallbackObj);
+        }
+        // perform
+        priv->seekDown(callback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.seekDown().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::scanStart(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef eventCBObj = validator.toCallbackObject(0, false, "onfrequencyfound", "onfinished", NULL);
+        JSObjectRef errorCBObj = validator.toFunction(1, true);
+
+        FMRadioScanCallbackPtr radioScanCallback(new FMRadioScanCallback(GlobalContextManager::getInstance()->getGlobalContext(context), eventCBObj, errorCBObj));
+
+        // perform
+        priv->scanStart(radioScanCallback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.scanStart().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::scanStop(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        FMRadiocallbackPtr callback(new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(0, true);
+        if (successCallbackObj) {
+            callback->setCallback("onsuccess", successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(1, true);
+        if (errorCallbackObj) {
+            callback->setCallback("onerror", errorCallbackObj);
+        }
+
+        // perform
+        priv->scanStop(callback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.scanStop().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::setFMRadioInterruptedListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef eventCBObj = validator.toCallbackObject(0, false, "oninterrupted", "oninterruptfinished", NULL);
+        FMRadioInterruptcallbackPtr radioInterruptCallback(new FMRadioInterruptcallback(GlobalContextManager::getInstance()->getGlobalContext(context), eventCBObj));
+
+        // perform
+        priv->setFMRadioInterruptedListener(radioInterruptCallback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.setFMRadioInterruptedListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::unsetFMRadioInterruptedListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        // perform
+        priv->unsetFMRadioInterruptedListener();
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.unsetFMRadioInterruptedListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::setAntennaChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        FMRadiocallbackPtr callback(new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context)));
+
+        JSObjectRef changeCallbackObj = validator.toFunction(0, false);
+        if (changeCallbackObj) {
+            callback->setCallback("onchange", changeCallbackObj);
+        }
+
+        priv->setAntennaChangeListener(callback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.setFMRadioInterruptedListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::unsetAntennaChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        priv->unsetAntennaChangeListener();
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.unsetFMRadioInterruptedListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFMRadioManager::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(object));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        // perform
+        if (JSStringIsEqualToUTF8CString(propertyName, FMRADIO_MANAGER_FREQUENCY)) {
+            double freq = priv->getFrequency();
+            return JSUtil::toJSValueRef(context, freq);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, FMRADIO_MANAGER_FREQUENCY_UPPER_BOUND)) {
+            double freqUpperBound = priv->getFrequencyUpperBound();
+            return JSUtil::toJSValueRef(context, freqUpperBound);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, FMRADIO_MANAGER_FREQUENCY_LOWER_BOUND)) {
+            double freqLowerBound = priv->getFrequencyLowerBound();
+            return JSUtil::toJSValueRef(context, freqLowerBound);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, FMRADIO_MANAGER_SIGNAL_STRENGTH)) {
+            long signalStrength = priv->getSignalStrength();
+            return JSUtil::toJSValueRef(context, signalStrength);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, FMRADIO_MANAGER_MUTE)) {
+            bool muted = priv->getMute();
+            return JSUtil::toJSValueRef(context, muted);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, FMRADIO_MANAGER_STATE)) {
+            std::string state = priv->getState();
+            return JSUtil::toJSValueRef(context, state);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, FMRADIO_MANAGER_IS_ANTENNA_CONNECTED)) {
+            bool isAntennaConnected = priv->getAntennaConnected();
+            return JSUtil::toJSValueRef(context, isAntennaConnected);
+        } else {
+            LOGD("no matched key exist");
+        }
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.getProperty().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+bool JSFMRadioManager::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        FMRadioManager *priv = static_cast<FMRadioManager*>(JSObjectGetPrivate(object));
+
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        // perform
+        if (JSStringIsEqualToUTF8CString(propertyName, FMRADIO_MANAGER_FREQUENCY)) {
+            priv->setFrequency(JSUtil::JSValueToNumber(context, value));
+            return true;
+        } else if (JSStringIsEqualToUTF8CString(propertyName, FMRADIO_MANAGER_MUTE)) {
+            priv->setMute(JSUtil::JSValueToBoolean(context, value));
+        } else {
+            LOGD("no matched key exist");
+        }
+        return false;
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in FMRadioManager.setProperty().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+} // FMRadio
+} // DeviceAPI
diff --git a/src/FMRadio/JSFMRadioManager.h b/src/FMRadio/JSFMRadioManager.h
new file mode 100755 (executable)
index 0000000..372bd52
--- /dev/null
@@ -0,0 +1,153 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_FMRADIO_MANAGER_H__
+#define __TIZEN_JS_FMRADIO_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "FMRadioManager.h"
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+class JSFMRadioManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef start(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef stop(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef seekUp(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef seekDown(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef scanStart(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef scanStop(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setFMRadioInterruptedListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetFMRadioInterruptedListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setAntennaChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetAntennaChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // FMRadio
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/FMRadio/config.xml b/src/FMRadio/config.xml
new file mode 100755 (executable)
index 0000000..4e21d3a
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-fmradio.so</library-name>
+    <feature-install-uri>fmradio.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/fmradio</name>
+    </api-feature>
+</plugin-properties>
diff --git a/src/FMRadio/plugin_config.cpp b/src/FMRadio/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..1246ae2
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+static FunctionMapping createFMRadioFunctions();
+static FunctionMapping FMRadioFunctions = createFMRadioFunctions();
+
+DEFINE_FUNCTION_GETTER(FMRadio, FMRadioFunctions);
+
+static FunctionMapping createFMRadioFunctions()
+{
+    FunctionMapping fMRadioMapping;
+    // TODO: implement here
+    return fMRadioMapping;
+}
+
+} // FMRadio
+} // DeviceAPI
diff --git a/src/FMRadio/plugin_config.h b/src/FMRadio/plugin_config.h
new file mode 100755 (executable)
index 0000000..c5c6e98
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _FMRADIO_PLUGIN_CONFIG_H_
+#define _FMRADIO_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+// attributes
+#define FMRADIO_MANAGER_FREQUENCY "frequency"
+#define FMRADIO_MANAGER_FREQUENCY_UPPER_BOUND "frequencyUpperBound"
+#define FMRADIO_MANAGER_FREQUENCY_LOWER_BOUND "frequencyLowerBound"
+#define FMRADIO_MANAGER_SIGNAL_STRENGTH "signalStrength"
+#define FMRADIO_MANAGER_MUTE "mute"
+#define FMRADIO_MANAGER_STATE "state"
+#define FMRADIO_MANAGER_IS_ANTENNA_CONNECTED "isAntennaConnected"
+
+// functions
+#define FMRADIO_MANAGER_API_START "start"
+#define FMRADIO_MANAGER_API_STOP "stop"
+#define FMRADIO_MANAGER_API_SEEK_UP "seekUp"
+#define FMRADIO_MANAGER_API_SEEK_DOWN "seekDown"
+#define FMRADIO_MANAGER_API_SCAN_START "scanStart"
+#define FMRADIO_MANAGER_API_SCAN_STOP "scanStop"
+#define FMRADIO_MANAGER_API_SET_FMRADIO_INTERRUPTED_LISTENER "setFMRadioInterruptedListener"
+#define FMRADIO_MANAGER_API_UNSET_FMRADIO_INTERRUPTED_LISTENER "unsetFMRadioInterruptedListener"
+#define FMRADIO_MANAGER_API_SET_ANTENNA_CHANGE_LISTENER "setAntennaChangeListener"
+#define FMRADIO_MANAGER_API_UNSET_ANTENNA_CHANGE_LISTENER "unsetAntennaChangeListener"
+
+
+
+DECLARE_FUNCTION_GETTER(FMRadio);
+
+#define FMRADIO_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getFMRadioFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _FMRADIO_PLUGIN_CONFIG_H_
diff --git a/src/FMRadio/plugin_initializer.cpp b/src/FMRadio/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..823c161
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+
+#include "JSFMRadioManager.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace FMRadio {
+
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\FMRadio] on_widget_start_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\FMRadio] on_widget_stop_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\FMRadio] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\FMRadio] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "fmradio",
+        (js_class_template_getter)JSFMRadioManager::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_END
+
+} // FMRadio
+} // DeviceAPI
diff --git a/src/Filesystem/CMakeLists.txt b/src/Filesystem/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..acaee9c
--- /dev/null
@@ -0,0 +1,86 @@
+SET(TARGET_NAME ${filesystem_target})
+SET(DESTINATION_NAME ${filesystem_dest})
+SET(TARGET_IMPL_NAME ${filesystem_impl})
+SET(TARGET_CONFIG_NAME ${filesystem_config})
+
+PKG_CHECK_MODULES(platform_pkgs_filesystem REQUIRED capi-appfw-application storage libpcrecpp ecore capi-system-info)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_filesystem_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    EventResolve.cpp
+    EventGetStorage.cpp
+    EventListStorages.cpp
+    EventCopy.cpp
+    EventMove.cpp
+    EventListNodes.cpp
+    EventOpen.cpp
+    NodeFilter.cpp
+    StorageProperties.cpp
+    EventStorageStateChanged.cpp
+    Manager.cpp
+    Node.cpp
+    Path.cpp
+    Stream.cpp
+    NodeFilterMatcher.cpp
+    JSFilesystemManager.cpp
+    JSFile.cpp
+    File.cpp
+    JSFilestream.cpp
+    JSStorage.cpp
+    JSErrors.cpp
+    Converter.cpp
+    Encodings.cpp
+    FilesystemUtils.cpp
+    FilesystemPathUtils.cpp
+    FilesystemExternalUtils.cpp
+    FilesystemErrorUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${LIBS_WIDGETDB}
+    ${tizen_impl}
+    ${platform_pkgs_filesystem_LIBRARIES}
+)
+
+SET(SRCS_CONFIG
+    plugin_config.cpp
+)
+
+ADD_LIBRARY(${TARGET_CONFIG_NAME} SHARED ${SRCS_CONFIG})
+
+TARGET_LINK_LIBRARIES(${TARGET_CONFIG_NAME}
+    ${LIBS_COMMON}
+)
+
+SET(SRCS
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+    ${TARGET_CONFIG_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_CONFIG_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/filesystem
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Filesystem/Converter.cpp b/src/Filesystem/Converter.cpp
new file mode 100755 (executable)
index 0000000..2fd16a1
--- /dev/null
@@ -0,0 +1,368 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Converter.cpp
+ */
+
+#include "Converter.h"
+
+#include <Logger.h>
+#include <Commons/Exception.h>
+#include <PlatformException.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+
+#include "Manager.h"
+#include "Path.h"
+#include "JSFile.h"
+#include "Encodings.h"
+#include "JSStorage.h"
+#include "FilesystemUtils.h"
+#include "FilesystemPathUtils.h"
+
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace DeviceAPI {
+namespace Filesystem{
+
+namespace {
+const char* PROPERTY_FILEFILTER_NAME = "name";
+const char* PROPERTY_FILEFILTER_START_CREATED = "startCreated";
+const char* PROPERTY_FILEFILTER_END_CREATED = "endCreated";
+const char* PROPERTY_FILEFILTER_START_MODIFIED = "startModified";
+const char* PROPERTY_FILEFILTER_END_MODIFIED = "endModified";
+const char* ACCESS_MODE_READ = "r";
+const char* ACCESS_MODE_APPEND = "a";
+const char* ACCESS_MODE_WRITE = "w";
+const char* ACCESS_MODE_READ_WRITE = "rw";
+const char* STORAGE_TYPE_STATE_MOUNTED = "MOUNTED";
+const char* STORAGE_TYPE_STATE_REMOVED = "REMOVED";
+const char* STORAGE_TYPE_STATE_UNMOUNTABLE = "REMOVED";
+const char* STORAGE_TYPE_INTERNAL = "INTERNAL";
+const char* STORAGE_TYPE_EXTERNAL = "EXTERNAL";
+
+
+const char* ENCODINGS[] = {
+    DeviceAPI::Filesystem::Encodings::UTF8,
+    DeviceAPI::Filesystem::Encodings::ISO88591,
+    DeviceAPI::Filesystem::Encodings::SJIS,
+    NULL
+};
+} // namespace
+
+
+Converter::Converter(JSContextRef context) : WrtDeviceApis::CommonsJavaScript::Converter(context)
+{
+}
+
+JSValueRef Converter::toJSValueRef(
+        const NodeList& arg,
+        const File::PermissionList &parentPermissions,
+        JSContextRef context)
+{
+    JSObjectRef jsResult = JSCreateArrayObject(m_context, 0, NULL);
+    if (!jsResult) {
+        LOGW("TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException(
+                 "Could not create js array object");
+    }
+
+    for (std::size_t i = 0; i < arg.size(); ++i)
+    {
+        FilePtr priv = FilePtr(new File(arg[i], parentPermissions));
+        JSObjectRef jsObject = JSFile::makeJSObject(m_context, priv, &Manager::getInstance());
+        if (!jsObject) {
+            LOGW("TypeMismatchException");
+            throw DeviceAPI::Common::TypeMismatchException(
+                     "Could not create JS object.");
+        }
+        if (!JSSetArrayElement(m_context, jsResult, i, jsObject)) {
+            LOGW("TypeMismatchException");
+            throw DeviceAPI::Common::TypeMismatchException(
+                     "Could not insert value into js array");
+        }
+    }
+
+    return jsResult;
+}
+
+
+JSValueRef Converter::toJSValueRef(unsigned char* data, std::size_t num)
+{
+    JSObjectRef result = JSCreateArrayObject(m_context, 0, NULL);
+    if (!result) {
+        LOGW("TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException(
+                "Could not create array object.");
+    }
+
+    for (std::size_t i = 0; i < num; ++i) {
+        JSValueRef value = JSValueMakeNumber(m_context, data[i]);
+        if (!JSSetArrayElement(m_context, result, i, value)) {
+            LOGW("TypeMismatchException");
+            throw DeviceAPI::Common::TypeMismatchException(
+                    "Could not fill array.");
+        }
+    }
+
+    return result;
+}
+
+JSValueRef Converter::toJSValueRef(unsigned long long arg)
+{
+    return JSValueMakeNumber(m_context, arg);
+}
+
+
+
+PathPtr Converter::toPath(const JSValueRef& arg)
+{
+    try {
+        std::string path = toString(arg);
+        if (!Utils::isPathValid(path) || path.empty()) {
+            LOGW("TypeMismatchException");
+            throw DeviceAPI::Common::InvalidValuesException(
+                    "Invalid path component.");
+        }
+        return Path::create(path);
+    } catch (const Commons::ConversionException exception) {
+        LOGW("caught ConversionException");
+        LOGW("throw TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException("Not a valid path.");
+    } catch (const DeviceAPI::Common::TypeMismatchException exception) {
+        LOGW("caught TypeMismatchException");
+        LOGW("throw TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException("Not a valid path.");
+    }
+}
+std::string Converter::checkPercentSign(std::string& arg)
+{
+    size_t pos = 0;
+
+    pos = arg.find("%");
+
+    if (pos == std::string::npos)
+    {
+        return arg;
+    }
+    else if (arg[arg.size() - 1] == '%')
+    {
+        arg[arg.size() - 1] = ')';
+
+        if (arg[0] == '%')
+        {
+            arg[0] = '(';
+        }
+        else
+        {
+            arg.insert(0, "^");
+            arg.insert(1, "(");
+        }
+
+        return arg;
+    }
+    LOGW("throw TypeMismatchException");
+    throw DeviceAPI::Common::TypeMismatchException("Invalid Filter");
+}
+
+NodeFilterPtr Converter::toNodeFilter(const JSValueRef& arg)
+{
+    JSObjectRef filter = toJSObjectRef(arg);
+
+    NodeFilterPtr result(new NodeFilter());
+    JSValueRef prop = NULL;
+    prop = JSUtils::getJSProperty(m_context, filter, PROPERTY_FILEFILTER_NAME);
+    if (prop) {
+        std::string nameFilter = toString(prop);
+        result->setName(makeOptionalPair(checkPercentSign(nameFilter)));
+    }
+
+    prop = JSUtils::getJSProperty(m_context, filter, PROPERTY_FILEFILTER_START_CREATED);
+    if (prop) {
+        result->setMinCreated(makeOptionalPair(toDateTimeT(prop)));
+    }
+
+    prop = JSUtils::getJSProperty(m_context, filter, PROPERTY_FILEFILTER_END_CREATED);
+    if (prop) {
+        result->setMaxCreated(makeOptionalPair(toDateTimeT(prop)));
+    }
+
+    prop = JSUtils::getJSProperty(m_context, filter, PROPERTY_FILEFILTER_START_MODIFIED);
+    if (prop) {
+        result->setMinModified(makeOptionalPair(toDateTimeT(prop)));
+    }
+
+    prop = JSUtils::getJSProperty(m_context, filter, PROPERTY_FILEFILTER_END_MODIFIED);
+    if (prop) {
+        result->setMaxModified(makeOptionalPair(toDateTimeT(prop)));
+    }
+
+    return result;
+}
+
+AccessMode Converter::toAccessMode(const JSValueRef& arg)
+{
+    std::string mode = toString_(arg);
+    if (ACCESS_MODE_READ == mode) {
+        return AM_READ;
+    } else if (ACCESS_MODE_APPEND == mode) {
+        return AM_APPEND;
+    } else if (ACCESS_MODE_WRITE == mode) {
+        return AM_WRITE;
+    } else if (ACCESS_MODE_READ_WRITE == mode) {
+        return AM_READ_WRITE;
+    }
+
+    LOGW("throw TypeMismatchException");
+    throw DeviceAPI::Common::TypeMismatchException("Invalid mode.");
+}
+
+std::string Converter::toEncoding(const JSValueRef& arg)
+{
+    std::string result = toString_(arg);
+    const char** ptr = ENCODINGS;
+    while (*ptr) {
+        if (result == *ptr) {
+            return result;
+        }
+        ++ptr;
+    }
+    LOGW("throw TypeMismatchException");
+    throw DeviceAPI::Common::TypeMismatchException("Invalid encoding");
+}
+JSValueRef Converter::toStorageState(const short type)
+{
+    switch (type)
+    {
+        case JSStorage::STATE_MOUNTED:
+            return toJSValueRef(STORAGE_TYPE_STATE_MOUNTED);
+        case JSStorage::STATE_REMOVED:
+            return toJSValueRef(STORAGE_TYPE_STATE_REMOVED);
+        case JSStorage::STATE_UNMOUNTABLE:
+            return toJSValueRef(STORAGE_TYPE_STATE_UNMOUNTABLE);
+    }
+    LOGW("throw TypeMismatchException");
+    throw DeviceAPI::Common::TypeMismatchException("Invalid storage type");
+}
+
+JSValueRef Converter::toStorageType(const short state)
+{
+    switch (state)
+    {
+        case StorageProperties::TYPE_INTERNAL:
+            return toJSValueRef(STORAGE_TYPE_INTERNAL);
+        case StorageProperties::TYPE_EXTERNAL:
+            return toJSValueRef(STORAGE_TYPE_EXTERNAL);
+    }
+    LOGW("throw TypeMismatchException");
+    throw DeviceAPI::Common::TypeMismatchException("Invalid storage type");
+}
+
+JSValueRef Converter::toJSValueRef(
+        const StoragePropertiesPtr &arg,
+        JSContextRef context,
+        Common::SecurityAccessor* srcSecurityAccessor)
+{
+    StorageProperties tmpStorage;
+
+    tmpStorage.setLabel(arg->getLabel());
+    tmpStorage.setType(arg->getType());
+
+    switch (arg->getState()) {
+    case StorageProperties::STATE_MOUNTED :
+    case StorageProperties::STATE_MOUNTED_READONLY :
+        tmpStorage.setState(JSStorage::STATE_MOUNTED);
+        break;
+    case StorageProperties::STATE_REMOVED:
+        tmpStorage.setState(JSStorage::STATE_REMOVED);
+        break;
+    case StorageProperties::STATE_UNMOUNTABLE:
+        tmpStorage.setState(JSStorage::STATE_UNMOUNTABLE);
+        break;
+    }
+
+    JSObjectRef jsObject = JSStorage::createJSObject(context, tmpStorage,
+        srcSecurityAccessor);
+    if (!jsObject) {
+        LOGW("throw TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException(
+                "Could not create JS object.");
+    }
+
+    return toJSValueRef(jsObject);
+}
+
+JSValueRef Converter::toJSValueRef(
+        const std::vector<StoragePropertiesPtr>& arg,
+        JSContextRef context)
+{
+    JSObjectRef jsResult = JSCreateArrayObject(m_context, 0, NULL);
+    if (!jsResult) {
+        LOGW("throw TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException(
+                "Could not create js array object");
+    }
+
+    StorageProperties tmpStorage;
+
+    for (size_t i = 0; i < arg.size(); i++) {
+        tmpStorage.setLabel(arg[i]->getLabel());
+        tmpStorage.setType(arg[i]->getType());
+
+        switch (arg[i]->getState()) {
+        case StorageProperties::STATE_MOUNTED :
+        case StorageProperties::STATE_MOUNTED_READONLY :
+            tmpStorage.setState(JSStorage::STATE_MOUNTED);
+            break;
+        case StorageProperties::STATE_REMOVED:
+            tmpStorage.setState(JSStorage::STATE_REMOVED);
+            break;
+        case StorageProperties::STATE_UNMOUNTABLE:
+            tmpStorage.setState(JSStorage::STATE_UNMOUNTABLE);
+            break;
+        }
+
+        JSObjectRef jsObject = JSObjectMake(m_context, NULL, NULL);
+        const ScopedJSStringRef labelStr(JSStringCreateWithUTF8CString("label"));
+        const ScopedJSStringRef typeStr(JSStringCreateWithUTF8CString("type"));
+        const ScopedJSStringRef stateStr(JSStringCreateWithUTF8CString("state"));
+
+        JSObjectSetProperty(m_context, jsObject, labelStr.get(), toJSValueRef(tmpStorage.getLabel()), kJSPropertyAttributeReadOnly, NULL);
+        JSObjectSetProperty(m_context, jsObject, typeStr.get(), toStorageType(tmpStorage.getType()), kJSPropertyAttributeReadOnly, NULL);
+        JSObjectSetProperty(m_context, jsObject, stateStr.get(), toStorageState(tmpStorage.getState()), kJSPropertyAttributeReadOnly, NULL);
+
+        if (!jsObject) {
+            LOGW("throw TypeMismatchException");
+            throw DeviceAPI::Common::TypeMismatchException(
+                    "Could not create JS object.");
+        }
+
+        if (!JSSetArrayElement(m_context, jsResult, i, jsObject)) {
+            LOGW("throw TypeMismatchException");
+            throw DeviceAPI::Common::TypeMismatchException(
+                    "Could not insert value into js array");
+        }
+    }
+
+    return jsResult;
+}
+}
+}
diff --git a/src/Filesystem/Converter.h b/src/Filesystem/Converter.h
new file mode 100644 (file)
index 0000000..ca65336
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Converter.h
+ */
+
+#ifndef TIZENAPIS_TIZEN_FILESYSTEM_CONVERTER_H_
+#define TIZENAPIS_TIZEN_FILESYSTEM_CONVERTER_H_
+
+#include <vector>
+#include <string>
+#include <map>
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/Converter.h>
+#include "Enums.h"
+#include "Path.h"
+#include "Node.h"
+#include "NodeFilter.h"
+#include "StorageProperties.h"
+#include "JSFile.h"
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Filesystem {
+class Converter : public WrtDeviceApis::CommonsJavaScript::Converter
+{
+public:
+    using WrtDeviceApis::CommonsJavaScript::Converter::toJSValueRef;
+
+public:
+    explicit Converter(JSContextRef context);
+
+    JSValueRef toJSValueRef(
+            const NodeList& arg,
+            const File::PermissionList &parentPermissions,
+            JSContextRef context);
+    JSValueRef toJSValueRef(unsigned char* data,
+        std::size_t num);
+    JSValueRef toJSValueRef(unsigned long long arg);
+
+    PathPtr toPath(const JSValueRef& arg);
+
+    NodeFilterPtr toNodeFilter(const JSValueRef& arg);
+
+    AccessMode toAccessMode(const JSValueRef& arg);
+
+    std::string toEncoding(const JSValueRef& arg);
+
+    JSValueRef toStorageType(const short type);
+    JSValueRef toStorageState(const short state);
+    std::string checkPercentSign(std::string& arg);
+
+    JSValueRef toJSValueRef(
+            const StoragePropertiesPtr &arg,
+            JSContextRef context,
+            Common::SecurityAccessor* srcSecurityAccessor);
+
+    JSValueRef toJSValueRef(
+        const std::vector<StoragePropertiesPtr>& arg,
+        JSContextRef context);
+};
+
+typedef WrtDeviceApis::CommonsJavaScript::ConverterFactory<Converter> ConverterFactory;
+typedef ConverterFactory::ConverterType ConverterPtr;
+}
+}
+
+#endif
diff --git a/src/Filesystem/Encodings.cpp b/src/Filesystem/Encodings.cpp
new file mode 100755 (executable)
index 0000000..edc767a
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Encodings.cpp
+ */
+
+#include "Encodings.h"
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+namespace Encodings {
+const char* UTF8 = "UTF-8";
+
+const char* ISO88591 = "ISO-8859-1";
+const char* SJIS = "SJIS";
+}
+}
+}
diff --git a/src/Filesystem/Encodings.h b/src/Filesystem/Encodings.h
new file mode 100644 (file)
index 0000000..f559921
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Encodings.h
+ */
+
+#ifndef TIZENAPIS_TIZEN_FILESYSTEM_ENCODINGS_H_
+#define TIZENAPIS_TIZEN_FILESYSTEM_ENCODINGS_H_
+
+namespace DeviceAPI {
+namespace Filesystem {
+namespace Encodings {
+extern const char* UTF8;
+
+extern const char* ISO88591;
+extern const char* SJIS;
+}
+}
+}
+
+#endif
diff --git a/src/Filesystem/Enums.h b/src/Filesystem/Enums.h
new file mode 100644 (file)
index 0000000..e0fb4d6
--- /dev/null
@@ -0,0 +1,117 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Enums.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_ENUMS_H_
+#define TIZENAPIS_FILESYSTEM_ENUMS_H_
+
+#include <string>
+#include <map>
+
+namespace DeviceAPI {
+namespace Filesystem {
+enum LocationType
+{
+    LT_APPS,
+    LT_DOCUMENTS,
+    LT_DOWNLOADS,
+    LT_GAMES,
+    LT_IMAGES,
+    LT_OTHERS,
+    LT_ROOT,
+    LT_SDCARD,
+    LT_USBHOST,
+    LT_SOUNDS,
+    LT_TEMP,
+    LT_VIDEOS,
+    LT_RINGTONES,
+    LT_WGTPKG,
+    LT_WGTPRV,
+    LT_WGTPRVTMP,
+    LT_CAMERA
+};
+
+enum NodeType
+{
+    NT_DIRECTORY,
+    NT_FILE
+};
+
+enum AccessMode
+{
+    AM_READ     = 0x0001,
+    AM_WRITE    = 0x0002,
+    AM_READ_WRITE = 0x0003,
+    AM_APPEND   = 0x0004
+
+
+};
+
+/**
+ * Used in @see Manager::access().
+ */
+enum AccessType
+{
+    AT_EXISTS   = 0x0000, //!< AT_EXISTS - checks for existence
+    AT_READ     = 0x0001, //!< AT_READ   - checks for read access
+    AT_WRITE    = 0x0002, //!< AT_WRITE  - checks for write access
+    AT_EXEC     = 0x0004 //!< AT_EXEC   - checks for execution access
+};
+
+enum Permissions
+{
+    PERM_NONE   = 0x0000,
+    PERM_READ   = 0x0001,
+    PERM_WRITE  = 0x0002
+};
+
+enum PlatformMode
+{
+    PM_USER_READ    = 0x0100,
+    PM_USER_WRITE   = 0x0080,
+    PM_USER_EXEC    = 0x0040,
+    PM_GROUP_READ   = 0x0020,
+    PM_GROUP_WRITE  = 0x0010,
+    PM_GROUP_EXEC   = 0x0008,
+    PM_OTHER_READ   = 0x0004,
+    PM_OTHER_WRITE  = 0x0002,
+    PM_OTHER_EXEC   = 0x0001,
+    PM_NONE         = 0x0000
+};
+
+enum Options
+{
+    OPT_NONE        = 0x0000,
+    OPT_OVERWRITE   = 0x0001,
+    OPT_RECURSIVE   = 0x0002
+};
+
+enum FindFilter
+{
+    FF_NAME,
+    FF_CREATED,
+    FF_MODIFIED,
+    FF_SIZE
+};
+typedef std::map<FindFilter, std::string> FiltersMap;
+} // Filesystem
+} // TizenApis
+
+#endif /* TIZENAPIS_FILESYSTEM_ENUMS_H_ */
diff --git a/src/Filesystem/EventCopy.cpp b/src/Filesystem/EventCopy.cpp
new file mode 100755 (executable)
index 0000000..e115c2c
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventCopy.cpp
+ */
+
+#include "EventCopy.h"
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+EventCopy::EventCopy(JSContextRef aGlobalCtx):
+    Utils::FilesystemEvent(aGlobalCtx),
+    m_options(OPT_NONE)
+{
+}
+
+PathPtr EventCopy::getDestination()
+{
+    return m_dest;
+}
+
+void EventCopy::setDestination(PathPtr aDestination)
+{
+    m_dest = aDestination;
+}
+
+PathPtr EventCopy::getSource()
+{
+    return m_src;
+}
+
+void EventCopy::setSource(PathPtr aSource)
+{
+    m_src = aSource;
+}
+
+NodePtr EventCopy::getResult()
+{
+    return m_result;
+}
+
+void EventCopy::setResult(NodePtr node)
+{
+    m_result = node;
+}
+
+int EventCopy::getOptions() const
+{
+    return m_options;
+}
+
+void EventCopy::setOptions(int options)
+{
+    m_options = options;
+}
+
+void EventCopy::setRealDestination(const std::string& aRealDestination)
+{
+    m_realDestination = aRealDestination;
+}
+void EventCopy::setRealSource(const std::string& aRealSource)
+{
+    m_realSource = aRealSource;
+}
+std::string EventCopy::getRealDestination()
+{
+    return m_realDestination;
+}
+std::string EventCopy::getRealSource()
+{
+    return m_realSource;
+}
+
+
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/EventCopy.h b/src/Filesystem/EventCopy.h
new file mode 100644 (file)
index 0000000..92db487
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventCopy.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_EVENTCOPY_H_
+#define TIZENAPIS_FILESYSTEM_EVENTCOPY_H_
+
+#include <memory>
+#include <Commons/IEvent.h>
+#include "Path.h"
+#include "Node.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class EventCopy : public  DeviceAPI::Filesystem::Utils::FilesystemEvent
+{
+  public:
+    EventCopy(JSContextRef aGlobalCtx);
+    PathPtr getDestination();
+    void setDestination(PathPtr aDestination);
+    PathPtr getSource();
+    void setSource(PathPtr aSource);
+    NodePtr getResult();
+    void setResult(NodePtr node);
+    int getOptions() const;
+    void setOptions(int options);
+    //! Sets real destination path which represents file in filesystem.
+    //! @param aRealDestination contains path to file.
+    void setRealDestination(const std::string& aRealDestination);
+    //! Sets real source path, which represents file in filesystem.
+    //! @param aRealSource contains path to file.
+    void setRealSource(const std::string& aRealSource);
+    //! Gets real destination path which represents file in filesystem.
+    //! @return contains path to file.
+    std::string getRealDestination();
+    //! Gets real source path, which represents file in filesystem.
+    //! @return contains path to file.
+    std::string getRealSource();
+
+  private:
+    PathPtr m_src;   ///< Source path.
+    PathPtr m_dest;  ///< Destination path.
+    NodePtr m_result; ///< Result node.
+    //! Options for copy actiona @see WrtPlugins::Api::Filesystem::Options.
+    int m_options;
+    std::string m_realSource; ///< Real source path
+    std::string m_realDestination; ///< Real destination path
+};
+
+typedef std::shared_ptr<EventCopy> EventCopyPtr;
+} // Filesystem
+} // TizenApis
+
+#endif // TIZENAPIS_FILESYSTEM_EVENTCOPY_H_
diff --git a/src/Filesystem/EventGetStorage.cpp b/src/Filesystem/EventGetStorage.cpp
new file mode 100755 (executable)
index 0000000..8098855
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventGetStorage.cpp
+ */
+
+#include "EventGetStorage.h"
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+EventGetStorage::EventGetStorage(JSContextRef aGlobalCtx):
+    Utils::FilesystemEvent(aGlobalCtx)
+{
+}
+
+void EventGetStorage::setLabel(const std::string &Label)
+{
+    label = Label;
+}
+
+std::string EventGetStorage::getLabel() const
+{
+    return label;
+}
+
+void EventGetStorage::setResult (const StoragePropertiesPtr &Storages)
+{
+    storages = Storages;
+}
+
+StoragePropertiesPtr EventGetStorage::getResult() const
+{
+    return storages;
+}
+
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/EventGetStorage.h b/src/Filesystem/EventGetStorage.h
new file mode 100644 (file)
index 0000000..8046d8b
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        EventGetStorage.h
+*/
+
+#ifndef TIZENAPIS_API_FILESYSTEM_EVENT_GET_STORAGE_H_
+#define TIZENAPIS_API_FILESYSTEM_EVENT_GET_STORAGE_H_
+
+#include <memory>
+#include <string>
+#include "FilesystemUtils.h"
+#include "StorageProperties.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+class EventGetStorage : public DeviceAPI::Filesystem::Utils::FilesystemEvent
+{
+public:
+    void setLabel(const std::string &Label);
+    std::string getLabel() const;
+    void setResult (const StoragePropertiesPtr& Storages);
+    StoragePropertiesPtr getResult() const;
+    EventGetStorage(JSContextRef aGlobalCtx);
+private:
+    std::string label;
+    StoragePropertiesPtr storages;
+};
+
+typedef std::shared_ptr<EventGetStorage> EventGetStoragePtr;
+} // Filesystem
+} // TizenApis
+
+#endif //TIZENAPIS_API_FILESYSTEM_EVENT_GET_STORAGE_H_
diff --git a/src/Filesystem/EventListNodes.cpp b/src/Filesystem/EventListNodes.cpp
new file mode 100755 (executable)
index 0000000..ab4564a
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventListNodes.cpp
+ */
+
+#include "EventListNodes.h"
+#include <PlatformException.h>
+#include <Logger.h>
+#include "Node.h"
+#include "Enums.h"
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+EventListNodes::EventListNodes(JSContextRef aGlobalCtx) :
+        Utils::FilesystemEvent(aGlobalCtx)
+{
+}
+
+NodeFilterPtr EventListNodes::getFilter() const
+{
+    return m_filter;
+}
+
+void EventListNodes::setFilter(const NodeFilterPtr& filter)
+{
+    m_filter = filter;
+}
+
+NodeList EventListNodes::getResult() const
+{
+    return m_list;
+}
+
+void EventListNodes::setResult(const NodeList& list)
+{
+    m_list = list;
+}
+
+void EventListNodes::setParentPermissions(
+        EventListNodes::PermissionList aParentPermissions)
+{
+    m_parentPermissions = aParentPermissions;
+}
+EventListNodes::PermissionList EventListNodes::getParentPermissions()
+{
+    return m_parentPermissions;
+}
+
+void EventListNodes::setNode(NodePtr aNode)
+{
+    m_node = aNode;
+}
+NodePtr EventListNodes::getNode()
+{
+    return m_node;
+}
+
+
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/EventListNodes.h b/src/Filesystem/EventListNodes.h
new file mode 100644 (file)
index 0000000..c2318f8
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventListNodes.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_EVENTLISTNODES_H_
+#define TIZENAPIS_FILESYSTEM_EVENTLISTNODES_H_
+
+#include <memory>
+#include "FilesystemUtils.h"
+#include "NodeTypes.h"
+#include "NodeFilter.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+class EventListNodes : public DeviceAPI::Filesystem::Utils::FilesystemEvent
+{
+  public:
+    typedef std::vector<int> PermissionList;
+    /**
+     * Creates new event object.
+     * @param path Node to list children for.
+     * @return New object.
+     */
+    explicit EventListNodes(JSContextRef aGlobalCtx);
+
+    /**
+     * Gets filter.
+     * @return Filter.
+     */
+    NodeFilterPtr getFilter() const;
+
+    /**
+     * Sets filter.
+     * @param filter Filter to list only specific nodes.
+     */
+    void setFilter(const NodeFilterPtr& filter);
+
+    /**
+     * Gets nodes.
+     * @return Nodes list.
+     */
+    NodeList getResult() const;
+
+    /**
+     * Sets nodes list.
+     * @param list Nodes list.
+     */
+    void setResult(const NodeList& list);
+
+    void setParentPermissions(PermissionList aParentPermissions);
+    PermissionList getParentPermissions();
+    void setNode(NodePtr aNode);
+    NodePtr getNode();
+  private:
+    NodeList m_list;      ///< List of child nodes.
+    NodePtr m_node;      ///< Node to list children for.
+    NodeFilterPtr m_filter; ///< Filter.
+    PermissionList m_parentPermissions;
+};
+
+typedef std::shared_ptr<EventListNodes> EventListNodesPtr;
+} // Filesystem
+} // TizenApis
+
+#endif // TIZENAPIS_FILESYSTEM_EVENTLISTNODES_H_
diff --git a/src/Filesystem/EventListStorages.cpp b/src/Filesystem/EventListStorages.cpp
new file mode 100755 (executable)
index 0000000..ac912f4
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventListStorages.cpp
+ */
+
+#include "EventListStorages.h"
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+EventListStorages::EventListStorages(JSContextRef aGlobalCtx):
+    Utils::FilesystemEvent(aGlobalCtx)
+{
+}
+
+void EventListStorages::setResult (const std::vector<StoragePropertiesPtr>& Storages)
+{
+    storages = Storages;
+}
+
+std::vector<StoragePropertiesPtr> EventListStorages::getResult() const
+{
+    return storages;
+}
+
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/EventListStorages.h b/src/Filesystem/EventListStorages.h
new file mode 100644 (file)
index 0000000..3a15a93
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventListStorages.h
+ */
+
+#ifndef TIZENAPIS_API_FILESYSTEM_EVENT_LIST_STORAGES_H_
+#define TIZENAPIS_API_FILESYSTEM_EVENT_LIST_STORAGES_H_
+
+#include <memory>
+#include <vector>
+#include "StorageProperties.h"
+#include "FilesystemUtils.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class Manager;
+
+class EventListStorages : public DeviceAPI::Filesystem::Utils::FilesystemEvent
+{
+public:
+    void setResult (const std::vector<StoragePropertiesPtr>& Storages);
+    void setManager (Manager* aManager) { m_manager = aManager; }
+    Manager* getManager () { return m_manager; }
+    std::vector<StoragePropertiesPtr> getResult() const;
+    EventListStorages(JSContextRef aGlobalCtx);
+private:
+    Manager* m_manager;
+    std::vector<StoragePropertiesPtr> storages;
+};
+
+typedef std::shared_ptr<EventListStorages> EventListStoragesPtr;
+}
+}
+
+#endif
diff --git a/src/Filesystem/EventMove.cpp b/src/Filesystem/EventMove.cpp
new file mode 100755 (executable)
index 0000000..c4e16a1
--- /dev/null
@@ -0,0 +1,74 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventMove.cpp
+ */
+
+#include "EventMove.h"
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+EventMove::EventMove(JSContextRef aGlobalCtx) :
+    Utils::FilesystemEvent(aGlobalCtx),
+    m_options(OPT_NONE)
+{
+
+}
+
+PathPtr EventMove::getDestination()
+{
+    return m_dest;
+}
+
+void EventMove::setDestination(PathPtr aDestination)
+{
+    m_dest = aDestination;
+}
+
+PathPtr EventMove::getSource()
+{
+    return m_src;
+}
+
+void EventMove::setSource(PathPtr aSource)
+{
+    m_src = aSource;
+}
+
+NodePtr EventMove::getResult()
+{
+    return m_result;
+}
+
+void EventMove::setResult(const NodePtr& node)
+{
+    m_result = node;
+}
+
+int EventMove::getOptions() const
+{
+    return m_options;
+}
+
+void EventMove::setOptions(int options)
+{
+    m_options = options;
+}
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/EventMove.h b/src/Filesystem/EventMove.h
new file mode 100644 (file)
index 0000000..bba8606
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventMove.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_EVENTMOVE_H_
+#define TIZENAPIS_FILESYSTEM_EVENTMOVE_H_
+
+#include <memory>
+#include "Path.h"
+#include "Node.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+class EventMove : public Utils::FilesystemEvent
+{
+public:
+    EventMove(JSContextRef aGlobalCtx);
+    PathPtr getDestination();
+    void setDestination(PathPtr aDestination);
+    PathPtr getSource();
+    void setSource(PathPtr aSource);
+    NodePtr getResult();
+    void setResult(const NodePtr& node);
+    int getOptions() const;
+    void setOptions(int options);
+
+private:
+    PathPtr m_src;   ///< Source path.
+    PathPtr m_dest;  ///< Destination path.
+    NodePtr m_result; ///< Result node.
+    /// Options for copy action @see WrtPlugins::Api::Filesystem::Options.
+    int m_options;
+};
+
+typedef std::shared_ptr<EventMove> EventMovePtr;
+} // Filesystem
+} // TizenApis
+
+#endif // TIZENAPIS_FILESYSTEM_EVENTMOVE_H_
diff --git a/src/Filesystem/EventOpen.cpp b/src/Filesystem/EventOpen.cpp
new file mode 100755 (executable)
index 0000000..b6f1223
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventOpen.cpp
+ */
+
+#include "EventOpen.h"
+#include "Stream.h"
+#include "Node.h"
+
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+EventOpen::EventOpen(JSContextRef aGlobalCtx) :
+    Utils::FilesystemEvent(aGlobalCtx),
+    m_mode(0)
+{
+}
+
+StreamPtr EventOpen::getResult() const
+{
+    return m_stream;
+}
+
+void EventOpen::setResult(const StreamPtr& stream)
+{
+    m_stream = stream;
+}
+
+
+void EventOpen::setCharSet(const std::string &charSet)
+{
+    m_charSet = charSet;
+}
+
+std::string EventOpen::getCharSet() const
+{
+    return m_charSet;
+}
+
+void EventOpen::setMode(int aMode)
+{
+    m_mode = aMode;
+}
+
+int EventOpen::getMode() const
+{
+    return m_mode;
+}
+
+void EventOpen::setNode(NodePtr aNode)
+{
+    m_node = aNode;
+}
+NodePtr EventOpen::getNode()
+{
+    return m_node;
+}
+
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/EventOpen.h b/src/Filesystem/EventOpen.h
new file mode 100644 (file)
index 0000000..df85120
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventOpen.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_EVENTOPEN_H_
+#define TIZENAPIS_FILESYSTEM_EVENTOPEN_H_
+
+#include <memory>
+#include "FilesystemUtils.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class Node;
+typedef std::shared_ptr<Node> NodePtr;
+class Stream;
+typedef std::shared_ptr<Stream> StreamPtr;
+
+class EventOpen : public Utils::FilesystemEvent
+{
+public:
+    explicit EventOpen(JSContextRef aGlobalCtx);
+    int getMode() const;
+    void setMode(int aMode);
+    StreamPtr getResult() const;
+    void setResult(const StreamPtr& stream);
+    void setCharSet(const std::string &charSet);
+    std::string getCharSet() const;
+    void setNode(NodePtr aNode);
+    NodePtr getNode();
+private:
+    std::string m_charSet;
+    int m_mode;
+    StreamPtr m_stream;
+    NodePtr m_node;
+};
+
+typedef std::shared_ptr<EventOpen> EventOpenPtr;
+} // Filesystem
+} // TizenApis
+
+#endif // TIZENAPIS_FILESYSTEM_EVENTOPEN_H_
diff --git a/src/Filesystem/EventReadText.h b/src/Filesystem/EventReadText.h
new file mode 100644 (file)
index 0000000..a7899ef
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventReadText.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_EVENTREADTEXT_H_
+#define TIZENAPIS_FILESYSTEM_EVENTREADTEXT_H_
+
+#include <string>
+#include <memory>
+#include "Stream.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+class EventReadText : public DeviceAPI::Filesystem::Utils::FilesystemEvent
+{
+public:
+    std::shared_ptr<std::string> getResult() { return m_result; }
+    void setResult(const std::shared_ptr<std::string> aResult)
+    {
+        m_result = aResult;
+    }
+    void setCharSet(const std::string &aCharSet) { m_charSet = aCharSet; }
+    std::string getCharSet() const { return m_charSet; }
+    EventReadText(JSContextRef aGlobalCtx) :
+        Utils::FilesystemEvent(aGlobalCtx)
+    {}
+    void setStream(StreamPtr aStream) { m_stream = aStream; }
+    StreamPtr getStream() { return m_stream; }
+    void setNode(NodePtr aNode) { m_node = aNode; }
+    NodePtr getNode() { return m_node; }
+private:
+    std::shared_ptr<std::string> m_result;
+    StreamPtr m_stream;
+    NodePtr m_node;
+    std::string m_charSet;
+};
+
+typedef std::shared_ptr<EventReadText> EventReadTextPtr;
+} // Filesystem
+} // DeviceAPI
+
+#endif // TIZENAPIS_FILESYSTEM_EVENTREADTEXT_H_
diff --git a/src/Filesystem/EventRemove.cpp b/src/Filesystem/EventRemove.cpp
new file mode 100755 (executable)
index 0000000..98f7dea
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventRemove.cpp
+ */
+
+#include "EventRemove.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+EventRemove::EventRemove(const PathPtr& path) :
+    m_path(path),
+    m_options(OPT_NONE)
+{
+}
+
+PathPtr EventRemove::getPath() const
+{
+    return m_path;
+}
+
+int EventRemove::getOptions() const
+{
+    return m_options;
+}
+
+void EventRemove::setOptions(int options)
+{
+    m_options = options;
+}
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/EventRemove.h b/src/Filesystem/EventRemove.h
new file mode 100644 (file)
index 0000000..f8a72e8
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventRemove.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_EVENTREMOVE_H_
+#define TIZENAPIS_FILESYSTEM_EVENTREMOVE_H_
+
+#include "Node.h"
+#include "Enums.h"
+#include "FilesystemUtils.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+class EventRemove : public Utils::FilesystemEvent
+{
+public:
+    explicit EventRemove(JSContextRef aGlobalCtx):
+        Utils::FilesystemEvent(aGlobalCtx),
+        mOptions(0)
+    {}
+
+    void setPath(PathPtr aPath) { mPath = aPath; }
+    void setOptions(int aOptions) { mOptions = aOptions; }
+    void setNode(NodePtr aNode) {mNode = aNode; }
+    PathPtr getPath() { return mPath; }
+    int getOptions() { return mOptions; }
+    NodePtr getNode() { return mNode; }
+
+private:
+    PathPtr mPath; ///< Source path.
+    //* Options for remove action
+    //* @see WrtPlugins::Api::Filesystem::Options.
+    int mOptions;
+    NodePtr mNode;
+};
+
+typedef std::shared_ptr<EventRemove> EventRemovePtr;
+} // Filesystem
+} // TizenApis
+
+#endif // TIZENAPIS_FILESYSTEM_EVENTREMOVE_H_
diff --git a/src/Filesystem/EventResolve.cpp b/src/Filesystem/EventResolve.cpp
new file mode 100755 (executable)
index 0000000..dfd202b
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventResolve.cpp
+ */
+
+#include "EventResolve.h"
+
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+EventResolve::EventResolve(JSContextRef aGlobalCtx) :
+    Utils::FilesystemEvent(aGlobalCtx),
+    m_mode("rw")
+{
+}
+
+PathPtr EventResolve::getPath()
+{
+    return m_path;
+}
+
+void EventResolve::setPath(PathPtr aPath)
+{
+    m_path = aPath;
+}
+
+NodePtr EventResolve::getResult()
+{
+    return m_node;
+}
+
+void EventResolve::setResult(const NodePtr& node)
+{
+    m_node = node;
+}
+
+void EventResolve::setMode(const std::string &mode)
+{
+    m_mode = mode;
+}
+
+std::string EventResolve::getMode()
+{
+    return m_mode;
+}
+
+void EventResolve::setOriginalLocation(const std::string& org_locaton)
+{
+    m_orginal_location = org_locaton;
+}
+
+const std::string& EventResolve::getOriginalLocaton() const
+{
+    return m_orginal_location;
+}
+
+
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/EventResolve.h b/src/Filesystem/EventResolve.h
new file mode 100644 (file)
index 0000000..fa3bbe6
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventResolve.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_EVENTRESOLVE_H_
+#define TIZENAPIS_FILESYSTEM_EVENTRESOLVE_H_
+
+#include <memory>
+#include "FilesystemUtils.h"
+#include "Path.h"
+#include "Node.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+class EventResolve : public Utils::FilesystemEvent
+{
+public:
+    explicit EventResolve(JSContextRef aGlobalCtx);
+    PathPtr getPath();
+    void setPath(PathPtr aPath);
+    NodePtr getResult();
+    void setResult(const NodePtr& node);
+    void setMode(const std::string &mode);
+    std::string getMode();
+
+    void setOriginalLocation(const std::string& org_locaton);
+    const std::string& getOriginalLocaton() const;
+private:
+    PathPtr m_path; ///< Path to the requested node.
+    NodePtr m_node; ///< Resolved node.
+    std::string m_mode;
+    std::string m_orginal_location;
+};
+
+typedef std::shared_ptr<EventResolve> EventResolvePtr;
+} // Filesystem
+} // TizenApis
+
+#endif // WRTPLUGINS_FILESYSTEM_EVENTRESOLVE_H_
diff --git a/src/Filesystem/EventStorageStateChanged.cpp b/src/Filesystem/EventStorageStateChanged.cpp
new file mode 100755 (executable)
index 0000000..896c094
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventStorageStateChanged.cpp
+ */
+
+#include "EventStorageStateChanged.h"
+
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+EventStorageStateChanged::EventStorageStateChanged(JSContextRef aGlobalCtx):
+    Utils::FilesystemEvent(aGlobalCtx)
+{
+}
+
+void EventStorageStateChanged::setResult (const StoragePropertiesPtr &Storages)
+{
+    storages = Storages;
+}
+
+StoragePropertiesPtr EventStorageStateChanged::getResult() const
+{
+    return storages;
+}
+
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/EventStorageStateChanged.h b/src/Filesystem/EventStorageStateChanged.h
new file mode 100644 (file)
index 0000000..0d4b365
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventStorageStateChanged.h
+ */
+
+#ifndef TIZENAPIS_API_FILESYSTEM_EVENT_STORAGESTATE_CHANGED_H_
+#define TIZENAPIS_API_FILESYSTEM_EVENT_STORAGESTATE_CHANGED_H_
+
+#include <vector>
+#include <memory>
+
+#include "FilesystemUtils.h"
+#include "StorageProperties.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class EventStorageStateChanged : public Utils::FilesystemEvent
+{
+private:
+    StoragePropertiesPtr storages;
+
+public:
+    void setResult (const StoragePropertiesPtr& Storages);
+    StoragePropertiesPtr getResult() const;
+
+    EventStorageStateChanged(JSContextRef aGlobalCtx);
+};
+
+typedef std::shared_ptr<EventStorageStateChanged> EventStorageStateChangedPtr;
+
+} // Filesystem
+} // TizenApis
+
+#endif //TIZENAPIS_API_FILESYSTEM_EVENT_STORAGESTATE_CHANGED_H_
diff --git a/src/Filesystem/File.cpp b/src/Filesystem/File.cpp
new file mode 100644 (file)
index 0000000..623d489
--- /dev/null
@@ -0,0 +1,86 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "File.h"
+#include "FilesystemPathUtils.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+File::File(NodePtr node, const File::PermissionList &parentPermissions,
+        const std::string original_location) :
+    Common::SecurityAccessor(),
+    m_node(node),
+    m_parentPerms(parentPermissions),
+    m_context(NULL)
+{
+    if(Utils::isUriPath(original_location)) {
+        LOGD("original_location is URI: %s", original_location.c_str());
+        m_original_URI = original_location;
+    }
+    else {
+        LOGD("original_location is fullPath: %s", original_location.c_str());
+        m_original_fullpath = original_location;
+    }
+}
+
+File::~File()
+{
+}
+
+NodePtr File::getNode() const
+{
+    return m_node;
+}
+
+File::PermissionList File::getParentPermissions() const
+{
+    return m_parentPerms;
+}
+
+void File::setParentPermissions(const PermissionList &permissions)
+{
+    m_parentPerms = permissions;
+}
+
+void File::pushParentPermissions(int permissions)
+{
+    m_parentPerms.push_back(permissions);
+}
+
+void File::setContext(JSContextRef context)
+{
+    m_context = context;
+}
+
+JSContextRef File::getContext() const
+{
+    return m_context;
+}
+
+const std::string& File::getOriginalURI() const
+{
+    return m_original_URI;
+}
+
+const std::string& File::getOriginalFullPath() const
+{
+    return m_original_fullpath;
+}
+
+} //namespace DeviceAPI
+} //namespace Filesystem
diff --git a/src/Filesystem/File.h b/src/Filesystem/File.h
new file mode 100644 (file)
index 0000000..ef3894d
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef TIZENAPIS_TIZEN_FILE_H_
+#define TIZENAPIS_TIZEN_FILE_H_
+
+#include <memory>
+#include <Export.h>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <Commons/IEvent.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include "Node.h"
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class File;
+typedef std::shared_ptr<File> FilePtr;
+
+struct FileHolder {
+    FilePtr ptr;
+};
+
+class DLL_EXPORT File : public Common::SecurityAccessor
+{
+public:
+    typedef std::vector<int> PermissionList;
+
+    File(NodePtr node, const PermissionList &parentPermissions,
+            const std::string original_location = std::string());
+    virtual ~File();
+
+    NodePtr getNode() const;
+    PermissionList getParentPermissions() const;
+    void setParentPermissions(const PermissionList &permissions);
+    void pushParentPermissions(int permissions);
+
+    JSContextRef getContext() const;
+    void setContext(JSContextRef context);
+
+    const std::string& getOriginalURI() const;
+    const std::string& getOriginalFullPath() const;
+private:
+    NodePtr m_node;
+    PermissionList m_parentPerms;
+    JSContextRef m_context;
+
+    std::string m_original_URI;
+    std::string m_original_fullpath;
+};
+
+} //namespace DeviceAPI
+} //namespace Filesystem
+
+#endif //TIZENAPIS_TIZEN_FILE_H_
diff --git a/src/Filesystem/FilesystemErrorUtil.cpp b/src/Filesystem/FilesystemErrorUtil.cpp
new file mode 100755 (executable)
index 0000000..ddd8f94
--- /dev/null
@@ -0,0 +1,62 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "FilesystemErrorUtil.h"
+
+#include <sstream>
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+using namespace DeviceAPI::Common;
+
+void FilesystemErrorUtil::throwFilesystemException(const int errorCode, const std::string &hint)
+{
+    std::stringstream ss;
+    ss << hint << " : " << getFilesystemErrorMessage(errorCode);
+    LOGE("%s", ss.str().c_str());
+
+    switch(errorCode) {
+    case STORAGE_ERROR_INVALID_PARAMETER:
+            throw InvalidValuesException(ss.str().c_str());
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+std::string FilesystemErrorUtil::getFilesystemErrorMessage(const int errorCode)
+{
+    LOGE("%d", errorCode);
+
+    switch(errorCode) {
+    case STORAGE_ERROR_INVALID_PARAMETER:
+            return "Invalid Parameter";
+        case STORAGE_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case STORAGE_ERROR_NOT_SUPPORTED:
+            return "Storage not supported";
+        case STORAGE_ERROR_OPERATION_FAILED:
+            return "Operation failed";
+        default:
+            return "Unknown Error";
+    }
+}
+
+} // Filesystem
+} // DeviceAPI
diff --git a/src/Filesystem/FilesystemErrorUtil.h b/src/Filesystem/FilesystemErrorUtil.h
new file mode 100755 (executable)
index 0000000..df0649e
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_FILESYSTEM_ERROR_UTIL_H_
+#define __TIZEN_FILESYSTEM_ERROR_UTIL_H_
+
+#include <string>
+#include <storage/storage.h>
+
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class FilesystemErrorUtil {
+public:
+    static void throwFilesystemException(const int errorCode, const std::string &hint);
+    static std::string getFilesystemErrorMessage(const int errorCode);
+};
+
+} // Filesystem
+} // DeviceAPI
+
+#endif // __TIZEN_FILESYSTEM_ERROR_UTIL_H_
\ No newline at end of file
diff --git a/src/Filesystem/FilesystemExternalUtils.cpp b/src/Filesystem/FilesystemExternalUtils.cpp
new file mode 100755 (executable)
index 0000000..17418cb
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        FilesystemExternalUtils.cpp
+ */
+
+#include "FilesystemExternalUtils.h"
+
+#include <string>
+#include <sys/stat.h>
+#include <cerrno>
+#include <cstring>
+#include <cstdlib>
+#include <unistd.h>
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Export.h>
+
+#include "Enums.h"
+#include "Manager.h"
+#include "FilesystemUtils.h"
+#include "FilesystemPathUtils.h"
+#include "JSErrors.h"
+
+
+namespace DeviceAPI
+{
+namespace Filesystem
+{
+namespace External
+{
+
+void DLL_EXPORT initializeManager() {
+    LOGD("initializeManager start");
+    Utils::initializeManager();
+    LOGD("initializeManager end");
+}
+
+std::string DLL_EXPORT fromVirtualPath(const std::string& arg, JSContextRef context)
+{
+    LOGD("fromVirtualPath start");
+    std::string fullPath;
+    {
+        auto path = DeviceAPI::Filesystem::Utils::fromVirtualPath(context, arg);
+        fullPath = path->getFullPath();
+    }
+    LOGD("fromVirtualPath end %s -> %s", arg.c_str(), fullPath.c_str());
+    return fullPath;
+}
+
+std::string DLL_EXPORT toVirtualPath(const std::string& arg, JSContextRef context)
+{
+    LOGD("toVirtualPath start");
+    auto virtualPath = Utils::toVirtualPath(context, arg);
+    LOGD("toVirtualPath end %s -> %s", arg.c_str(), virtualPath.c_str());
+    return virtualPath;
+}
+
+bool DLL_EXPORT isVirtualPath(const std::string& path)
+{
+    LOGD("isVirtualPath start");
+    bool result = Utils::isVirtualPath(path);
+    LOGD("isVirtualPath end");
+    return result;
+}
+
+}
+}
+}
+
+
+
+
+
+
+
+
diff --git a/src/Filesystem/FilesystemExternalUtils.h b/src/Filesystem/FilesystemExternalUtils.h
new file mode 100644 (file)
index 0000000..b7dbae6
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        FilesystemExternalUtils.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_EXTERNAL_UTILS_H_
+#define TIZENAPIS_FILESYSTEM_EXTERNAL_UTILS_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI
+{
+namespace Filesystem
+{
+namespace External
+{
+
+void initializeManager();
+
+std::string fromVirtualPath(const std::string& arg, JSContextRef context = NULL);
+
+std::string toVirtualPath(const std::string& arg,  JSContextRef context = NULL);
+
+bool isVirtualPath(const std::string& path);
+
+}
+}
+}
+
+#endif  //ifndef TIZENAPIS_FILESYSTEM_EXTERNAL_UTILS_H_
+
diff --git a/src/Filesystem/FilesystemPathUtils.cpp b/src/Filesystem/FilesystemPathUtils.cpp
new file mode 100755 (executable)
index 0000000..bbcde73
--- /dev/null
@@ -0,0 +1,351 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+
+/**
+ * @file        FilesystemPathUtils.cpp
+ */
+
+#include "FilesystemPathUtils.h"
+
+#include <map>
+#include <string>
+#include <sys/stat.h>
+#include <cerrno>
+#include <cstring>
+#include <cstdlib>
+#include <unistd.h>
+
+#include <system_info.h>
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <WidgetDB/WidgetDBMgr.h>
+#include <Export.h>
+
+#include "Enums.h"
+#include "Manager.h"
+#include "FilesystemUtils.h"
+#include "JSErrors.h"
+
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+namespace
+{
+const std::string PATH_INVALID_COMPONENT_PARENT_DIR("..");
+const std::string PATH_INVALID_COMPONENT_CURRENT_DIR(".");
+
+typedef std::map<std::string, std::string> RootToPathMap;
+typedef RootToPathMap::const_iterator RootToPathMapIterator;
+typedef std::map<std::string, std::string> PathToRootMap;
+typedef PathToRootMap::const_iterator PathToRootMapIterator;
+
+int try_mkdir(const char* path, mode_t mode)
+{
+    struct stat st;
+    int err = 0;
+
+    if (::stat(path, &st) != 0)
+    {
+        if (::mkdir(path, mode) != 0)
+        {
+            err = -1;
+        }
+    }
+    else if (!S_ISDIR(st.st_mode))
+    {
+        errno = ENOTDIR;
+        err = -1;
+    }
+
+    return err;
+}
+
+int mkpath(const char* path, mode_t mode)
+{
+    char* copy = ::strdup(path);
+    if (NULL == copy)
+    {
+        return -1;
+    }
+
+    int err = 0;
+    char* ptr = copy;
+    char* slash = NULL;
+
+    while ((0 == err) && (NULL != (slash = ::strchr(ptr, '/'))))
+    {
+        if (slash != ptr)
+        {
+            *slash = '\0';
+            err = try_mkdir(copy, mode);
+            *slash = '/';
+        }
+        ptr = slash + 1;
+    }
+
+    if (0 == err)
+    {
+        err = try_mkdir(path, mode);
+    }
+
+    ::free(copy);
+    return err;
+}
+} //Anonymous namespace
+
+
+namespace DeviceAPI
+{
+namespace Filesystem
+{
+namespace Utils
+{
+
+const char* PLATFORM_FEATURE_CAMERA =  "tizen.org/feature/camera";
+
+void getRootToPathMap(RootToPathMap& result)
+{
+    auto locations = Manager::getInstance().getStorageList();
+    for (auto it = locations.begin(); it != locations.end(); ++it)
+    {
+        result[it->first] = it->second->getFullPath();
+    }
+}
+
+void getPathToRootMap(PathToRootMap& result)
+{
+    auto locations = Manager::getInstance().getStorageList();
+    for (auto it = locations.begin(); it != locations.end(); ++it)
+    {
+        result[it->second->getFullPath()] = it->first;
+    }
+}
+
+void initializeManager()
+{
+    Manager::getInstance();
+}
+
+PathPtr fromVirtualPath(JSContextRef context,
+                                   const std::string& arg)
+{
+    LOGD("arg:[%s]", arg.c_str());
+    // uri path, strip file://
+    if (isUriPath(arg))
+    {
+        std::string stripPath = arg.substr(strlen("file://"));
+        LOGD("uri absolute path %s", stripPath.c_str());
+        PathPtr result = Path::create(stripPath);
+
+        return result;
+    }
+    if (!isPathValid(arg))
+    {
+        LOGW("virtual path is invalid:[%s]", arg.c_str());
+        LOGW("throw TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException(
+            "Not found path component.");
+    }
+    std::string root;
+    std::string tail;
+    std::string::size_type separatorPosition = arg.find(Path::getSeparator());
+    if (separatorPosition != std::string::npos)
+    {
+        root = arg.substr(0, separatorPosition);
+        tail = arg.substr(separatorPosition + 1, arg.size() - 1);
+    }
+    else
+    {
+        root = arg;
+    }
+
+    if (!root.compare("camera")) {
+        bool bCamera = false;
+        int ret = system_info_get_platform_bool(PLATFORM_FEATURE_CAMERA, &bCamera);
+        if (ret != SYSTEM_INFO_ERROR_NONE) {
+            LOGE("system info unknown error");
+            throw DeviceAPI::Common::NotSupportedException("camera not supported");
+        } else if(bCamera == false) {
+            LOGE("camera not supported : %d", bCamera);
+            throw DeviceAPI::Common::NotSupportedException("camera not supported");
+        }
+        LOGD("enter : %d", bCamera);
+    }
+
+    int widgetId = WrtAccessSingleton::Instance().getWidgetId();
+    WidgetDB::Api::IWidgetDBPtr widgetDB = WidgetDB::Api::getWidgetDB(widgetId);
+    RootToPathMap rootToPath;
+    getRootToPathMap(rootToPath);
+    rootToPath["wgt-package"] = widgetDB->getWidgetInstallationPath();
+    rootToPath["wgt-private"] = widgetDB->getWidgetPersistentStoragePath();
+    rootToPath["wgt-private-tmp"] = widgetDB->getWidgetTemporaryStoragePath();
+
+    RootToPathMapIterator iter;
+    for (iter = rootToPath.begin() ; iter != rootToPath.end() ; ++iter) {
+        LOGD("enter %s, %s", iter->first.c_str(), iter->second.c_str());
+    }
+
+    RootToPathMapIterator it = rootToPath.find(root);
+    if (it == rootToPath.end())
+    {
+        LOGD("Allow non virtual root path %s", arg.c_str());
+        return Path::create(arg);
+    }
+    PathPtr result = Path::create(it->second);
+    if (!tail.empty())
+    {
+        result->append(tail);
+    }
+    return result;
+}
+
+std::string toVirtualPath(JSContextRef context,
+                                     const std::string& arg)
+{
+
+    int widgetId = WrtAccessSingleton::Instance().getWidgetId();
+    WidgetDB::Api::IWidgetDBPtr widgetDB =
+        WidgetDB::Api::getWidgetDB(widgetId);
+    PathToRootMap pathToRoot;
+    getPathToRootMap(pathToRoot);
+    pathToRoot[widgetDB->getWidgetInstallationPath()] = "wgt-package";
+    pathToRoot[widgetDB->getWidgetPersistentStoragePath()] = "wgt-private";
+    pathToRoot[widgetDB->getWidgetTemporaryStoragePath()] = "wgt-private-tmp";
+    std::string path = arg;
+    std::string::size_type pos = path.size();
+    while (std::string::npos != (pos = path.rfind(Path::getSeparator(), pos)))
+    {
+        PathToRootMapIterator it = pathToRoot.find(path);
+        if (pathToRoot.end() != it)
+        {
+            return it->second + arg.substr(path.size());
+        }
+        path.erase(pos, path.size());
+    }
+    LOGD("Allow non virtual root path");
+    return arg;
+}
+
+bool isVirtualPath(const std::string& path)
+{
+    std::string root;
+    std::string::size_type separatorPosition = path.find(Path::getSeparator());
+    if (separatorPosition != std::string::npos)
+    {
+        root = path.substr(0, separatorPosition);
+    }
+    else
+    {
+        root = path;
+    }
+    int widgetId = WrtAccessSingleton::Instance().getWidgetId();
+    WidgetDB::Api::IWidgetDBPtr widgetDB = WidgetDB::Api::getWidgetDB(widgetId);
+    RootToPathMap rootToPath;
+    getRootToPathMap(rootToPath);
+    rootToPath["wgt-package"] = widgetDB->getWidgetInstallationPath();
+    rootToPath["wgt-private"] = widgetDB->getWidgetPersistentStoragePath();
+    rootToPath["wgt-private-tmp"] = widgetDB->getWidgetTemporaryStoragePath();
+    RootToPathMapIterator it = rootToPath.find(root);
+    if (it == rootToPath.end())
+    {
+        return false;
+    }
+    else
+    {
+        return true;
+    }
+}
+
+bool isUriPath(const std::string& path)
+{
+    const char* uriPrefix = "file://";
+    const char* stringFromPath = path.c_str();
+    if (!strncmp(uriPrefix, stringFromPath, strlen(uriPrefix)) &&
+            path[strlen(uriPrefix)] == '/')
+    {
+        return true;
+    }
+
+    return false;
+}
+
+bool isPathValid(const std::string& path)
+{
+    static const std::string currentDirBegin(PATH_INVALID_COMPONENT_CURRENT_DIR +
+            Path::getSeparator());
+    static const std::string parentDirBegin(PATH_INVALID_COMPONENT_PARENT_DIR +
+                                            Path::getSeparator());
+    static const std::string currentDirMiddle(Path::getSeparator() +
+            PATH_INVALID_COMPONENT_CURRENT_DIR + Path::getSeparator());
+    static const std::string parentDirMiddle(Path::getSeparator() +
+            PATH_INVALID_COMPONENT_PARENT_DIR + Path::getSeparator());
+
+    if (path.find(parentDirBegin) == 0 ||
+            path.find(currentDirBegin) == 0 ||
+            path.find(parentDirMiddle) != std::string::npos ||
+            path.find(currentDirMiddle) != std::string::npos)
+    {
+        return false;
+    }
+    return true;
+}
+
+bool nodeExists(const std::string& path)
+{
+    struct stat info;
+    if (stat(path.c_str(), &info) == 0)
+    {
+        if (S_ISDIR(info.st_mode))
+        {
+            return true;
+        }
+    }
+    return false;
+}
+
+void makePath(const std::string& path,
+              mode_t mode)
+{
+    if (mkpath(path.c_str(), mode) == -1)
+    {
+        LOGW("Couldn't create path: %s", path.c_str());
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Couldn't create path");
+    }
+}
+
+PathList getParts(const PathPtr& path)
+{
+    PathList result;
+    Path::SeparatorType separator = path->getSeparator();
+    std::string fullPath = path->getFullPath();
+    std::string::size_type pos = 0;
+    while ((pos = fullPath.find(separator, pos + 1)) != std::string::npos)
+    {
+        result.push_back(Path::create(fullPath.substr(0, pos)));
+    }
+    return result;
+}
+
+} // namespace Utils
+} // namespace Filesystem
+} // namespace DeviceAPI
+
diff --git a/src/Filesystem/FilesystemPathUtils.h b/src/Filesystem/FilesystemPathUtils.h
new file mode 100644 (file)
index 0000000..8624bc1
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        FilesystemPathUtils.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_PATH_UTILS_H_
+#define TIZENAPIS_FILESYSTEM_PATH_UTILS_H_
+
+#include <string>
+#include <sys/types.h>
+#include <vector>
+#include <JavaScriptCore/JavaScript.h>
+
+#include "Path.h"
+
+namespace DeviceAPI
+{
+namespace Filesystem
+{
+namespace Utils
+{
+
+void initializeManager();
+
+PathPtr fromVirtualPath(JSContextRef context, const std::string& arg);
+
+std::string toVirtualPath(JSContextRef context, const std::string& arg);
+
+bool isPathValid(const std::string& path);
+
+bool isUriPath(const std::string& path);
+
+bool isVirtualPath(const std::string& path);
+
+bool nodeExists(const std::string& path);
+
+void makePath(const std::string& path, mode_t mode);
+
+typedef std::vector<PathPtr> PathList;
+typedef PathList::iterator PathListIterator;
+
+/**
+ * Gets sub-paths of supplied path.
+ * The supplied path is not included.
+ * @param path
+ * @return List of paths.
+ */
+PathList getParts(const PathPtr& path);
+
+}
+}
+}
+
+#endif  //ifndef TIZENAPIS_FILESYSTEM_UTILS_H_
+
diff --git a/src/Filesystem/FilesystemUtils.cpp b/src/Filesystem/FilesystemUtils.cpp
new file mode 100755 (executable)
index 0000000..44ee47c
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        FilesystemUtils.cpp
+ */
+
+#include "FilesystemUtils.h"
+
+#include <map>
+#include <string>
+#include <iconv.h>
+#include <PlatformException.h>
+#include <Export.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <WidgetDB/WidgetDBMgr.h>
+#include "Enums.h"
+#include "JSErrors.h"
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+namespace Utils{
+
+void DLL_EXPORT toUTF8String(const std::string& fromEncoding,
+                             const char* from,
+                             const size_t fromLength,
+                             std::string &outputString)
+{
+    const char *fromEncodingSet = fromEncoding.c_str();
+    char *outputBuf = NULL;
+    char *buf = NULL;
+    int ret = 0;
+    iconv_t cd;
+    size_t outputLength= 0;
+
+    try {
+        cd = iconv_open("UTF-8", fromEncodingSet);
+
+        if (cd == (iconv_t) -1)
+        {
+            LOGW("charset conversion exception iconv -1");
+            LOGW("throw UnknownException");
+            throw DeviceAPI::Common::UnknownException(
+                    "Couldn't allocate output buffer.");
+        }
+
+        if (fromLength == 0)
+        {
+            LOGW("from length 0");
+            LOGW("throw UnknownException");
+            //FIXME: Memory leak of cd
+            throw DeviceAPI::Common::UnknownException(
+                    "charset conversion exception");
+        }
+
+        outputBuf = new char[fromLength * 4 + 1];
+        outputLength = fromLength * 4;
+        memset(outputBuf, 0, outputLength + 1);
+        buf = outputBuf;
+
+        char** from_ = const_cast<char**>(&from);
+        size_t* fromLength_ = const_cast<size_t*>(&fromLength);
+
+        ret = iconv(cd, from_, fromLength_, &buf, &outputLength);
+
+        LOGD("%d %d", fromLength, outputLength);
+
+        if (ret < 0)
+        {
+            iconv_close(cd);
+            LOGW("charset conversion exception ret %d", ret);
+            LOGW("throw UnknownException");
+            //FIXME: Memory leak of ouputBuf and cd
+            throw DeviceAPI::Common::UnknownException(
+                    "charset conversion exception");
+        }
+
+        iconv_close(cd);
+        outputString = outputBuf;
+
+        if (outputBuf)
+            delete[] outputBuf;
+
+    }
+    catch(std::bad_alloc) {
+        LOGW("Couldn't allocate output buffer.");
+        LOGW("throw UnknownException");
+        throw DeviceAPI::Common::UnknownException(
+                "Couldn't allocate output buffer.");
+    }
+}
+}
+}
+}
diff --git a/src/Filesystem/FilesystemUtils.h b/src/Filesystem/FilesystemUtils.h
new file mode 100755 (executable)
index 0000000..bdbf2a2
--- /dev/null
@@ -0,0 +1,368 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        FilesystemUtils.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_UTILS_H_
+#define TIZENAPIS_FILESYSTEM_UTILS_H_
+
+#include <string>
+#include <memory>
+#include <vector>
+#include <Logger.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <CallbackUserData.h>
+#include <JSWebAPIErrorFactory.h>
+
+#include <glib.h>
+
+#include "PlatformException.h"
+#include "Commons/Exception.h"
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+namespace Utils{
+
+void toUTF8String(const std::string& fromEncoding,
+                  const char* from,
+                  const size_t fromLength,
+                  std::string &outputString);
+
+class ScopedExecution
+{
+public:
+    ScopedExecution(std::function<void()> aRoutine):
+        mRountine(aRoutine)
+    {}
+    ~ScopedExecution() {mRountine();}
+private:
+    std::function<void()> mRountine;
+};
+
+class FilesystemEvent : public Common::CallbackUserData
+{
+public:
+    FilesystemEvent(JSContextRef aGlobalCtx):
+        CallbackUserData(aGlobalCtx),
+        mCode(WrtDeviceApis::Commons::ExceptionCodes::None),
+        m_synchronous(false),
+        m_is_error(false)
+    {}
+    void setException(std::string aName, std::string aMessage = "")
+    {
+        mExceptionName = aName;
+        mExceptionMessage = aMessage;
+    }
+    WrtDeviceApis::Commons::ExceptionCodes::Enumeration getExceptionCode()
+    {
+        return mCode;
+    }
+    void setExceptionCode(WrtDeviceApis::Commons::ExceptionCodes::Enumeration
+                          aCode)
+    {
+        mCode = aCode;
+    }
+    std::string getExceptionName()
+    {
+        return mExceptionName;
+    }
+    std::string getExceptionMessage()
+    {
+        return mExceptionMessage;
+    }
+    void setJSError(JSValueRef aJSError)
+    {
+        m_JSError = aJSError;
+    }
+    void internalCallErrorCallback()
+    {
+        LOGE("enter");
+        callErrorCallback(
+                DeviceAPI::Common::JSWebAPIErrorFactory::makeErrorObject(
+                        getContext(),
+                        getExceptionName(),
+                        getExceptionMessage()));
+        LOGE("enter");
+    }
+    void setForSynchronousCall()
+    {
+        m_synchronous = true;
+    }
+    void setForAsynchronousCall()
+    {
+        m_synchronous = false;
+    }
+    bool isSynchronous()
+    {
+        return m_synchronous;
+    }
+
+    void setIsError(bool val){
+        m_is_error = val;
+    }
+
+    bool isError(){
+        return m_is_error;
+    }
+
+private:
+    std::string mExceptionName;
+    std::string mExceptionMessage;
+    WrtDeviceApis::Commons::ExceptionCodes::Enumeration mCode;
+    JSValueRef m_JSError;
+    bool m_synchronous;
+    bool m_is_error;
+};
+
+
+template <class EventObjectPtr>
+class MainLoop
+{
+public:
+    static JSValueRef passErrorLater(std::string errorName,
+                                     std::string errorMessage,
+                                     JSValueRef result,
+                                     EventObjectPtr event)
+    {
+        auto eventData = new EventObjectPtr(event);
+        event->setException(errorName, errorMessage);
+        if (!g_idle_add(errorWorker, static_cast<gpointer>(eventData))) {
+            LOGE("g_idle addition failed");
+        }
+        return result;
+    }
+private:
+    static gboolean errorWorker(gpointer aData)
+    {
+        try {
+            auto event = static_cast<EventObjectPtr*>(aData);
+            (*event)->internalCallErrorCallback();
+            delete event;
+        } catch (...) {
+            LOGE("Unknown exception caught");
+        }
+        return false;
+    }
+};
+
+enum NoFunction {
+    ENoFunction
+};
+
+template <class EventPtr>
+class MultiThreadHandler
+{
+public:
+    typedef std::function<void(EventPtr)> Routine;
+    static void execute(Routine aBeginFunction,
+                        Routine aThreadFunction,
+                        Routine aEndFunction,
+                        EventPtr aPassedEvent,
+                        bool aEmptyWorkerThread = false)
+    {
+        try {
+            aBeginFunction(aPassedEvent);
+            if (aPassedEvent->isSynchronous()) {
+                if (!aEmptyWorkerThread) {
+                    aThreadFunction(aPassedEvent);
+                }
+                aEndFunction(aPassedEvent);
+            }
+        } catch (const WrtDeviceApis::Commons::Exception& ex) {
+            LOGW("Exception caught:%s:%s",
+                 ex.GetClassName().c_str(),
+                 ex.GetMessage().c_str());
+            aPassedEvent->setException(ex.GetClassName(), ex.GetMessage());
+        } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+            LOGW("Exception caught %s:%s",
+                 ex.getName().c_str(),
+                 ex.getMessage().c_str());
+            aPassedEvent->setException(ex.getName(), ex.getMessage());
+        }
+        if (!aPassedEvent->isSynchronous()) {
+            auto handler = new MultiThreadHandler<EventPtr>(aThreadFunction,
+                                                            aEndFunction,
+                                                            aPassedEvent);
+            if (aPassedEvent->getExceptionName().empty() && !aEmptyWorkerThread) {
+                pthread_t thread;
+                //Handler ownership is passed to threadWorker
+                if(!pthread_create(
+                        &thread, NULL, MultiThreadHandler<EventPtr>::threadWorker, handler)) {
+                    if(pthread_detach(thread)) {
+                        LOGE("Pthread detach error");
+                    }
+                } else {
+                    LOGE("Pthread create error");
+                }
+            } else {
+                //aData ownership is passed to mainWorker
+                g_idle_add(mainWorker, handler);
+            }
+        }
+    }
+    static void noOperation(EventPtr /*aEvent*/){ }
+private:
+    Routine m_threadFunction;
+    Routine m_endFunction;
+    EventPtr m_event;
+    MultiThreadHandler(Routine aThreadFunction,
+                       Routine aEndFunction,
+                       EventPtr aPassedEvent):
+        m_threadFunction(aThreadFunction),
+        m_endFunction(aEndFunction),
+        m_event(aPassedEvent)
+    {}
+    static void* threadWorker(void* aEvent)
+    {
+        try {
+            if (!aEvent) {
+               LOGE("NULL pointer received as event data");
+               return NULL;
+            }
+            auto handler = static_cast<MultiThreadHandler<EventPtr>*>(aEvent);
+            auto event = handler->m_event;
+            if (event->getExceptionName().empty()) {
+                try {
+                    handler->m_threadFunction(event);
+                } catch (const WrtDeviceApis::Commons::Exception& ex) {
+                    LOGW("Exception caught: %s", ex.GetMessage().c_str());
+                    event->setException(ex.GetClassName(), ex.GetMessage());
+                } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+                    LOGW("Exception caught: %s", ex.getMessage().c_str());
+                    event->setException(ex.getName(), ex.getMessage());
+                } catch (...) {
+                    LOGW("Unknown exception caught and passed to JS layer");
+                    DeviceAPI::Common::IOException ex("Unknown exception caught");
+                    event->setException(ex.getName(), ex.getMessage());
+                }
+            }
+            //aData ownership is passed to mainWorker
+            g_idle_add(mainWorker, handler);
+        } catch (...) {
+            LOGW("Unknown exception caught and ignored in Filesystem worker thread");
+        }
+        return NULL;
+    }
+    static gboolean mainWorker(gpointer aData)
+    {
+        try
+        {
+            auto handler = static_cast<MultiThreadHandler<EventPtr>*>(aData);
+            auto event = handler->m_event;
+            if (!handler) {
+                LOGE("NULL pointer passed");
+                return false;
+            }
+            if (!event->getExceptionName().empty()) {
+                LOGW("IO error reported to JavaScript Error:[%s] Message:[%s]",
+                      event->getExceptionName().c_str(),
+                      event->getExceptionMessage().c_str());
+                event->internalCallErrorCallback();
+                LOGE("enter");
+            } else {
+                try {
+                    handler->m_endFunction(event);
+                } catch (const WrtDeviceApis::Commons::Exception& ex) {
+                    LOGW("Exception caught: %s", ex.GetMessage().c_str());
+                    event->setException(ex.GetClassName(), ex.GetMessage());
+                    event->internalCallErrorCallback();
+                } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+                    LOGW("Exception caught: %s", ex.getMessage().c_str());
+                    event->setException(ex.getName(), ex.getMessage());
+                    event->internalCallErrorCallback();
+                } catch (...) {
+                    LOGW("Unknown exception caught and passed to JS layer");
+                    DeviceAPI::Common::IOException ex("Unknown exception caught");
+                    event->setException(ex.getName(), ex.getMessage());
+                    event->internalCallErrorCallback();
+                }
+            }
+            delete handler;
+        } catch (...) {
+            LOGW("Unknown error ignored in Filesystem Main Thread");
+        }
+        return false;
+    }
+};
+
+template <class EventPtr>
+void executeThreadAndMainFunctions(
+        EventPtr aPassedEvent,
+        typename MultiThreadHandler<EventPtr>::Routine aBeginFunction,
+        typename MultiThreadHandler<EventPtr>::Routine aThreadFunction,
+        typename MultiThreadHandler<EventPtr>::Routine aEndFunction)
+{
+    MultiThreadHandler<EventPtr>::execute(aBeginFunction,
+                                          aThreadFunction,
+                                          aEndFunction,
+                                          aPassedEvent,
+                                          false);
+}
+
+template <class EventPtr>
+void executeThreadAndMainFunctions(
+        EventPtr aPassedEvent,
+        NoFunction /*aBeginFunction*/,
+        typename MultiThreadHandler<EventPtr>::Routine aThreadFunction,
+        typename MultiThreadHandler<EventPtr>::Routine aEndFunction)
+{
+    MultiThreadHandler<EventPtr>::execute(
+            MultiThreadHandler<EventPtr>::noOperation,
+            aThreadFunction,
+            aEndFunction,
+            aPassedEvent,
+            false);
+}
+
+template <class EventPtr>
+void executeThreadAndMainFunctions(
+        EventPtr aPassedEvent,
+        NoFunction /*aBeginFunction*/,
+        NoFunction /*aThreadFunction*/,
+        typename MultiThreadHandler<EventPtr>::Routine aEndFunction)
+{
+    MultiThreadHandler<EventPtr>::execute(
+            MultiThreadHandler<EventPtr>::noOperation,
+            MultiThreadHandler<EventPtr>::noOperation,
+            aEndFunction,
+            aPassedEvent,
+            true);
+}
+
+template <class EventPtr>
+void executeThreadAndMainFunctions(
+        EventPtr aPassedEvent,
+        typename MultiThreadHandler<EventPtr>::Routine aBeginFunction,
+        NoFunction /*aThreadFunction*/,
+        typename MultiThreadHandler<EventPtr>::Routine aEndFunction)
+{
+    MultiThreadHandler<EventPtr>::execute(
+            aBeginFunction,
+            MultiThreadHandler<EventPtr>::noOperation,
+            aEndFunction,
+            aPassedEvent,
+            true);
+}
+
+} //Utils namespace
+} //Filesystem namespace
+} //DeviceAPI namespace
+
+#endif  //ifndef TIZENAPIS_FILESYSTEM_UTILS_H_
diff --git a/src/Filesystem/JSErrors.cpp b/src/Filesystem/JSErrors.cpp
new file mode 100755 (executable)
index 0000000..9935c93
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSErrors.cpp
+ */
+
+#include "JSErrors.h"
+#include <JSWebAPIErrorFactory.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+
+std::string translateApi2APIErrors(const std::string& aApiError)
+{
+    std::string retError;
+    if ("ConversionException" == aApiError) {
+        retError = "TypeMismatchError";
+    } else if ("InvalidArgumentException" == aApiError) {
+        retError = "InvalidValuesError";
+    } else if ("NotFoundException" == aApiError) {
+        retError = "NotFoundError"; //It is correct.
+    } else if ("PlatformException" == aApiError) {
+        retError = "IOError";
+    } else {
+        retError = "UnknownError";
+    }
+    LOGD("Error [%s] translated to [%s]", aApiError.c_str(), retError.c_str());
+    return retError;
+}
+
+
+bool checkReportAsync(
+        const std::string& aName,
+        const std::string& aMessage,
+        WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr aCallback,
+        JSContextRef aContext)
+{
+    LOGD("Error mode check for [%s]", aName.c_str());
+    bool mode = "InvalidValuesError" == aName ||
+                "IOError" == aName ||
+                "UnknownError" == aName ||
+                "SecurityError" == aName ||
+                "InvalidAccessError" == aName ||
+                "QuotaExceededError" == aName ||
+                "NotFoundError" == aName;
+    if (mode) {
+        LOGD("Asyncrhonous error report for %s", aName.c_str());
+        aCallback->callOnError(
+                DeviceAPI::Common::JSWebAPIErrorFactory::makeErrorObject(
+                aContext,
+                aName,
+                aMessage));
+    }
+    return mode;
+}
+
+}
+}
+
diff --git a/src/Filesystem/JSErrors.h b/src/Filesystem/JSErrors.h
new file mode 100644 (file)
index 0000000..22a438b
--- /dev/null
@@ -0,0 +1,110 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSErrors.h
+ */
+
+#ifndef _TIZEN_FILESYSTEM_JSERRORS_H_
+#define _TIZEN_FILESYSTEM_JSERRORS_H_
+
+#include <string>
+#include <memory>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+
+#include "FilesystemUtils.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+bool checkReportAsync(
+        const std::string& aName,
+        const std::string& aMessage,
+        WrtDeviceApis::CommonsJavaScript::JSCallbackManagerPtr aCallback,
+        JSContextRef aContext);
+
+template <class UserData>
+inline bool checkReportAsyncAPI(
+        const std::string& aName,
+        const std::string& aMessage,
+        std::shared_ptr<UserData> aCallback,
+        JSContextRef aContext)
+{
+    LOGD("Error mode check for [%s]", aName.c_str());
+    bool mode = "InvalidValuesError" == aName ||
+                "IOError" == aName ||
+                "UnknownError" == aName ||
+                "NotFoundError" == aName;
+    if (mode)
+    {
+        LOGD("Asynchronous error report for Name:[%s] Message[%s]",
+             aName.c_str(), aMessage.c_str());
+        Utils::MainLoop<std::shared_ptr<UserData> >::passErrorLater(
+                aName,
+                aMessage,
+                JSValueMakeUndefined(aContext),
+                aCallback);
+    }
+    return mode;
+}
+
+std::string translateApi2APIErrors(const std::string& aApiError);
+
+template <class taEvent>
+inline void reportErrorCode(const taEvent& aEvent,
+                            const std::string& aErrorName,
+                            const std::string& aMessage)
+{
+    using namespace WrtDeviceApis::Commons;
+    ExceptionCodes::Enumeration exceptionCode;
+    if ("TypeMismatchError" == aErrorName) {
+        exceptionCode = ExceptionCodes::InvalidArgumentException;
+    } else if ("InvalidValuesError" == aErrorName) {
+        exceptionCode = ExceptionCodes::PlatformException;
+    } else if ("IOError" == aErrorName) {
+        exceptionCode = ExceptionCodes::InvalidArgumentException;
+    } else if ("UnknownError" == aErrorName) {
+        exceptionCode = ExceptionCodes::UnknownException;
+    } else if ("ServiceNotAvailableError" == aErrorName) {
+        exceptionCode = ExceptionCodes::PlatformException;
+    } else if ("SecurityError" == aErrorName) {
+        exceptionCode = ExceptionCodes::SecurityException;
+    } else if ("NotSupportedError" == aErrorName) {
+        exceptionCode = ExceptionCodes::UnsupportedException;
+    } else if ("NotFoundError" == aErrorName) {
+        exceptionCode = ExceptionCodes::NotFoundException;
+    } else if ("InvalidAccessError" == aErrorName) {
+        exceptionCode = ExceptionCodes::SecurityException;
+    } else if ("QuotaExceededError" == aErrorName) {
+        exceptionCode = ExceptionCodes::PlatformException;
+    } else {
+        exceptionCode = ExceptionCodes::UnknownException;
+    }
+    LOGD("Exception %s message %s translated to code %d ",
+         aErrorName.c_str(),
+         aMessage.c_str(),
+         exceptionCode);
+    aEvent->setExceptionCode(exceptionCode);
+}
+
+}
+}
+
+#endif //ifndef _TIZEN_FILESYSTEM_JSERRORS_H_
+
diff --git a/src/Filesystem/JSFile.cpp b/src/Filesystem/JSFile.cpp
new file mode 100755 (executable)
index 0000000..ce72638
--- /dev/null
@@ -0,0 +1,1405 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSFile.cpp
+ */
+
+#include "JSFile.h"
+
+#include <string>
+#include <ctime>
+#include <Logger.h>
+
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Export.h>
+#include <TimeTracer.h>
+
+#include "Enums.h"
+#include "Manager.h"
+#include "EventCopy.h"
+#include "EventMove.h"
+#include "EventListNodes.h"
+#include "EventOpen.h"
+#include "EventReadText.h"
+#include "Converter.h"
+#include "plugin_config.h"
+#include "Encodings.h"
+#include "JSFilestream.h"
+#include "JSErrors.h"
+#include "FilesystemUtils.h"
+#include "FilesystemPathUtils.h"
+#include <SecurityAccessor.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace {
+#define PLUGIN_NAME  "File"
+#define PROPERTY_PARENT  "parent"
+#define PROPERTY_READ_ONLY  "readOnly"
+#define PROPERTY_IS_FILE  "isFile"
+#define PROPERTY_IS_DIRECTORY "isDirectory"
+#define PROPERTY_CREATED  "created"
+#define PROPERTY_MODIFIED  "modified"
+#define PROPERTY_PATH  "path"
+#define PROPERTY_NAME  "name"
+#define PROPERTY_FULL_PATH  "fullPath"
+#define PROPERTY_FILE_SIZE  "fileSize"
+#define PROPERTY_LENGTH "length"
+
+const std::string TIME_TRACER_FILE_RESOLVE = "JSFile::resolve";
+}    //namespace
+
+JSValueRef getFunctionOrNull(JSContextRef ctx, JSValueRef arg)
+{
+    if (Validator(ctx).isCallback(arg)) {
+        return arg;
+    } else if (!JSValueIsNull(ctx, arg) && !JSValueIsUndefined(ctx, arg)) {
+        LOGW("throw DeviceAPI::Common::TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException(
+                "Not a function nor JS null.");
+    }
+    return NULL;
+}
+
+JSValueRef getFunction(JSContextRef ctx, JSValueRef arg)
+{
+    if (Validator(ctx).isCallback(arg)) {
+        return arg;
+    } else{
+        LOGW("throw DeviceAPI::Common::TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException(
+                "Not a function nor JS null.");
+    }
+}
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+using namespace DeviceAPI::Common;
+
+namespace {
+template <class EventPtr>
+bool verifyPath(EventPtr callback,
+                PathPtr aPath,
+                JSContextRef localContext,
+                NodeType aType)
+{
+
+    EventResolvePtr eventResolve(new EventResolve(localContext));
+    eventResolve->setPath(aPath);
+    eventResolve->setForSynchronousCall();
+
+    Manager::getInstance().getNode(eventResolve);
+    if (!eventResolve->getResult() || !eventResolve->getExceptionName().empty())
+    {
+        LOGW("Exception name %s", eventResolve->getExceptionName().c_str());
+        if ("NotFoundError" == eventResolve->getExceptionName())
+        {
+            LOGW("throw NotFoundException");
+            throw DeviceAPI::Common::NotFoundException(
+                    "Not found error");
+        }
+        LOGD("POST IO ERROR");
+        Utils::MainLoop<EventPtr>::passErrorLater(
+                JSWebAPIErrorFactory::IO_ERROR,
+                "IO error",
+                JSValueMakeUndefined(localContext),
+                callback);
+        return true;
+    }
+    if (eventResolve->getResult()->getType() != aType) {
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException(
+                "Invalid directory");
+    }
+    return false;
+}
+} //Anonymous namespace
+
+JSClassRef JSFile::m_classRef = 0;
+
+JSClassDefinition JSFile::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    PLUGIN_NAME,
+    0,
+    m_properties,
+    m_functions,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    getPropertyNames,
+    NULL,
+    NULL,
+    hasInstance,
+    NULL
+};
+
+JSStaticValue JSFile::m_properties[] = {
+    { PROPERTY_PARENT, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_READ_ONLY, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_IS_FILE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_IS_DIRECTORY, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_CREATED, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_MODIFIED, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_PATH, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_NAME, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_FULL_PATH, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_FILE_SIZE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_LENGTH, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSFile::m_functions[] = {
+    { "toURI", toUri, kJSPropertyAttributeNone },
+    { "listFiles", listFiles, kJSPropertyAttributeNone },
+    { "openStream", openStream, kJSPropertyAttributeNone },
+    { "readAsText", readAsText, kJSPropertyAttributeNone },
+    { "copyTo", copyTo, kJSPropertyAttributeNone },
+    { "moveTo", moveTo, kJSPropertyAttributeNone },
+    { "createDirectory", createDirectory, kJSPropertyAttributeNone },
+    { "createFile", createFile, kJSPropertyAttributeNone },
+    { "resolve", resolve, kJSPropertyAttributeNone },
+    { "deleteDirectory", deleteDirectory, kJSPropertyAttributeNone },
+    { "deleteFile", deleteFile, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+void JSFile::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+}
+
+void JSFile::finalize(JSObjectRef object)
+{
+    FileHolder* priv = static_cast<FileHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+const JSClassRef DLL_EXPORT JSFile::getClassRef()
+{
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+const JSClassDefinition* JSFile::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+FilePtr DLL_EXPORT JSFile::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not JSFile");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    FileHolder* priv = static_cast<FileHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSFile::setPrivateObject(JSObjectRef object, FilePtr data)
+{
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+
+    FileHolder* priv = static_cast<FileHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new FileHolder();
+        priv->ptr = data;
+
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set JSFile private datae");
+            throw UnknownException("Failed to set JSFile private data");
+        }
+    }
+}
+
+JSObjectRef DLL_EXPORT JSFile::makeJSObject(JSContextRef context, FilePtr ptr,
+        Common::SecurityAccessor* srcSecurityAccessor)
+{
+    if (!ptr) {
+        LOGE("NULL pointer to File given");
+        throw UnknownException("NULL pointer to File given");
+    }
+
+    FileHolder* priv = new FileHolder();
+    priv->ptr = ptr;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
+        delete priv;
+        LOGE("Failed to set private in JSFile");
+        throw UnknownException("Private data not set");
+    }
+
+    ptr->setContext(context);
+
+    if(srcSecurityAccessor) {
+        ptr->copyAceCheckAccessFunction(srcSecurityAccessor);
+    }
+    else {
+        LOGW("Source SecurityAccessor is not available!");
+    }
+
+    return obj;
+}
+
+JSValueRef JSFile::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Private object is not set.");
+            return JSValueMakeUndefined(context);
+        }
+
+        JSContextRef globalContext = priv->getContext();
+        Converter converter(globalContext);
+
+        auto node = priv->getNode();
+        if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_PARENT))
+        {
+            NodePtr parent(node->getParent());
+            File::PermissionList perms = priv->getParentPermissions();
+            if (parent && !perms.empty())
+            {
+                parent->setPermissions(perms.back());
+                perms.pop_back();
+
+                FilePtr parentPriv = FilePtr(new File(parent, perms));
+                return JSFile::makeJSObject(priv->getContext(),parentPriv, priv.get());
+            }
+            return JSValueMakeNull(context);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_READ_ONLY))
+        {
+            bool readOnly = ((node->getMode() & PM_USER_WRITE) == 0);
+            return converter.toJSValueRef(readOnly);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_IS_FILE))
+        {
+            bool isFile = (node->getType() == NT_FILE);
+            return converter.toJSValueRef(isFile);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName,
+                  PROPERTY_IS_DIRECTORY))
+        {
+            bool isDirectory = (node->getType() == NT_DIRECTORY);
+            return converter.toJSValueRef(isDirectory);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_CREATED))
+        {
+            std::time_t created = node->getCreated();
+            return converter.toJSValueRef(created);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_MODIFIED))
+        {
+            std::time_t modified = node->getModified();
+            return converter.toJSValueRef(modified);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_PATH))
+        {
+            std::string fpath = node->getPath()->getFullPath();
+            std::string vpath = Utils::toVirtualPath(globalContext, fpath);
+            std::string::size_type pos = vpath.rfind(Path::getSeparator());
+            std::string path;
+            if (std::string::npos != pos)
+            {
+                path = vpath.substr(0, pos + 1);
+            }
+            else
+            {
+                path = vpath;
+            }
+            return converter.toJSValueRef(path);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_NAME))
+        {
+            std::string fpath = node->getPath()->getFullPath();
+            std::string vpath = Utils::toVirtualPath(globalContext, fpath);
+            std::string name;
+            std::string::size_type pos = vpath.rfind(Path::getSeparator());
+
+            if (std::string::npos != pos) {
+                name = vpath.substr(pos + 1);
+            }
+            return converter.toJSValueRef(name);
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_FULL_PATH))
+        {
+            std::string path = priv->getOriginalFullPath();
+            LOGD("path = originalFullPath: %s", path.c_str());
+
+            if(path.empty()) {
+                path = node->getPath()->getFullPath();
+                LOGD("path =  %s (originalFullPath is not set)", path.c_str());
+            }
+
+            return converter.toJSValueRef(Utils::toVirtualPath(globalContext,
+                                                               path));
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_FILE_SIZE))
+        {
+            if (node->getType() == NT_DIRECTORY)
+            {
+                return JSValueMakeUndefined(context);
+            }
+            return converter.toJSValueRef(node->getSize());
+        }
+        else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_LENGTH))
+        {
+            if (node->getType() == NT_FILE) {
+                return JSValueMakeUndefined(context);
+            }
+            // TODO: think about more efficent solution!
+            NodeList children = node->getChildNodes();
+            return converter.toJSValueRef(children.size());
+        }
+    } catch (const WrtDeviceApis::Commons::Exception& ex) {
+        LOGW("Exception caught: %s", ex.GetMessage().c_str());
+    } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+        LOGW("Exception caught: %s", ex.getMessage().c_str());
+    } catch(...) {
+        LOGW("Unknown exception cought");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+void JSFile::getPropertyNames(JSContextRef context,
+        JSObjectRef object,
+        JSPropertyNameAccumulatorRef propertyNames)
+{
+}
+
+bool JSFile::hasInstance(JSContextRef context,
+        JSObjectRef constructor,
+        JSValueRef possibleInstance,
+        JSValueRef* exception)
+{
+    return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
+}
+
+JSValueRef JSFile::toUri(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(context, thisObject);
+
+        Converter converter(context);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), FILESYSTEM_FUNCTION_API_TO_URI);
+
+        std::string uri = priv->getOriginalURI();
+        LOGD("uri = originalURI: %s", uri.c_str());
+
+        if(uri.empty()) {
+            int widgetId = WrtAccessSingleton::Instance().getWidgetId();
+            uri = priv->getNode()->toUri(widgetId);
+            LOGD("uri = %s(originalURI is not set)", uri.c_str());
+        }
+
+        return converter.toJSValueRef(uri);
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGW("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGW("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFile::listFiles(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventListNodesPtr callback;
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_LIST_FILES);
+
+        ArgumentValidator validator(context, argc, argv);
+        validator.toFunction(0, false);
+        validator.toFunction(1, true);
+        validator.toObject(2, true);
+
+        JSContextRef globalContext = priv->getContext();
+        size_t index = 0;
+        JSValueRef reserveArguments[3];
+        JSCallbackManagerPtr cbm = JSCallbackManager::createObject(globalContext);
+
+        auto globalContextManager = GlobalContextManager::getInstance();
+        auto listContext = globalContextManager->getGlobalContext(context);
+        callback = EventListNodesPtr(new EventListNodes(listContext));
+
+        for (index = 0; index < 3; index++)
+        {
+            if (index < argc) {
+                reserveArguments[index] = argv[index];
+            } else {
+                reserveArguments[index] = JSValueMakeUndefined(context);
+            }
+        }
+
+        JSValueRef onSuccess = getFunction(globalContext, reserveArguments[0]);
+        JSValueRef onError = NULL;
+
+
+        if (argc > 1) {
+            onError = getFunctionOrNull(globalContext, reserveArguments[1]);
+        }
+
+        callback->setSuccessCallback(onSuccess);
+        callback->setErrorCallback(onError);
+
+        Converter converter(globalContext);
+
+        if (argc > 2) {
+            if (JSValueIsNull(context, reserveArguments[2]) == false &&
+                JSValueIsUndefined(context, reserveArguments[2]) == false) {
+                    callback->setFilter(converter.toNodeFilter(reserveArguments[2]));
+                }
+        }
+        auto myNode = priv->getNode();
+        File::PermissionList perms = priv->getParentPermissions();
+        perms.push_back(myNode->getPermissions());
+
+        callback->setParentPermissions(perms);
+        callback->setNode(myNode);
+
+        Node::getChildNodes(callback);
+
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                              err.getMessage(),
+                              callback,
+                              context)) {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(context,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                              err.GetMessage(),
+                              callback,
+                              context)) {
+            return JSWebAPIErrorFactory::postException(
+                    context,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFile::openStream(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventOpenPtr callback;
+    try {
+        FilePtr priv = JSFile::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_OPEN_STREAM);
+
+        auto globalCtx = GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = EventOpenPtr(new EventOpen(globalCtx));
+        ArgumentValidator validator(context, argumentCount, arguments);
+        AccessMode mode =
+                Converter(globalCtx).toAccessMode(validator.toJSValueRef(0, false));
+        callback->setSuccessCallback(validator.toFunction(1 ,false));
+        callback->setErrorCallback(validator.toFunction(2 ,true));
+        std::string encoding = validator.toString(3, true, Encodings::UTF8);
+
+        auto node = priv->getNode();
+        if ((AM_READ != mode) && (PERM_READ == node->getPermissions())) {
+            LOGE("Permission denied");
+            return Utils::MainLoop<EventOpenPtr>::passErrorLater(
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                    "permission denied error",
+                    JSValueMakeUndefined(context),
+                    callback);
+        }
+
+        if (!(encoding == Encodings::UTF8 || encoding == Encodings::ISO88591
+                || encoding == Encodings::SJIS)) {
+            LOGE("Type mismath");
+            throw DeviceAPI::Common::TypeMismatchException("Type mismatch");
+        }
+        callback->setCharSet(encoding);
+        callback->setNode(priv->getNode());
+        callback->setMode(mode);
+        Node::open(callback);
+
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 context)) {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(context,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                              err.GetMessage(),
+                              callback,
+                              context)) {
+            return JSWebAPIErrorFactory::postException(
+                    context,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFile::readAsText(
+        JSContextRef localContext,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventReadTextPtr callback;
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(localContext, thisObject);
+        TIZEN_CHECK_ACCESS(localContext, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_READ_AS_TEXT);
+
+        callback = EventReadTextPtr(new EventReadText(
+                GlobalContextManager::getInstance()->getGlobalContext(localContext)));
+
+        ArgumentValidator validator(localContext, argc, argv);
+        callback->setSuccessCallback(validator.toFunction(0,false));
+        callback->setErrorCallback(validator.toFunction(1,true));
+
+        std::string encoding = validator.toString(2,true,Encodings::UTF8);
+
+        if (!(encoding == Encodings::UTF8 || encoding == Encodings::ISO88591
+                || encoding == Encodings::SJIS)) {
+            LOGE("Type mismath");
+            throw DeviceAPI::Common::TypeMismatchException("Type mismatch");
+        }
+
+        if (NT_FILE != priv->getNode()->getType()) {
+            LOGE("JSFile is not file.");
+            return Utils::MainLoop<EventReadTextPtr>::passErrorLater(
+                    JSWebAPIErrorFactory::IO_ERROR,
+                    "IO error",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+
+        callback->setCharSet(encoding);
+        callback->setNode(priv->getNode());
+
+        Node::readAsText(callback);
+
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 localContext)) {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(localContext,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                              err.GetMessage(),
+                              callback,
+                              localContext)) {
+            return JSWebAPIErrorFactory::postException(
+                    localContext,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(localContext, exception, err);
+    }
+
+    return JSValueMakeUndefined(localContext);
+}
+
+JSValueRef JSFile::copyTo(JSContextRef localContext,
+        JSObjectRef /*object*/,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    JSContextRef globalContext = NULL;
+    EventCopyPtr callback;
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(localContext, thisObject);
+
+        TIZEN_CHECK_ACCESS(localContext, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_COPY_TO);
+
+        JSContextRef privateContext = priv->getContext();
+        size_t index = 0;
+        JSValueRef reserveArguments[5];
+        auto globalContextManager = GlobalContextManager::getInstance();
+        globalContext = globalContextManager->getGlobalContext(localContext);
+        callback = EventCopyPtr(new EventCopy(globalContext));
+
+        ArgumentValidator validator(localContext, argc, argv);
+        validator.toFunction(3, true);
+        validator.toFunction(4, true);
+
+        for (index = 0; index < 5; index++)
+        {
+            if (index < argc) {
+                reserveArguments[index] = argv[index];
+            } else {
+                 reserveArguments[index] = JSValueMakeUndefined(localContext);
+            }
+        }
+
+        Converter converter(privateContext);
+        JSValueRef onSuccess = NULL;
+        JSValueRef onError = NULL;
+
+        onSuccess = getFunctionOrNull(privateContext, reserveArguments[3]);
+        onError = getFunctionOrNull(privateContext, reserveArguments[4]);
+
+        callback->setSuccessCallback(onSuccess);
+        callback->setErrorCallback(onError);
+
+        //TODO add check validation for src, dest string.
+        PathPtr src = Utils::fromVirtualPath(
+                privateContext,
+                converter.toString(reserveArguments[0]));
+        PathPtr dest = Utils::fromVirtualPath(
+                privateContext,
+                converter.toString(reserveArguments[1]));
+        bool overwrite = converter.toBool(reserveArguments[2]);;
+
+        auto dirNode = priv->getNode();
+        LOGD("copyTo executed from dir:[%s] src path:[%s] dest path:[%s]",
+                dirNode->getPath()->getFullPath().c_str(),
+                src->getFullPath().c_str(),
+                dest->getFullPath().c_str());
+        if (NT_DIRECTORY != dirNode->getType()) {
+            LOGW("This node is not directory");
+            return Utils::MainLoop<EventCopyPtr>::passErrorLater(
+                    JSWebAPIErrorFactory::IO_ERROR,
+                    "IO error",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+
+        // Filesystem spec:
+        // The file or directory to be copied MUST be under the Directory
+        // from which the method is invoked, otherwise the operation
+        // MUST NOT be performed.
+        //
+        // ringtones: the location for ringtones (read-only location)
+        // wgt-package: the widget package location (read-only location)
+        //
+
+        const bool isSubPath = dirNode->isSubPath(src);
+        const bool destIsAllowed = isDestinationAllowed(dest);
+        if (!isSubPath || !destIsAllowed)
+        {
+            LOGE("isSubPath:%d destIsAllowed:%d", isSubPath, destIsAllowed);
+            return Utils::MainLoop<EventCopyPtr>::passErrorLater(
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                    "Invalid Values",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+
+        callback->setSource(src);
+        callback->setDestination(dest);
+
+        if (overwrite) {
+            callback->setOptions(OPT_OVERWRITE);
+        }
+
+        Manager::getInstance().copy(callback);
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 globalContext))
+        {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(localContext,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                                 err.GetMessage(),
+                                 callback,
+                                 globalContext))
+        {
+            return JSWebAPIErrorFactory::postException(
+                    localContext,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err("Unknown Error");
+        return JSWebAPIErrorFactory::postException(localContext, exception, err);
+    }
+
+    return JSValueMakeUndefined(localContext);
+}
+
+bool JSFile::isDestinationAllowed(PathPtr aDestination)
+{
+    static auto ringtones =
+        Utils::fromVirtualPath(NULL, "ringtones")->getFullPath();
+    static auto wgtPackage =
+        Utils::fromVirtualPath(NULL, "wgt-package")->getFullPath();
+    LOGD("Check allowed destinations ringtones [%s] wgt-package [%s] "
+         "destination [%s]",
+         ringtones.c_str(),
+         wgtPackage.c_str(),
+         aDestination->getFullPath().c_str());
+    return !Node::isSubPath(ringtones, aDestination) &&
+           !Node::isSubPath(wgtPackage, aDestination);
+
+}
+
+JSValueRef JSFile::moveTo(JSContextRef localContext,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventMovePtr callback;
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(localContext, thisObject);
+
+        TIZEN_CHECK_ACCESS(localContext, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_MOVE_TO);
+
+        ArgumentValidator validator(localContext, argc, argv);
+        auto globalManager = GlobalContextManager::getInstance();
+        JSContextRef globalContext = globalManager->getGlobalContext(localContext);
+        callback = EventMovePtr(new EventMove(globalContext));
+
+        std::string srcPath = validator.toString(0);
+        std::string destPath = validator.toString(1);
+        bool overwrite = validator.toBool(2);
+
+        JSValueRef onSuccess = validator.toFunction(3, true);
+        JSValueRef onError = validator.toFunction(4, true);
+
+        callback->setSuccessCallback(onSuccess);
+        callback->setErrorCallback(onError);
+        auto node = priv->getNode();
+
+        if (NT_DIRECTORY != node->getType()) {
+            return Utils::MainLoop<EventMovePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::IO_ERROR,
+                    "io error",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+        auto dirNode = priv->getNode();
+
+        PathPtr src = Utils::fromVirtualPath(
+                globalContext,
+                srcPath);
+        PathPtr dest = Utils::fromVirtualPath(
+                globalContext,
+                destPath);
+
+        // Filesystem spec:
+        // The file or directory to be moved MUST be under the Directory
+        // from which the method is invoked, otherwise the operation
+        // MUST NOT be performed.
+        //
+        // ringtones: the location for ringtones (read-only location)
+        // wgt-package: the widget package location (read-only location)
+        //
+        if (!dirNode->isSubPath(src) || !isDestinationAllowed(dest))
+        {
+            return Utils::MainLoop<EventMovePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                    "Invalid Values",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+        if ((node->getPermissions() & PERM_WRITE) == 0)
+        {
+            return Utils::MainLoop<EventMovePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                    "permission denied error",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+
+        callback->setSource(src);
+        callback->setDestination(dest);
+
+        if (overwrite)
+        {
+            callback->setOptions(OPT_OVERWRITE);
+        }
+
+        Manager::getInstance().move(callback);
+
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 localContext))
+        {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(localContext,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                                                        err.GetMessage(),
+                                                        callback,
+                                                        localContext))
+        {
+            return JSWebAPIErrorFactory::postException(
+                    localContext,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(localContext, exception, err);
+    }
+
+    return JSValueMakeUndefined(localContext);
+}
+
+JSValueRef JSFile::createDirectory(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                    FILESYSTEM_FUNCTION_API_CREATE_DIR);
+
+        Converter converter(context);
+
+        if (argc < 1) {
+            LOGW("throw InvalidValuesException");
+            throw DeviceAPI::Common::InvalidValuesException(
+                    "Invalid path name");
+        }
+        auto dirNode = priv->getNode();
+        if ((dirNode->getPermissions() & PERM_WRITE) == 0)
+        {
+            LOGW("throw SecurityException");
+            throw DeviceAPI::Common::InvalidValuesException(
+                    "Permission denied error");
+        }
+
+        PathPtr path = converter.toPath(argv[0]);
+        NodePtr node(dirNode->createChild(path, NT_DIRECTORY, OPT_RECURSIVE));
+        node->setPermissions(dirNode->getPermissions());
+
+        FilePtr newDirPriv = FilePtr(new File(node, priv->getParentPermissions()));
+        newDirPriv->pushParentPermissions(dirNode->getPermissions());
+        return JSFile::makeJSObject(priv->getContext(), newDirPriv, priv.get());
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFile::createFile(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_CREATE_FILE);
+
+        Converter converter(context);
+
+        if (argc < 1) {
+            LOGW("throw InvalidValuesException");
+            throw DeviceAPI::Common::InvalidValuesException(
+                    "Invalid path name");
+        }
+        auto dirNode = priv->getNode();
+        if ((dirNode->getPermissions() & PERM_WRITE) == 0)
+        {
+            LOGW("throw SecurityException");
+            throw DeviceAPI::Common::InvalidValuesException("Permission denied error");
+        }
+
+        PathPtr path = converter.toPath(argv[0]);
+        NodePtr node = dirNode->createChild(path, NT_FILE);
+
+        FilePtr newFilePriv = FilePtr(new File(node, priv->getParentPermissions()));
+        newFilePriv->pushParentPermissions(dirNode->getPermissions());
+        return JSFile::makeJSObject(priv->getContext(), newFilePriv, priv.get());
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught - %s: %s",
+            err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFile::resolve(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_RESOLVE);
+
+        if (priv->getNode()->getType() != NT_DIRECTORY) {
+            LOGE("JSFile object is not directory.");
+            return JSWebAPIErrorFactory::postException(
+                    context,
+                    exception,
+                    JSWebAPIErrorFactory::IO_ERROR,
+                    "IO error");
+        }
+
+        Converter converter(context);
+
+        if (argc < 1) {
+            LOGW("throw InvalidValuesException");
+            throw DeviceAPI::Common::InvalidValuesException(
+                    "Invalid path name");
+        }
+        auto dirNode = priv->getNode();
+        PathPtr path = converter.toPath(argv[0]);
+        NodePtr node = dirNode->getChild(path);
+        node->setPermissions(dirNode->getPermissions());
+
+        FilePtr resolvedPriv = FilePtr(new File(node, priv->getParentPermissions()));
+        resolvedPriv->pushParentPermissions(dirNode->getPermissions());
+        return JSFile::makeJSObject(priv->getContext(), resolvedPriv, priv.get());
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFile::deleteDirectory(JSContextRef localContext,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventRemovePtr callback;
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(localContext, thisObject);
+
+        TIZEN_CHECK_ACCESS(localContext, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_DELETE_DIR);
+
+        auto fileNode = priv->getNode();
+
+        if (argc < 2) {
+            return JSWebAPIErrorFactory::postException(
+                    localContext,
+                    exception,
+                    JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR,
+                    "Type missmatch error");
+        }
+
+        ArgumentValidator validator(localContext, argc, argv);
+        validator.toFunction(2, true);
+
+        size_t index = 0;
+        JSValueRef reserveArguments[4];
+
+        auto global = GlobalContextManager::getInstance();
+        JSContextRef globalContext = global->getGlobalContext(localContext);
+        callback = EventRemovePtr(new EventRemove(globalContext));
+
+        for (index = 0; index < 4; index++) {
+        if (index < argc)
+            reserveArguments[index] = argv[index];
+        else
+            reserveArguments[index] = JSValueMakeUndefined(localContext);
+        }
+
+
+        JSValueRef onSuccess = NULL;
+        JSValueRef onError = NULL;
+
+        onSuccess = getFunctionOrNull(globalContext, reserveArguments[2]);
+        onError = getFunctionOrNull(globalContext, reserveArguments[3]);
+
+        callback->setSuccessCallback(onSuccess);
+        callback->setErrorCallback(onError);
+
+
+        if ((fileNode->getPermissions() & PERM_WRITE) == 0)
+        {
+            return Utils::MainLoop<EventRemovePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                    "permission denied error",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+
+        if (fileNode->getType() != NT_DIRECTORY) {
+            return Utils::MainLoop<EventRemovePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::IO_ERROR,
+                    "IO error",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+
+        Converter converter(localContext);
+        PathPtr path = Utils::fromVirtualPath(
+                globalContext,
+                converter.toString(reserveArguments[0]));
+        bool recursive = converter.toBool(reserveArguments[1]);
+
+        if (fileNode->getPath()->getFullPath() != path->getPath()) {
+            return Utils::MainLoop<EventRemovePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::NOT_FOUND_ERROR,
+                    "not found error in current directory",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+
+        if (verifyPath(callback, path, localContext, NT_DIRECTORY))
+        {
+            return JSValueMakeUndefined(localContext);
+        }
+        if (recursive) {
+            callback->setOptions(OPT_RECURSIVE);
+        }
+
+        callback->setPath(path);
+
+        Manager::getInstance().remove(callback);
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 localContext)) {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(localContext,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                              err.GetMessage(),
+                              callback,
+                              localContext)) {
+            return JSWebAPIErrorFactory::postException(
+                    localContext,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(localContext, exception, err);
+    }
+
+    return JSValueMakeUndefined(localContext);
+}
+
+JSValueRef JSFile::deleteFile(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventRemovePtr callback;
+
+    try {
+        FilePtr priv = JSFile::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_DELETE_FILE);
+
+        ArgumentValidator validator(context, argc, argv);
+        validator.toFunction(1, true);
+        validator.toFunction(2, true);
+
+        size_t index = 0;
+        JSValueRef reserveArguments[3];
+        auto contextManager = GlobalContextManager::getInstance();
+        JSContextRef globalContext = contextManager->getGlobalContext(context);
+        callback = EventRemovePtr(new EventRemove(globalContext));
+
+        for (index = 0; index < 3; index++) {
+            if (index < argc) {
+                reserveArguments[index] = argv[index];
+            } else {
+                reserveArguments[index] = JSValueMakeUndefined(context);
+            }
+        }
+
+        JSValueRef onSuccess = NULL;
+        JSValueRef onError = NULL;
+
+        onSuccess = getFunctionOrNull(globalContext, reserveArguments[1]);
+        onError = getFunctionOrNull(globalContext, reserveArguments[2]);
+
+        callback->setSuccessCallback(onSuccess);
+        callback->setErrorCallback(onError);
+
+        auto node = priv->getNode();
+        if ((node->getPermissions() & PERM_WRITE) == 0)
+        {
+            return Utils::MainLoop<EventRemovePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                    "permission denied error",
+                    JSValueMakeUndefined(context),
+                    callback);
+        }
+
+        if (node->getType() != NT_DIRECTORY) {
+            return Utils::MainLoop<EventRemovePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::IO_ERROR,
+                    "IO error",
+                    JSValueMakeUndefined(context),
+                    callback);
+        }
+
+
+        Converter converter(context);
+        PathPtr path = Utils::fromVirtualPath(
+                globalContext,
+                converter.toString(reserveArguments[0]));
+
+        if (*node->getPath() != path->getPath()) {
+            return Utils::MainLoop<EventRemovePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::NOT_FOUND_ERROR,
+                    "not found error in current directory",
+                    JSValueMakeUndefined(context),
+                    callback);
+        }
+        if (verifyPath(callback, path, context, NT_FILE))
+        {
+            return JSValueMakeUndefined(context);
+        }
+
+        LOGD("try to call async event");
+        callback->setPath(path);
+        Manager::getInstance().remove(callback);
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 context)) {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(context,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                                 err.GetMessage(),
+                                 callback,
+                                 context)) {
+            return JSWebAPIErrorFactory::postException(
+                    context,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} //namespace DeviceAPI
+} //namespace Filesystem
diff --git a/src/Filesystem/JSFile.h b/src/Filesystem/JSFile.h
new file mode 100644 (file)
index 0000000..576b6eb
--- /dev/null
@@ -0,0 +1,222 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSFile.h
+ */
+
+#ifndef TIZENAPIS_TIZEN_JSFILE_H_
+#define TIZENAPIS_TIZEN_JSFILE_H_
+
+#include <memory>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <Commons/IEvent.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include "Node.h"
+#include "File.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class JSFile
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static FilePtr getPrivateObject(JSContextRef context, JSValueRef value);
+    static void setPrivateObject(JSObjectRef object, FilePtr data);
+    static JSObjectRef makeJSObject(JSContextRef context, FilePtr ptr,
+            Common::SecurityAccessor* srcSecurityAccessor);
+
+private:
+    /**
+    * The callback invoked when an object is first created.
+    */
+    static void initialize(JSContextRef context,
+        JSObjectRef object);
+
+    /**
+    * The callback invoked when an object is finalized.
+    */
+    static void finalize(JSObjectRef object);
+
+    /**
+    * The callback invoked when getting a property's value.
+    */
+    static JSValueRef getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception);
+
+    /**
+    * The callback invoked when collecting the names of an object's properties.
+    */
+    static void getPropertyNames(JSContextRef context,
+        JSObjectRef object,
+        JSPropertyNameAccumulatorRef propertyNames);
+
+    /**
+    * The callback invoked when an object is used as the target of an 'instanceof' expression.
+    */
+    static bool hasInstance(JSContextRef context,
+        JSObjectRef constructor,
+        JSValueRef possibleInstance,
+        JSValueRef* exception);
+
+    /**
+    * Returns a URI for the file.
+    */
+    static JSValueRef toUri(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Returns list of all files of this directory.
+    */
+    static JSValueRef listFiles(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * WRT_GeneralError exception
+    */
+    static JSValueRef openStream(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * WRT_GeneralError exception
+    */
+    static JSValueRef readAsText(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * The operation is only for file except for directory.
+    * Make sure the dest directory already exists.
+    */
+    static JSValueRef copyTo(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * This operation is only for file not directory
+    * The dest directory should exists in local file system, or the operation fails.
+    */
+    static JSValueRef moveTo(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * create directory even through the parent directories do not  exist in local file system.
+    */
+    static JSValueRef createDirectory(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Creates a new empty file in a specified location.
+    */
+    static JSValueRef createFile(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Resolves an existing file or directory relative to
+    * the current directory this operation is performed on; and
+    * returns a file handle for it.
+    */
+    static JSValueRef resolve(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+     * Removes all files from specified directory if recursive is true,
+     * or just remove the directory itself when there is no files or directories underneath it
+     */
+    static JSValueRef deleteDirectory(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Deletes a specified file.
+    */
+    static JSValueRef deleteFile(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    static bool isDestinationAllowed(PathPtr aDestination);
+
+    /**
+    * This structure describes a statically declared function property.
+    */
+    static JSStaticFunction m_functions[];
+
+    /**
+    * This structure describes a statically declared value property.
+    */
+    static JSStaticValue m_properties[];
+
+    /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_classRef;
+};
+
+} //namespace DeviceAPI
+} //namespace Filesystem
+
+#endif //TIZENAPIS_TIZEN_JSFILE_H_
diff --git a/src/Filesystem/JSFilestream.cpp b/src/Filesystem/JSFilestream.cpp
new file mode 100755 (executable)
index 0000000..5cb9d66
--- /dev/null
@@ -0,0 +1,566 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSFilestream.cpp
+ */
+
+#include "JSFilestream.h"
+
+#include <Commons/Base64.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <TimeTracer.h>
+#include <Logger.h>
+#include <ArgumentValidator.h>
+#include <Export.h>
+
+#include "Converter.h"
+#include "Encodings.h"
+#include "plugin_config.h"
+#include "FilesystemUtils.h"
+#include "JSErrors.h"
+#include <Commons/Exception.h>
+
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace {
+const char* PLUGIN_NAME = "FileStream";
+const char* PROPERTY_EOF = "eof";
+const char* PROPERTY_POSITION = "position";
+const char* PROPERTY_BYTES_AVAILABLE = "bytesAvailable";
+}
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+using namespace DeviceAPI::Common;
+
+JSClassRef JSFilestream::m_classRef = 0;
+
+JSClassDefinition JSFilestream::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    PLUGIN_NAME,
+    0,
+    m_properties,
+    m_functions,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    getPropertyNames,
+    NULL,
+    NULL,
+    hasInstance,
+    NULL
+};
+
+JSStaticValue JSFilestream::m_properties[] = {
+    { PROPERTY_EOF, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PROPERTY_POSITION, getProperty, setProperty, kJSPropertyAttributeNone },
+    { PROPERTY_BYTES_AVAILABLE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSFilestream::m_functions[] = {
+    { "close", close, kJSPropertyAttributeNone },
+    { "read", read, kJSPropertyAttributeNone },
+    { "readBytes", readBytes, kJSPropertyAttributeNone },
+    { "readBase64", readBase64, kJSPropertyAttributeNone },
+    { "write", write, kJSPropertyAttributeNone },
+    { "writeBytes", writeBytes, kJSPropertyAttributeNone },
+    { "writeBase64", writeBase64, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+void JSFilestream::initialize(JSContextRef context,
+    JSObjectRef object)
+{
+}
+
+void JSFilestream::finalize(JSObjectRef object)
+{
+    StreamHolder* priv = static_cast<StreamHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+const JSClassRef DLL_EXPORT JSFilestream::getClassRef()
+{
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+const JSClassDefinition* JSFilestream::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+StreamPtr JSFilestream::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not JSFilestream");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    StreamHolder* priv = static_cast<StreamHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSFilestream::setPrivateObject(JSObjectRef object, StreamPtr data)
+{
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+
+    StreamHolder* priv = static_cast<StreamHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new StreamHolder();
+        priv->ptr = data;
+
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set JSFilestream private datae");
+            throw UnknownException("Failed to set JSFilestream private data");
+        }
+    }
+}
+
+JSObjectRef JSFilestream::makeJSObject(JSContextRef context, StreamPtr ptr,
+        Common::SecurityAccessor* srcSecurityAccessor)
+{
+    if (!ptr) {
+        LOGE("NULL pointer to File given");
+        throw UnknownException("NULL pointer to File given");
+    }
+
+    StreamHolder* priv = new StreamHolder();
+    priv->ptr = ptr;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
+        delete priv;
+        LOGE("Failed to set private in JSFilestream");
+        throw UnknownException("Private data not set");
+    }
+
+    if(srcSecurityAccessor) {
+        ptr->copyAceCheckAccessFunction(srcSecurityAccessor);
+    }
+    else {
+        LOGW("Source SecurityAccessor is not available!");
+    }
+
+    return obj;
+}
+
+JSValueRef JSFilestream::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        StreamPtr priv = JSFilestream::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Private object is not set.");
+            return JSValueMakeUndefined(context);
+        }
+
+        Converter converter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_EOF)) {
+            return converter.toJSValueRef(priv->isEof());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_POSITION)) {
+            long pos = priv->getPosition();
+            if (pos < 0) {
+                return JSValueMakeUndefined(context);
+            }
+            return converter.toJSValueRef(static_cast<unsigned long>(pos));
+        } else if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_BYTES_AVAILABLE)) {
+            long position = priv->getPosition();
+            long bytes = priv->getSize() - position;
+
+            return converter.toJSValueRefLong(static_cast<long>(bytes));
+        }
+    } catch (const WrtDeviceApis::Commons::ConversionException& ex) {
+        LOGW("trying to get incorrect value");
+    } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+        LOGW("trying to get incorrect value");
+    } catch(...) {
+        LOGW("Unknown exception cought");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+bool JSFilestream::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    try {
+        StreamPtr priv = JSFilestream::getPrivateObject(context, object);
+        if (!priv) {
+            LOGE("Private object is not set.");
+            return false;
+        }
+
+        Converter converter(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, PROPERTY_POSITION)) {
+            priv->setPosition(converter.toLong(value));
+            return true;
+        }
+    } catch (const WrtDeviceApis::Commons::Exception& ex) {
+        LOGW("trying to set incorrect value");
+    } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+        LOGW("trying to get incorrect value");
+    }
+
+    return false;
+}
+
+void JSFilestream::getPropertyNames(JSContextRef context,
+        JSObjectRef object,
+        JSPropertyNameAccumulatorRef propertyNames)
+{
+}
+
+bool JSFilestream::hasInstance(JSContextRef context,
+        JSObjectRef constructor,
+        JSValueRef instance,
+        JSValueRef* exception)
+{
+    return JSValueIsObjectOfClass(context, instance, JSFilestream::getClassRef());
+}
+
+JSValueRef JSFilestream::close(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        StreamPtr priv = JSFilestream::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_CLOSE);
+
+        priv->close();
+    } catch (WrtDeviceApis::Commons::PlatformException) {
+        LOGW("PlatformException caught translated to UNKNOWN_ERROR sync");
+        return JSWebAPIErrorFactory::postException(
+                context,
+                exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Unknown error");
+    } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+        LOGW("trying to get incorrect value");
+        return JSWebAPIErrorFactory::postException(
+                context,
+                exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Unknown error"
+        );
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFilestream::read(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+    char* text = NULL;
+    try {
+        StreamPtr priv = JSFilestream::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_READ);
+
+        ArgumentValidator validator(context, argc, argv);
+        long count = validator.toLong(0, false, 0);
+        if (count <= 0) {
+            LOGE("throw InvalidValuesException");
+            throw DeviceAPI::Common::InvalidValuesException("Invalid argument");
+        }
+
+        std::string currentCharSet = priv->getCharSet();
+
+        const char* currentCharSet_c_str = currentCharSet.c_str();
+        // utf8, iso8859-1, skip
+        if (!strcmp(currentCharSet_c_str, Encodings::UTF8)
+            || !strcmp(currentCharSet_c_str, Encodings::ISO88591)
+            || !strcmp(currentCharSet_c_str, Encodings::SJIS))
+        {
+            text = priv->getChars(count);
+            std::string str = std::string(text);
+            delete[] text;
+            return JSUtil::toJSValueRef(context,str);
+        }
+        else {
+            std::string outStr = "";
+            text = priv->getChars(count);
+            Utils::toUTF8String(currentCharSet, text, count, outStr);
+            delete[] text;
+            return JSUtil::toJSValueRef(context, outStr);
+        }
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        delete[] text;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        delete[] text;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFilestream::readBytes(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+    unsigned char* data = NULL;
+    try {
+        StreamPtr priv = JSFilestream::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_READ_BYTES);
+
+        long count = ArgumentValidator(context, argc, argv).toLong(0, false);
+        if (count <= 0) {
+            LOGE("throw InvalidValuesException");
+            throw DeviceAPI::Common::InvalidValuesException("Invalid argument");
+        }
+        data = priv->getBytes(count);
+        size_t objectCount = priv->getCount();
+        auto to_ret = Converter(context).toJSValueRef(data, objectCount);
+        delete [] data;
+        return to_ret;
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        delete [] data;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        delete [] data;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFilestream::readBase64(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+    unsigned char* data = NULL;
+
+    try {
+        StreamPtr priv = JSFilestream::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_READ_BASE64);
+        long count = ArgumentValidator(context, argc, argv).toLong(0, false);
+        if (count <= 0) {
+            LOGE("throw InvalidValuesException");
+            throw DeviceAPI::Common::InvalidValuesException("Invalid argument");
+        }
+        data = priv->getBytes(count);
+        size_t objectCount = priv->getCount();
+        std::string base64 =
+            WrtDeviceApis::Commons::Base64::encode(data, objectCount);
+        delete[] data;
+        data = NULL;
+        return JSUtil::toJSValueRef(context, base64);
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        delete[] data;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        delete[] data;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSFilestream::write(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argc,
+    const JSValueRef argv[],
+    JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        StreamPtr priv = JSFilestream::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_WRITE);
+        priv->write(ArgumentValidator(context, argc, argv).toString(0, false));
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFilestream::writeBytes(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        StreamPtr priv = JSFilestream::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_WRITE_BYTES);
+
+        ArgumentValidator validator(context, argc, argv);
+
+        JSObjectRef jsArrayRef = validator.toArrayObject(0);
+        unsigned int arrSize = JSGetArrayLength(context, jsArrayRef);
+        JSValueRef conversionException = NULL;
+        unsigned char *arrData = new unsigned char[arrSize];
+        try {
+            for (int i=0; i<arrSize; i++) {
+                JSValueRef element = JSGetArrayElement(context, jsArrayRef, i);
+                arrData[i] = JSUtil::JSValueToOctet(context, element);
+            }
+
+            priv->write(arrData, arrSize);
+            delete [] arrData;
+        } catch (...) {
+            delete [] arrData;
+            throw;
+        }
+
+    } catch (const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFilestream::writeBase64(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        StreamPtr priv = JSFilestream::getPrivateObject(context, thisObject);
+
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                FILESYSTEM_FUNCTION_API_WRITE_BASE64);
+
+        ArgumentValidator validator(context, argc, argv);
+
+        std::string base64 =
+                WrtDeviceApis::Commons::Base64::decode(validator.toString(0, false));
+
+        priv->write(base64);
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGW("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const WrtDeviceApis::Commons::InvalidArgumentException& err) {
+        LOGE("WrtDeviceApis::Commons::InvalidArgumentException caught");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::INVALID_VALUES_ERROR, err.GetMessage());
+    } catch (...) {
+        LOGW("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err("Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+} // Tizen1_0
+} // TizenApis
+
diff --git a/src/Filesystem/JSFilestream.h b/src/Filesystem/JSFilestream.h
new file mode 100644 (file)
index 0000000..181f8f4
--- /dev/null
@@ -0,0 +1,178 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSFilestream.h
+ */
+
+#ifndef TIZENAPIS_TIZEN_JSFILESTREAM_H_
+#define TIZENAPIS_TIZEN_JSFILESTREAM_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "Stream.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+class JSFilestream
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static StreamPtr getPrivateObject(JSContextRef context, JSValueRef value);
+    static void setPrivateObject(JSObjectRef object, StreamPtr data);
+    static JSObjectRef makeJSObject(JSContextRef context, StreamPtr ptr,
+            Common::SecurityAccessor* srcSecurityAccessor);
+
+private:
+    /**
+    * The callback invoked when an object is first created.
+    */
+    static void initialize(JSContextRef context,
+        JSObjectRef object);
+
+    /**
+    * The callback invoked when an object is finalized.
+    */
+    static void finalize(JSObjectRef object);
+
+    /**
+    * The callback invoked when getting a property's value.
+    */
+    static JSValueRef getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception);
+
+    /**
+    * The callback invoked when setting a property's value.
+    */
+    static bool setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception);
+
+    /**
+    * The callback invoked when collecting the names of an object's properties.
+    */
+    static void getPropertyNames(JSContextRef context,
+        JSObjectRef object,
+        JSPropertyNameAccumulatorRef propertyNames);
+
+    /**
+    * The callback invoked when an object is used as the target of an 'instanceof' expression.
+    */
+    static bool hasInstance(JSContextRef context,
+        JSObjectRef constructor,
+        JSValueRef possibleInstance,
+        JSValueRef* exception);
+
+    /**
+    * Closes this FileStream.
+    */
+    static JSValueRef close(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Reads the specified number of characters from this FileStream.
+    */
+    static JSValueRef read(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Reads the specified number of bytes from this FileStream.
+    */
+    static JSValueRef readBytes(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Reads the specified number of bytes from this FileStream, encoding the result in base64.
+    */
+    static JSValueRef readBase64(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Writes the specified DOMString to this FileStream.
+    */
+    static JSValueRef write(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Writes the specified bytes to this FileStream.
+    */
+    static JSValueRef writeBytes(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * Converts the specified base64 DOMString to bytes and writes the result to this FileStream.
+    */
+    static JSValueRef writeBase64(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception);
+
+    /**
+    * This structure describes a statically declared function property.
+    */
+    static JSStaticFunction m_functions[];
+
+    /**
+    * This structure describes a statically declared value property.
+    */
+    static JSStaticValue m_properties[];
+
+    /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_classRef;
+    Stream* getPrivateObject(JSObjectRef aObject);
+};
+}
+}
+
+#endif
diff --git a/src/Filesystem/JSFilesystemManager.cpp b/src/Filesystem/JSFilesystemManager.cpp
new file mode 100755 (executable)
index 0000000..645a6d8
--- /dev/null
@@ -0,0 +1,656 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSFilesystemManager.cpp
+ */
+
+#include "JSFilesystemManager.h"
+
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Validator.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <WidgetDB/WidgetDBMgr.h>
+#include <WidgetDB/IWidgetDB.h>
+#include <TimeTracer.h>
+#include <ArgumentValidator.h>
+#include <JSWebAPIException.h>
+#include <Commons/Exception.h>
+#include <JSUtil.h>
+#include <Export.h>
+#include <Logger.h>
+
+#include "EventResolve.h"
+#include "Manager.h"
+#include "Path.h"
+#include "EventGetStorage.h"
+#include "EventListStorages.h"
+#include "EventStorageStateChanged.h"
+#include "JSFile.h"
+#include "Converter.h"
+#include "plugin_config.h"
+#include "JSErrors.h"
+#include "FilesystemUtils.h"
+#include "FilesystemPathUtils.h"
+#include "GlobalContextManager.h"
+
+
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace {
+const char* PLUGIN_NAME = "FileSystemManager";
+const char* PROPERTY_MAXPATHLENGTH = "maxPathLength";
+const std::string TIME_TRACER_SYSTEM_MANAGER_RESOLVE = "JSFilesystemManager::resolve";
+
+JSValueRef getFunctionOrNull(JSContextRef ctx, JSValueRef arg)
+{
+    if (Validator(ctx).isCallback(arg)) {
+        return arg;
+    } else if (!JSValueIsNull(ctx, arg) &&  !JSValueIsUndefined(ctx, arg)) {
+        LOGW("throw TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException(
+                "Not a function nor JS null.");
+    }
+    return NULL;
+}
+
+
+JSValueRef getFunction(JSContextRef ctx, JSValueRef arg)
+{
+    if (Validator(ctx).isCallback(arg)) {
+        return arg;
+    }else{
+        LOGW("throw TypeMismatchException");
+        throw DeviceAPI::Common::TypeMismatchException(
+                "JS null passed as function.");
+    }
+}
+
+}
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+using namespace DeviceAPI::Common;
+
+JSClassRef JSFilesystemManager::m_classRef = 0;
+
+JSClassDefinition JSFilesystemManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    PLUGIN_NAME,
+    0,
+    m_properties,
+    m_functions,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+JSStaticValue JSFilesystemManager::m_properties[] = {
+    { PROPERTY_MAXPATHLENGTH, getMaxPathLength, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSFilesystemManager::m_functions[] = {
+    { "resolve", JSFilesystemManager::resolve, kJSPropertyAttributeNone },
+    { "getStorage", JSFilesystemManager::getStorage, kJSPropertyAttributeNone },
+    { "listStorages", JSFilesystemManager::getStorageList, kJSPropertyAttributeNone },
+    { "addStorageStateChangeListener", JSFilesystemManager::addStorageStateListener, kJSPropertyAttributeNone },
+    { "removeStorageStateChangeListener", JSFilesystemManager::removeStorageStateListener, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSFilesystemManager::getClassRef()
+{
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+const JSClassDefinition* JSFilesystemManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+Manager* JSFilesystemManager::getPrivateObject(
+        JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not JSFilesystemManager");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    Manager* priv = static_cast<Manager*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv;
+}
+
+void JSFilesystemManager::setPrivateObject(JSObjectRef object,
+        Manager* newPriv)
+{
+    if (!newPriv) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+
+    if(!JSObjectSetPrivate(object, static_cast<void*>(newPriv))) {
+        LOGE("Failed to set JSFilesystemManager private data");
+        throw UnknownException("Failed to set JSFilesystemManager private data");
+    }
+}
+
+void JSFilesystemManager::initialize(JSContextRef context,
+                                     JSObjectRef object)
+{
+    LOGD("Entered");
+    Manager* priv = &Manager::getInstance();
+    priv->setContext(context);
+    JSFilesystemManager::setPrivateObject(object, priv);
+
+    int widgetId = WrtAccessSingleton::Instance().getWidgetId();
+    auto widgetDB = WidgetDB::Api::getWidgetDB(widgetId);
+    std::map<std::string, std::string> paths;
+    paths["wgt-package"] = widgetDB->getWidgetInstallationPath();
+    paths["wgt-private"] = widgetDB->getWidgetPersistentStoragePath();
+    paths["wgt-private-tmp"] = widgetDB->getWidgetTemporaryStoragePath();
+    Manager& manager = Manager::getInstance();
+    std::for_each(
+            paths.begin(),
+            paths.end(),
+            [&manager] (const std::pair<std::string, std::string>& entry) {
+                LOGD("Storage %s added %s",
+                    entry.first.c_str(),
+                    entry.second.c_str());
+                manager.addWidgetStorage(entry.first, entry.second);
+            }
+    );
+}
+
+void JSFilesystemManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+JSValueRef JSFilesystemManager::getMaxPathLength(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        ConverterPtr converter = ConverterFactory::getConverter(context);
+        return converter->toJSValueRef(Manager::getInstance().getMaxPathLength());
+    } catch (const WrtDeviceApis::Commons::ConversionException& ex) {
+        LOGD("WrtDeviceApis::Commons::ConversionException exception caught: %s : %s",
+                ex.GetClassName().c_str(), ex.GetMessage().c_str());
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught: %s : %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGD("Uknown exception caught");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFilesystemManager::getStorage(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventGetStoragePtr callback;
+
+    try {
+        Manager* priv = JSFilesystemManager::getPrivateObject(context, thisObject);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            return JSValueMakeUndefined(context);
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                FILESYSTEM_FUNCTION_API_GET_STORAGE);
+
+        ArgumentValidator validator(context, argc, argv);
+        validator.toString(0, false);
+        validator.toFunction(1, false);
+        validator.toFunction(2, true);
+
+        JSContextRef privateContext = priv->getContext();
+        ConverterPtr converter = ConverterFactory::getConverter(privateContext);
+
+        auto globalContextManager = GlobalContextManager::getInstance();
+        auto globalContext = globalContextManager->getGlobalContext(context);
+        callback = EventGetStoragePtr(new EventGetStorage(globalContext));
+
+        JSValueRef onSuccess = getFunction(privateContext, argv[1]);
+        JSValueRef onError = NULL;
+
+        if (argc > 2) {
+            onError = getFunctionOrNull(privateContext, argv[2]);
+        }
+
+        callback->setSuccessCallback(onSuccess);
+        callback->setErrorCallback(onError);
+
+        callback->setLabel(converter->toString(argv[0]));
+
+        Manager::getInstance().getStorage(callback);
+
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 context)) {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(context,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                              err.GetMessage(),
+                              callback,
+                              context)) {
+            return JSWebAPIErrorFactory::postException(
+                    context,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFilesystemManager::getStorageList(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventListStoragesPtr callback;
+
+    try {
+        Manager* priv = JSFilesystemManager::getPrivateObject(context, thisObject);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            return JSValueMakeUndefined(context);
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                FILESYSTEM_FUNCTION_API_LIST_STORAGE);
+
+        ArgumentValidator validator(context, argc, argv);
+        validator.toFunction(0, false);
+        validator.toFunction(1, true);
+
+        JSContextRef privateContext = priv->getContext();
+        ConverterPtr converter = ConverterFactory::getConverter(privateContext);
+        auto globalContextManager = GlobalContextManager::getInstance();
+        auto globalContext = globalContextManager->getGlobalContext(context);
+        callback = EventListStoragesPtr(new EventListStorages(globalContext));
+
+        JSValueRef onSuccess = getFunction(privateContext, argv[0]);
+        JSValueRef onError = NULL;
+
+        if (argc > 1) {
+            onError = getFunctionOrNull(privateContext, argv[1]);
+        }
+
+        callback->setSuccessCallback(onSuccess);
+        callback->setErrorCallback(onError);
+        callback->setManager(&Manager::getInstance());
+        Manager::listStorages(callback);
+
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 context)) {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(context,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                              err.GetMessage(),
+                              callback,
+                              context)) {
+            return JSWebAPIErrorFactory::postException(
+                    context,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFilesystemManager::addStorageStateListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventStorageStateChangedPtr callback;
+
+    try {
+        Manager* priv = JSFilesystemManager::getPrivateObject(context, thisObject);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            return JSValueMakeUndefined(context);
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                FILESYSTEM_FUNCTION_API_ADD_STORAGE_LISTENER);
+
+        ArgumentValidator validator(context, argc, argv);
+        validator.toFunction(0, false);
+        validator.toFunction(1, true);
+
+        JSContextRef globalContext = priv->getContext();
+        ConverterPtr converter = ConverterFactory::getConverter(globalContext);
+        auto contextManager = GlobalContextManager::getInstance();
+        callback = EventStorageStateChangedPtr(new EventStorageStateChanged(
+                    contextManager->getGlobalContext(context)));
+
+        JSValueRef onSuccess = getFunction(globalContext, argv[0]);
+        JSValueRef onError = NULL;
+        if (argc > 1) {
+            onError = getFunctionOrNull(globalContext, argv[1]);
+        }
+
+        callback->setSuccessCallback(onSuccess);
+        callback->setErrorCallback(onError);
+
+        long id = Manager::getInstance().addStorageStateChangeListener(callback);
+
+        return converter->toJSValueRefLong(id);
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 context)) {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(context,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(
+                              err.GetClassName()),
+                              err.GetMessage(),
+                              callback,
+                              context)) {
+            return JSWebAPIErrorFactory::postException(
+                    context,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFilesystemManager::removeStorageStateListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        Manager* priv = JSFilesystemManager::getPrivateObject(context, thisObject);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            return JSValueMakeUndefined(context);
+        }
+
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                FILESYSTEM_FUNCTION_API_REMOVE_STORAGE_LISTENER);
+
+        ArgumentValidator validator(context, argc, argv);
+        validator.toLong(0, false);
+
+        JSContextRef globalContext = priv->getContext();
+        ConverterPtr converter = ConverterFactory::getConverter(globalContext);
+
+        long id = static_cast<long>(converter->toLong(argv[0]));
+        LOGD("id: %ld", id);
+
+        Manager::getInstance().removeStorageStateChangeListener(id);
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSFilesystemManager::resolve(JSContextRef localContext,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argc,
+        const JSValueRef argv[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    EventResolvePtr callback;
+
+    try {
+        Manager* priv = JSFilesystemManager::getPrivateObject(localContext, thisObject);
+        if (!priv) {
+            LOGE("Private object is NULL");
+            return JSValueMakeUndefined(localContext);
+        }
+
+        TIZEN_CHECK_ACCESS(localContext, exception, priv,
+                FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID);
+
+        ArgumentValidator validator(localContext, argc, argv);
+        const std::string virtualPath = validator.toString(0, false);
+        JSValueRef onSuccess = validator.toFunction(1, false);
+        JSValueRef onError = validator.toFunction(2, true);
+        std::string perm = validator.toString(3, true, "rw");
+
+        LOGD("resolve");
+
+        JSContextRef globalContext = priv->getContext();
+
+        auto contextManager = GlobalContextManager::getInstance();
+        callback = EventResolvePtr(new EventResolve(
+                contextManager->getGlobalContext(localContext)));
+
+        callback->setSuccessCallback(onSuccess);
+        callback->setErrorCallback(onError);
+
+        PathPtr path;
+        path = Utils::fromVirtualPath(
+                globalContext,
+                virtualPath);
+        LOGD("virtualPath:[%s]", virtualPath.c_str());
+        int permissions = PERM_READ | PERM_WRITE;
+
+        std::string rootPath;
+        std::size_t found;
+
+        if ((found = virtualPath.find("/")) == std::string::npos) {
+            rootPath = virtualPath;
+        } else {
+            rootPath = virtualPath.substr(0, found);
+        }
+
+        if (virtualPath.find("removable") != std::string::npos) {
+            LOGD("%s : %s",  rootPath.c_str(), virtualPath.c_str());
+            EventGetStoragePtr getStorageEvent(new EventGetStorage(localContext));
+            getStorageEvent->setLabel(rootPath);
+            getStorageEvent->setForSynchronousCall();
+
+            Manager::getInstance().getStorage(getStorageEvent);
+            if (!getStorageEvent->getExceptionName().empty()) {
+                LOGE("%s: %s", getStorageEvent->getExceptionName().c_str(),
+                    getStorageEvent->getExceptionMessage().c_str());
+                return Utils::MainLoop<EventResolvePtr>::passErrorLater(
+                        getStorageEvent->getExceptionName(),
+                        getStorageEvent->getExceptionMessage(),
+                        JSValueMakeUndefined(localContext),
+                        callback);
+            }
+            StoragePropertiesPtr storage = getStorageEvent->getResult();
+
+            if (storage->getState() != StorageProperties::STATE_MOUNTED &&
+                storage->getState() != StorageProperties::STATE_MOUNTED_READONLY)
+            {
+                LOGW("throw NotFoundException");
+                throw DeviceAPI::Common::NotFoundException(
+                        "removable storage is not available.");
+            }
+        }
+
+        if (argc > 3) {
+            LOGD("perms:[%s]", perm.c_str());
+            if (("r" != perm) && ("rw" != perm) && ("w" != perm) && ("a" != perm)) {
+                return JSWebAPIErrorFactory::postException(
+                        localContext,
+                        exception,
+                        JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR,
+                        "Invalid mode");
+            } else if ("r" == perm) {
+                permissions = PERM_READ;
+            }
+        }
+
+        if (permissions & PERM_WRITE && ((virtualPath == "wgt-package" ) ||
+            (virtualPath == "ringtones" )))
+        {
+            return Utils::MainLoop<EventResolvePtr>::passErrorLater(
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                    "invalid mode, permission denied error",
+                    JSValueMakeUndefined(localContext),
+                    callback);
+        }
+
+        callback->setOriginalLocation(virtualPath);
+        callback->setPath(path);
+        callback->setMode(perm);
+
+        Manager::getInstance().getNode(callback);
+
+    } catch(const DeviceAPI::Common::BasePlatformException& err) {
+        LOGD("WrtDeviceAPI::Common::BasePlatformException exception caught");
+        if (!checkReportAsyncAPI(err.getName(),
+                                 err.getMessage(),
+                                 callback,
+                                 localContext)) {
+            LOGD("Synchronous error report for [%s]", err.getName().c_str());
+            return JSWebAPIErrorFactory::postException(localContext,
+                                                       exception,
+                                                       err);
+        }
+    } catch(const WrtDeviceApis::Commons::Exception& err) {
+        LOGD("WrtDeviceApis::Commons::Exception Exception caught");
+        if (!checkReportAsyncAPI(translateApi2APIErrors(err.GetClassName()),
+                                                        err.GetMessage(),
+                                                        callback,
+                                                        localContext)) {
+            return JSWebAPIErrorFactory::postException(
+                    localContext,
+                    exception,
+                    translateApi2APIErrors(std::string(err.GetClassName())),
+                    std::string(err.GetMessage()));
+        }
+    } catch (...) {
+        LOGD("Unexpected exception caught");
+        DeviceAPI::Common::UnknownException err(
+                "Unknown Error");
+        return JSWebAPIErrorFactory::postException(localContext, exception, err);
+    }
+
+    return JSValueMakeUndefined(localContext);
+}
+
+} // namespace DeviceAPI
+} // namespace Filesystem
diff --git a/src/Filesystem/JSFilesystemManager.h b/src/Filesystem/JSFilesystemManager.h
new file mode 100644 (file)
index 0000000..5b2d5c6
--- /dev/null
@@ -0,0 +1,134 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSFilesystemManager.h
+ */
+
+#ifndef TIZENAPIS_TIZEN_JSFILESYSTEMMANAGER_H_
+#define TIZENAPIS_TIZEN_JSFILESYSTEMMANAGER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+
+#include <SecurityAccessor.h>
+#include "Manager.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class JSFilesystemManager
+{
+  public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+  private:
+    static Manager* getPrivateObject(JSContextRef context, JSValueRef value);
+
+    /**
+     * newPriv - WARNING: pointer is not owned
+     *                    (use for example with &Manager::getInstance())
+     */
+    static void setPrivateObject(JSObjectRef object, Manager* newPriv);
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * The callback invoked when getting a property's value.
+     */
+    static JSValueRef getMaxPathLength(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * Resolves a location to a File handle.
+     */
+    static JSValueRef resolve(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argc,
+            const JSValueRef argv[],
+            JSValueRef* exception);
+
+    /**
+     * Get information about a storage based on it's label.
+     */
+    static JSValueRef getStorage(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argc,
+            const JSValueRef argv[],
+            JSValueRef* exception);
+
+    /**
+     * List the available storages on the device.
+     * Get the list of available internal and external storage devices.
+     */
+    static JSValueRef getStorageList(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argc,
+            const JSValueRef argv[],
+            JSValueRef* exception);
+
+    static JSValueRef addStorageStateListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argc,
+            const JSValueRef argv[],
+            JSValueRef* exception) ;
+
+    static JSValueRef removeStorageStateListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argc,
+            const JSValueRef argv[],
+            JSValueRef* exception);
+
+  private:
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_functions[];
+
+    /**
+     * This structure describes a statically declared value property.
+     */
+    static JSStaticValue m_properties[];
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_classRef;
+};
+}
+}
+
+#endif
diff --git a/src/Filesystem/JSStorage.cpp b/src/Filesystem/JSStorage.cpp
new file mode 100755 (executable)
index 0000000..74df28d
--- /dev/null
@@ -0,0 +1,210 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSStorage.cpp
+ */
+
+#include <cassert>
+#include <memory>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/JSDOMExceptionFactory.h>
+#include <Export.h>
+#include "StorageProperties.h"
+#include "JSStorage.h"
+#include "Converter.h"
+#include <Logger.h>
+#include <PlatformException.h>
+
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+
+JSStoragePriv::JSStoragePriv() :
+    m_context(NULL)
+{
+}
+
+JSStoragePriv::~JSStoragePriv()
+{
+}
+
+void JSStoragePriv::setProperties(StoragePropertiesPtr newProp)
+{
+    m_storageProperties = newProp;
+}
+
+StoragePropertiesPtr JSStoragePriv::getProperties() const
+{
+    return m_storageProperties;
+}
+
+void JSStoragePriv::setContext(JSContextRef context)
+{
+    m_context = context;
+}
+
+JSContextRef JSStoragePriv::getContext() const
+{
+    return m_context;
+}
+
+namespace {
+const char* STR_STORAGE_LABEL = "label";
+const char* STR_STORAGE_TYPE = "type";
+const char* STR_STORAGE_STATE = "state";
+} //private namespace
+
+JSClassDefinition JSStorage::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "FileSystemStorage",
+    0,
+    m_property,
+    0,
+    initialize,
+    finalize,
+    NULL,     //HasProperty,
+    getProperty,
+    NULL,     //SetProperty,
+    NULL,     //DeleteProperty,
+    NULL,     //GetPropertyNames,
+    NULL,     //CallAsFunction,
+    NULL,     //CallAsConstructor,
+    hasInstance,
+    NULL,     //ConvertToType
+};
+
+JSStaticValue JSStorage::m_property[] = {
+    { STR_STORAGE_LABEL, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { STR_STORAGE_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { STR_STORAGE_STATE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSStorage::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSStorage::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSStorage::m_jsClassRef = JSClassCreate(
+        JSStorage::getClassInfo());
+
+JSObjectRef JSStorage::createJSObject(JSContextRef context,
+        const StorageProperties &storages,
+        Common::SecurityAccessor* srcSecurityAccessor)
+{
+    JSStoragePriv *priv = new JSStoragePriv();
+    if (!priv) {
+        LOGW("throw UnknownException");
+        throw DeviceAPI::Common::UnknownException("Can not new an object");
+    }
+
+    StoragePropertiesPtr newProps = StoragePropertiesPtr(
+            new StorageProperties(storages));
+    priv->setProperties(newProps);
+    priv->setContext(context);
+
+    if(srcSecurityAccessor) {
+        priv->copyAceCheckAccessFunction(srcSecurityAccessor);
+    }
+    else {
+        LOGW("Source SecurityAccessor is not available!");
+    }
+
+    return JSObjectMake(context, getClassRef(), priv);
+}
+
+void JSStorage::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+}
+
+void JSStorage::finalize(JSObjectRef object)
+{
+    JSStoragePriv* priv = static_cast<JSStoragePriv*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+JSValueRef JSStorage::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    JSStoragePriv *priv = static_cast<JSStoragePriv*>(JSObjectGetPrivate(object));
+
+    try {
+        if (!priv) {
+            LOGE("Private object is not set.");
+            return JSValueMakeUndefined(context);
+        }
+
+        StoragePropertiesPtr storages = priv->getProperties();
+        Converter convert(context);
+
+        if (JSStringIsEqualToUTF8CString(propertyName, STR_STORAGE_LABEL)) {
+            return convert.toJSValueRef(storages->getLabel());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, STR_STORAGE_TYPE)) {
+            return convert.toStorageType(storages->getType());
+        } else if (JSStringIsEqualToUTF8CString(propertyName, STR_STORAGE_STATE)) {
+            return convert.toStorageState(storages->getState());
+        }
+        /*else if (JSStringIsEqualToUTF8CString(propertyName, STR_TYPE_INTERNAL)) {
+            return convert.toJSValueRef(TYPE_INTERNAL);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, STR_TYPE_EXTERNAL)) {
+            return convert.toJSValueRef(TYPE_EXTERNAL);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, STR_STATE_MOUNTED)) {
+            return convert.toJSValueRef(STATE_MOUNTED);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, STR_STATE_REMOVED)) {
+            return convert.toJSValueRef(STATE_REMOVED);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, STR_STATE_UNMOUNTABLE)) {
+            return convert.toJSValueRef(STATE_UNMOUNTABLE);
+        }*/
+    } catch(const Commons::Exception& ex) {
+        LOGW("trying to get incorrect value");
+    } catch(const DeviceAPI::Common::BasePlatformException ex) {
+        LOGW("trying to get incorrect value %s",
+             ex.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSStorage::hasInstance(JSContextRef context,
+        JSObjectRef constructor,
+        JSValueRef possibleInstance,
+        JSValueRef* exception)
+{
+    return JSValueIsObjectOfClass(context, possibleInstance, getClassRef());
+}
+
+} //namespace DeviceAPI
+} //namespace Filesystem
diff --git a/src/Filesystem/JSStorage.h b/src/Filesystem/JSStorage.h
new file mode 100644 (file)
index 0000000..90a24dc
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSStorage.h
+ */
+
+#ifndef TIZENAPIS_TIZEN_JS_STORAGE_H_
+#define TIZENAPIS_TIZEN_JS_STORAGE_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "StorageProperties.h"
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class JSStoragePriv : public Common::SecurityAccessor
+{
+public:
+    JSStoragePriv();
+    virtual ~JSStoragePriv();
+
+    void setProperties(StoragePropertiesPtr newProp);
+    StoragePropertiesPtr getProperties() const;
+
+    JSContextRef getContext() const;
+    void setContext(JSContextRef context);
+
+private:
+    StoragePropertiesPtr m_storageProperties;
+    JSContextRef m_context;
+};
+
+class JSStorage
+{
+public:
+    enum StorageType
+    {
+        TYPE_INTERNAL = 0,
+        TYPE_EXTERNAL,
+    };
+
+    enum StorageState
+    {
+        STATE_MOUNTED = 0,
+        STATE_REMOVED,
+        STATE_UNMOUNTABLE,
+    };
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    /**
+    * create an JSObject for callback function(onAnswerReceived).
+    */
+    static JSObjectRef createJSObject(JSContextRef context,
+            const StorageProperties &storages,
+            Common::SecurityAccessor* srcSecurityAccessor);
+
+private:
+    /**
+    * The callback invoked when an object is first created.
+    */
+    static void initialize(JSContextRef context,
+        JSObjectRef object);
+
+    /**
+    * The callback invoked when an object is finalized.
+    */
+    static void finalize(JSObjectRef object);
+
+    /**
+    * The callback invoked when getting a property's value.
+    */
+    static JSValueRef getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception);
+
+    /**
+    * The callback invoked when an object is used as the target of an 'instanceof' expression.
+    */
+    static bool hasInstance(JSContextRef context,
+        JSObjectRef constructor,
+        JSValueRef possibleInstance,
+        JSValueRef* exception);
+
+    /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+    /**
+    * This structure describes a statically declared value property.
+    */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+}
+}
+
+#endif
+
diff --git a/src/Filesystem/Manager.cpp b/src/Filesystem/Manager.cpp
new file mode 100755 (executable)
index 0000000..b6cc6f2
--- /dev/null
@@ -0,0 +1,1116 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "Manager.h"
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <pcrecpp.h>
+#include <ctime>
+#include <sstream>
+#include <dirent.h>
+#include <app.h>
+#include <glib.h>
+#include <Logger.h>
+#include <Commons/ThreadPool.h>
+#include <storage/storage.h>
+#include <Commons/Exception.h>
+#include <PlatformException.h>
+#include <Commons/Regex.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include "StorageProperties.h"
+#include "Node.h"
+#include "JSErrors.h"
+#include "FilesystemPathUtils.h"
+#include "JSStorage.h"
+
+#include <JSWebAPIErrorFactory.h>
+#include "Converter.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+Manager::Locations Manager::m_locations;
+Manager::RootList Manager::m_rootlist;
+Manager::SubRootList Manager::m_subrootlist;
+const std::size_t Manager::m_maxPathLength = PATH_MAX;
+
+Manager::WatcherContainer  Manager::m_watchers;
+
+bool Manager::fileExists(const std::string &file)
+{
+    errno = 0;
+    struct stat info;
+    memset(&info, 0, sizeof(struct stat));
+    int status = lstat(file.c_str(), &info);
+    if (status == 0) {
+        return true;
+    } else if (errno == ENOENT) {
+        return false;
+    }
+    LOGW("throw IOException");
+    throw DeviceAPI::Common::IOException("Cannot stat file.");
+}
+
+bool Manager::getSupportedVirtualPathCB(int storage,
+                                   storage_type_e type,
+                                   storage_state_e state,
+                                   const char *path,
+                                   void *user_data)
+
+{
+    int ret = STORAGE_ERROR_NONE ;
+    char* absolutePath = NULL;
+    std::string pathString;
+    std::map<std::string, PathPtr>* locationMap = (std::map<std::string, PathPtr>*)user_data;
+
+    LOGD("%d , %d , %d, %s", storage, type, state, path);
+
+    if (type == STORAGE_TYPE_INTERNAL) {
+        absolutePath = NULL;
+        ret = storage_get_directory(storage, STORAGE_DIRECTORY_IMAGES, &absolutePath);
+        if(ret == STORAGE_ERROR_NONE){
+            LOGD(":: %s", absolutePath);
+            pathString.clear();
+            pathString.append(absolutePath);
+            locationMap->insert(make_pair("images", Path::create(pathString)));
+        } else {
+            LOGE("unknown error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+        }
+
+        free(absolutePath);
+        absolutePath = NULL;
+        ret = storage_get_directory(storage, STORAGE_DIRECTORY_VIDEOS, &absolutePath);
+        if (ret == STORAGE_ERROR_NONE) {
+            LOGD(":: %s", absolutePath);
+            pathString.clear();
+            pathString.append(absolutePath);
+            locationMap->insert(make_pair("videos", Path::create(pathString)));
+        } else {
+            LOGE("unknown error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+        }
+
+        free(absolutePath);
+        absolutePath = NULL;
+        ret = storage_get_directory(storage, STORAGE_DIRECTORY_CAMERA , &absolutePath);
+        if (ret == STORAGE_ERROR_NONE) {
+            LOGD(":: %s", absolutePath);
+            pathString.clear();
+            pathString.append(absolutePath);
+            locationMap->insert(make_pair("camera", Path::create(pathString)));
+        } else {
+            LOGE("unknown error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+        }
+
+        free(absolutePath);
+        absolutePath = NULL;
+        ret = storage_get_directory(storage, STORAGE_DIRECTORY_DOWNLOADS , &absolutePath);
+        if (ret == STORAGE_ERROR_NONE) {
+            LOGD(":: %s", absolutePath);
+            pathString.clear();
+            pathString.append(absolutePath);
+            locationMap->insert(make_pair("downloads", Path::create(pathString)));
+        } else {
+            LOGE("unknown error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+        }
+
+        free(absolutePath);
+        absolutePath = NULL;
+        ret = storage_get_directory(storage, STORAGE_DIRECTORY_MUSIC  , &absolutePath);
+        if (ret == STORAGE_ERROR_NONE) {
+            LOGD(":: %s", absolutePath);
+            pathString.clear();
+            pathString.append(absolutePath);
+            locationMap->insert(make_pair("music", Path::create(pathString)));
+        } else {
+            LOGE("unknown error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+        }
+
+        free(absolutePath);
+        absolutePath = NULL;
+        ret = storage_get_directory(storage, STORAGE_DIRECTORY_DOCUMENTS, &absolutePath);
+        if (ret == STORAGE_ERROR_NONE) {
+            LOGD(":: %s", absolutePath);
+            pathString.clear();
+            pathString.append(absolutePath);
+            locationMap->insert(make_pair("documents", Path::create(pathString)));
+        } else {
+            LOGE("unknown error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+        }
+
+        free(absolutePath);
+        absolutePath = NULL;
+        ret = storage_get_directory(storage, STORAGE_DIRECTORY_SYSTEM_RINGTONES, &absolutePath);
+        if (ret == STORAGE_ERROR_NONE){
+            LOGD(":: %s", absolutePath);
+            pathString.clear();
+            pathString.append(absolutePath);
+            locationMap->insert(make_pair("ringtones", Path::create(pathString)));
+        } else {
+            LOGE("unknown error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+        }
+
+        free(absolutePath);
+        absolutePath = NULL;
+    }
+    return true;
+}
+
+
+
+bool Manager::getSupportedDeviceCB(int storage,
+                                   storage_type_e type,
+                                   storage_state_e state,
+                                   const char *path,
+                                   void *user_data)
+
+{
+    std::vector<StoragePropertiesPtr>* storageVector =
+    (std::vector<StoragePropertiesPtr>*)user_data;
+    StoragePropertiesPtr storageItem(new StorageProperties());
+
+    int size = 12;
+    char buf[size];
+    std::string label;
+    std::string fullpath;
+    if (path) {
+        fullpath = path;
+    } else {
+        LOGE("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException("NULL pointer for path");
+    }
+    if (type == STORAGE_TYPE_INTERNAL) {
+        snprintf(buf, size, "internal%d", storage);
+        label.append(buf);
+    } else if (type == STORAGE_TYPE_EXTERNAL) {
+        snprintf(buf, size, "removable%d", storage);
+        label.append(buf);
+    } else {
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException("Unknown storage type");
+    }
+
+    LOGD("%s state %d", label.c_str(), state);
+
+    storageItem->setId(storage);
+    storageItem->setLabel(label);
+    storageItem->setType((short)type);
+    storageItem->setState((short)state);
+    storageItem->setFullPath(fullpath);
+
+    if (storageVector) {
+        storageVector->insert(storageVector->end(), storageItem);
+    } else {
+        LOGE("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException(
+                "NULL pointer for user data");
+    }
+
+    return true;
+}
+
+void Manager::storageStateChangedCB(int storage,
+                                    storage_state_e state,
+                                    void* /*user_data*/)
+{
+    StorageStateHasChanged(storage, state);
+}
+
+Manager& Manager::getInstance()
+{
+    static Manager instance;
+    return instance;
+}
+
+Manager::Manager() :
+    m_context(NULL)
+{
+    LOGD("enter");
+    std::vector<StoragePropertiesPtr> storageList;
+    storage_foreach_device_supported(Manager::getSupportedDeviceCB, &storageList);
+    for (size_t i = 0; i < storageList.size(); i++) {
+        m_locations[storageList[i]->getLabel()] =Path::create(storageList[i]->getFullPath());
+        m_rootlist[storageList[i]->getLabel()] = storageList[i]->getId();
+    }
+
+    storage_foreach_device_supported(Manager::getSupportedVirtualPathCB, &m_locations);
+
+    /* for Tizen */
+    std::map<std::string, PathPtr>::iterator iter;
+    for(iter = m_locations.begin() ; iter != m_locations.end() ; ++iter){
+        setupLocation(iter->first, iter->second->getFullPath().c_str());
+        //LOGE("enter %s, %s", iter->first.c_str(), iter->second->getFullPath().c_str());
+    }
+
+    m_subrootlist[LT_ROOT] = "internal0";
+    m_subrootlist[LT_SDCARD] = "removable1";
+    m_subrootlist[LT_USBHOST] = "removable2";
+    m_subrootlist[LT_DOWNLOADS] = "downloads";
+    m_subrootlist[LT_DOCUMENTS] = "documents";
+    m_subrootlist[LT_SOUNDS] = "music";
+    m_subrootlist[LT_IMAGES] = "images";
+    m_subrootlist[LT_VIDEOS] = "videos";
+    m_subrootlist[LT_RINGTONES] = "ringtones";
+    m_subrootlist[LT_CAMERA] = "camera";
+}
+
+Manager::~Manager()
+{
+    if (m_watchers.size() > 0) {
+        RootList::const_iterator itRoot;
+        for (itRoot = m_rootlist.begin(); itRoot != m_rootlist.end(); ++itRoot) {
+            storage_unset_state_changed_cb(itRoot->second, Manager::storageStateChangedCB);
+        }
+    }
+}
+
+StorageList Manager::getStorageList() const
+{
+    return m_locations;
+}
+
+PathPtr Manager::getBasePath() const
+{
+    Locations::const_iterator it = m_locations.find(m_subrootlist.find(LT_ROOT)->second);
+    if (it == m_locations.end()) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Base path not available.");
+    }
+    return it->second;
+}
+
+PathPtr Manager::getLocationPath(LocationType type) const
+{
+    Locations::const_iterator it = m_locations.find(m_subrootlist.find(type)->second);
+    if (it != m_locations.end()) {
+        return it->second->clone();
+    }
+    return PathPtr();
+}
+
+LocationPaths Manager::getLocationPaths() const
+{
+    LocationPaths result;
+    Locations::const_iterator it = m_locations.begin();
+    for (; it != m_locations.end(); ++it) {
+        result.push_back(it->second->clone());
+    }
+    return result;
+}
+
+LocationTypes Manager::getLocations() const
+{
+    LocationTypes result;
+    SubRootList::const_iterator it = m_subrootlist.begin();
+    for (; it != m_subrootlist.end(); ++it) {
+        result.push_back(it->first);
+    }
+    return result;
+}
+
+void Manager::getNode(const EventResolvePtr& event)
+{
+    // Storage processing is executed at main thread because
+    // it manipulates global singletons.
+    LOGD("Entered path:[%s]", event->getPath()->getFullPath().c_str());
+    // This function executes three functions:
+    // 1. Main initialization.
+    // 2. Worker thread.
+    // 3. Main results relay.
+    Utils::executeThreadAndMainFunctions<EventResolvePtr>(
+            event,
+            Utils::ENoFunction,
+            Manager::resolveWorker,
+            Manager::resolveEnd);
+    LOGD("Finished path:[%s]", event->getPath()->getFullPath().c_str());
+}
+
+void Manager::getStorageBegin(EventGetStoragePtr aEvent)
+{
+    StoragePropertiesPtr storage(new StorageProperties());
+
+    RootList::const_iterator it = m_rootlist.find(aEvent->getLabel());
+    if (it == m_rootlist.end())
+    {
+        Locations::const_iterator itL = m_locations.find(aEvent->getLabel());
+        if (itL == m_locations.end())
+        {
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::NotFoundException(
+                "Base path not available.");
+        }
+        else
+        {
+            storage->setId(0xff);
+            storage->setLabel(aEvent->getLabel());
+            storage->setType(StorageProperties::TYPE_INTERNAL);
+            storage->setState(StorageProperties::STATE_MOUNTED);
+        }
+    }
+    else {
+        int id = it->second;
+
+        storage_type_e currentType;
+        storage_state_e currentState;
+
+        storage_get_type(id, &currentType);
+        storage_get_state(id, &currentState);
+
+        storage->setId(id);
+        storage->setLabel(aEvent->getLabel());
+        storage->setType(static_cast<short>(currentType));
+        storage->setState(static_cast<short>(currentState));
+    }
+    aEvent->setResult(storage);
+}
+void Manager::getStorageEnd(EventGetStoragePtr aEvent)
+{
+    StoragePropertiesPtr storage = aEvent->getResult();
+    Converter converter(aEvent->getContext());
+    JSValueRef result = converter.toJSValueRef(storage,
+                                               aEvent->getContext(),
+                                               &Manager::getInstance());
+    aEvent->callSuccessCallback(result);
+}
+
+void Manager::getStorage(const EventGetStoragePtr& event)
+{
+    // Storage processing is executed at main thread because
+    // it manipulates global singletons.
+    LOGD("get storage start");
+    // This function executes three functions:
+    // 1. Main initialization.
+    // 2. Worker thread.
+    // 3. Main results relay.
+    Utils::executeThreadAndMainFunctions<EventGetStoragePtr>(
+            event,
+            Manager::getStorageBegin,
+            Utils::ENoFunction,
+            Manager::getStorageEnd);
+    LOGD("get storages end");
+}
+
+void Manager::listStoragesEnd(EventListStoragesPtr aEvent)
+{
+    auto thiz = aEvent->getManager();
+    std::vector<StoragePropertiesPtr> storageList;
+    storage_foreach_device_supported(Manager::getSupportedDeviceCB,
+        &storageList);
+    SubRootList::const_iterator it = thiz->m_subrootlist.begin();
+    for (; it != thiz->m_subrootlist.end(); ++it)  {
+        if (it->first == LT_ROOT) {
+            continue;
+        }
+        if (it->first == LT_SDCARD) {
+            continue;
+        }
+        if (it->first == LT_USBHOST) {
+            continue;
+        }
+        thiz->addLocalStorage(it->second, storageList);
+    }
+    Converter converter(aEvent->getContext());
+    JSValueRef result = converter.toJSValueRef(storageList,
+                                               aEvent->getContext());
+    aEvent->callSuccessCallback(result);
+}
+
+void Manager::listStorages(const EventListStoragesPtr& event)
+{
+    // Storage processing is executed at main thread because
+    // it manipulates global singletons.
+    LOGD("list storages start");
+    // This function executes three functions:
+    // 1. Main initialization.
+    // 2. Worker thread.
+    // 3. Main results relay.
+    LOGE("storage end %p", Manager::listStoragesEnd);
+    Utils::executeThreadAndMainFunctions<EventListStoragesPtr>(
+        event,
+        Utils::ENoFunction, //Begin function
+        Utils::ENoFunction, //Worker thread function
+        Manager::listStoragesEnd);
+    LOGD("list storages end");
+}
+
+std::size_t Manager::getMaxPathLength() const
+{
+    return m_maxPathLength;
+}
+
+void Manager::copyBegin(EventCopyPtr aEvent)
+{
+    PathPtr src = aEvent->getSource();
+    PathPtr dest = aEvent->getDestination();
+    LOGD("Entered src:%s dest:%s", src->getFullPath().c_str(),
+            dest->getFullPath().c_str());
+
+    NodePtr srcNode = Node::resolve(src);
+    LOGD("%x %x", srcNode->getMode(), PM_USER_READ);
+    if ((srcNode->getMode() & PM_USER_READ) == 0)
+    {
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException(
+            "Not enough permissions to read source node.");
+    }
+
+    if (!dest->isAbsolute())
+    {
+        dest = src->getPath() + *dest;
+        LOGD("updated dest to:[%s]", dest->getFullPath().c_str());
+    }
+
+    NodePtr parent;
+    try {
+        LOGD("Resolving dest->getPath():[%s]", dest->getPath().c_str());
+        parent = Node::resolve(Path::create(dest->getPath()));
+
+        if (!parent->checkPermission(parent->getPath(), "rw", parent->getType())) {
+           LOGE("parent directory:[%s] permissions is not rw (mode is 0x%x)",
+                parent->getPath()->getFullPath().c_str(),
+                parent->getMode());
+           throw DeviceAPI::Common::IOException("Not enough permissions");
+        }
+    }
+    catch (const DeviceAPI::Common::NotFoundException& ex)
+    {
+        LOGW("caught NotFoundException message: %s", ex.getName().c_str());
+        LOGW("throw NotFoundException");
+        throw ex;
+    }
+    catch (const DeviceAPI::Common::BasePlatformException& ex)
+    {
+        LOGW("caught BasePlatformException message: %s", ex.getName().c_str());
+        LOGW("throw BasePlatformException");
+        throw ex;
+    }
+
+    if (parent->getType() != NT_DIRECTORY)
+    {
+        LOGW("Destination's parent node is not directory, throwing IOException");
+        throw DeviceAPI::Common::IOException(
+                "Destination's parent node is not directory.");
+    }
+
+    std::string realSrc = src->getFullPath();
+    std::string realDest = dest->getFullPath();
+
+    if ( (realSrc == realDest) || (src->getPath() == realDest) ) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Destination is same as source.");
+    }
+
+    errno = 0;
+    struct stat info;
+    memset(&info, 0, sizeof(struct stat));
+    int status = lstat(realDest.c_str(), &info);
+    if ((status != 0) && (errno != ENOENT))
+    {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+            "No access to platform destination node.");
+    }
+
+    if (S_ISDIR(info.st_mode) && srcNode->getType() == NT_FILE)
+    {
+        dest->append("/" + src->getName());
+        realDest = dest->getFullPath();
+        memset(&info, 0, sizeof(struct stat));
+        status = lstat(realDest.c_str(), &info);
+        if ((status != 0) && (errno != ENOENT))
+        {
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::IOException(
+                "No access to platform destination node.");
+        }
+        LOGD("dest updated to:[%s]", dest->getFullPath().c_str());
+    }
+
+    if (0 == status)
+    {
+        //no owerwrite flag setted -> exception
+        if ((aEvent->getOptions() & OPT_OVERWRITE) == 0)
+        {
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::IOException(
+                "Overwrite is not set.");
+        }
+
+        //destination exist. Need to be removed
+        NodePtr node = Node::resolve(dest);
+
+        // only remove if dest is file.
+        if (node->getType() == NT_FILE)
+        {
+            node->remove(aEvent->getOptions());
+        }
+        else
+        {
+            // destination exist and src & dest are directory
+            // and dest path ends with '/'
+            if (srcNode->getType() == NT_DIRECTORY &&
+                    realDest[realDest.length() - 1] == '/')
+            {
+                realDest += src->getName();
+                LOGD("updated dest to:[%s]", realDest.c_str());
+            }
+        }
+        //Destination is not exist. Start copy now
+    }
+
+    LOGD("setting src:[%s] dest:[%s]", src->getFullPath().c_str(),
+            dest->getFullPath().c_str());
+
+    aEvent->setRealDestination(realDest);
+    aEvent->setRealSource(realSrc);
+}
+
+void Manager::copyWorker(EventCopyPtr aEvent)
+{
+    LOGD("Entered");
+    copyElement(aEvent->getRealSource(), aEvent->getRealDestination());
+}
+
+void Manager::copyEnd(EventCopyPtr aEvent)
+{
+    LOGD("Entered");
+    aEvent->callSuccessCallback();
+}
+
+void Manager::copy(EventCopyPtr aCopyEvent)
+{
+    LOGD("Entered");
+    // This function executes three functions:
+    // 1. Main initialization.
+    // 2. Worker thread.
+    // 3. Main results relay.
+    Utils::executeThreadAndMainFunctions<EventCopyPtr>(
+        aCopyEvent,
+        Manager::copyBegin,
+        Manager::copyWorker,
+        Manager::copyEnd);
+}
+
+void Manager::move(const EventMovePtr& event)
+{
+    // This function executes three functions:
+    // 1. Main initialization.
+    // 2. Worker thread.
+    // 3. Main results relay.
+    Utils::executeThreadAndMainFunctions<EventMovePtr>(
+        event,
+        Utils::ENoFunction,  //Begin function
+        Manager::moveWorker, //Main function
+        Manager::moveEnd);   //End function
+}
+
+void Manager::removeBegin(EventRemovePtr aEvent)
+{
+    PathPtr path = aEvent->getPath();
+    NodePtr node = Node::resolve(path);
+    aEvent->setNode(node);
+}
+
+void Manager::removeWorker(EventRemovePtr aEvent)
+{
+    aEvent->getNode()->remove(aEvent->getOptions());
+}
+
+void Manager::removeEnd(EventRemovePtr aEvent)
+{
+    aEvent->callSuccessCallback();
+}
+
+void Manager::remove(EventRemovePtr aRemoveData)
+{
+    LOGD("Remove start");
+    // This function executes three functions:
+    // 1. Main initialization.
+    // 2. Worker thread.
+    // 3. Main results relay.
+    Utils::executeThreadAndMainFunctions<EventRemovePtr>(
+            aRemoveData,
+            Manager::removeBegin,
+            Manager::removeWorker,
+            Manager::removeEnd);
+    LOGD("Remove end");
+}
+
+void Manager::copyElement(const std::string &src,
+                          const std::string &dest,
+                          bool recursive)
+{
+    LOGD("Copying src: %s to: %s", src.c_str(), dest.c_str());
+
+    //element is a file:
+    if (EINA_TRUE != ecore_file_is_dir(src.c_str())) {
+        if (EINA_TRUE != ecore_file_cp(src.c_str(), dest.c_str())) {
+            LOGW("throw IOException [%s] -> [%s]", src.c_str(), dest.c_str());
+            throw DeviceAPI::Common::IOException("Failed to copy file");
+        }
+        return;
+    }
+    //element is a directory -> create it:
+    if (EINA_TRUE != ecore_file_is_dir(dest.c_str())) {
+        if (EINA_TRUE != ecore_file_mkdir(dest.c_str())) {
+            LOGW("Failed to create destination directory [%s]", dest.c_str());
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::IOException("Failed to copy directory");
+        }
+    }
+    //copy all elements of directory:
+    if (recursive) {
+        Eina_List* list = ecore_file_ls(src.c_str());
+        void* data;
+        EINA_LIST_FREE(list, data)
+        {
+            try {
+                copyElement((src + '/' + static_cast<char*>(data)).c_str(),
+                            (dest + '/' + static_cast<char*>(data)).c_str());
+            } catch (DeviceAPI::Common::IOException exception) {
+                LOGW("caught IOException");
+                LOGW("Exception caught Message: %s",
+                     exception.getMessage().c_str());
+                 //remove rest of the list
+                EINA_LIST_FREE(list, data)
+                {
+                    free(data);
+                }
+                LOGW("throw IOException");
+                throw DeviceAPI::Common::IOException("Failed to copy directory");
+            }
+            free(data);
+        }
+    }
+}
+
+long Manager::addStorageStateChangeListener(EventStorageStateChangedPtr callback)
+{
+    RootList::const_iterator it = m_rootlist.begin();
+    long id = 0;
+    if (!m_watchers.empty()){
+        id = (--(m_watchers.end()))->first;
+    }
+    ++id;
+    Manager::m_watchers.insert(std::make_pair(id, callback));
+    for (; it != m_rootlist.end(); ++it)
+    {
+        storage_set_state_changed_cb(
+                it->second,
+                Manager::storageStateChangedCB,
+                NULL);
+    }
+    return id;
+}
+
+void Manager::removeStorageStateChangeListener(long id)
+{
+    auto it = m_watchers.find(id);
+    bool found = false;
+    if (m_watchers.end() != it)
+    {
+        m_watchers.erase(it);
+        found = true;
+    }
+    if (m_watchers.size() == 0) {
+        RootList::const_iterator itRoot;
+        for (itRoot = m_rootlist.begin(); itRoot != m_rootlist.end(); ++itRoot) {
+            storage_unset_state_changed_cb(itRoot->second, Manager::storageStateChangedCB);
+        }
+    }
+    if (found == false) {
+        LOGW("The %d is not exist", id);
+    }
+}
+
+
+bool Manager::matchFilters(const std::string& name,
+        const struct stat& info,
+        const FiltersMap& filters)
+{
+    FiltersMap::const_iterator it = filters.begin();
+    for (; it != filters.end(); ++it) {
+        if (it->first == FF_NAME) {
+            if (!pcrecpp::RE(it->second).PartialMatch(name)) { return false; }
+        } else if (it->first == FF_SIZE) {
+            std::size_t size;
+            std::stringstream ss(it->second);
+            ss >> size;
+            if (!ss ||
+                (size != static_cast<size_t>(info.st_size))) { return false; }
+        } else if (it->first == FF_CREATED) {
+            std::time_t created;
+            std::stringstream ss(it->second);
+            ss >> created;
+            if (!ss || (created != info.st_ctime)) { return false; }
+        } else if (it->first == FF_MODIFIED) {
+            std::time_t modified;
+            std::stringstream ss(it->second);
+            ss >> modified;
+            if (!ss || (modified != info.st_mtime)) { return false; }
+        }
+    }
+    return true;
+}
+
+void Manager::resolveWorker(EventResolvePtr aEvent)
+{
+    NodePtr node = Node::resolve(aEvent->getPath());
+    auto mode = aEvent->getMode();
+    if (!node->checkPermission(aEvent->getPath(),
+                               mode,
+                               node->getType()))
+    {
+        LOGW("throw NotFoundException - Permission Denied Error");
+        throw DeviceAPI::Common::NotFoundException("Permission Denied Error");
+    }
+    int permissions = PERM_NONE;
+    if ("rw" ==  mode)
+    {
+        permissions = PERM_READ | PERM_WRITE;
+    }
+    if ("r" ==  mode)
+    {
+        permissions = PERM_READ;
+    }
+    if ("w" ==  mode)
+    {
+        permissions = PERM_WRITE;
+    }
+    node->setPermissions(permissions);
+    aEvent->setResult(node);
+}
+
+void Manager::resolveEnd(EventResolvePtr aEvent)
+{
+    Converter converter(aEvent->getContext());
+    auto result = aEvent->getResult();
+
+    FilePtr priv = FilePtr(new File(result, File::PermissionList(),
+            aEvent->getOriginalLocaton()));
+    try {
+        NodePtr parent = result->getParent();
+        if (parent) {
+            priv->pushParentPermissions(parent->getPermissions());
+        }
+    }
+    catch (...)
+    {
+        LOGW("Why we control normal operation with EXCEPTION???");
+    }
+
+    JSObjectRef object = JSFile::makeJSObject(aEvent->getContext(), priv,
+            &Manager::getInstance());
+
+    aEvent->callSuccessCallback(object);
+}
+
+void Manager::moveWorker(EventMovePtr aEvent)
+{
+    PathPtr src = aEvent->getSource();
+    PathPtr dest = aEvent->getDestination();
+
+    NodePtr srcNode = Node::resolve(src);
+    if ((srcNode->getMode() & PM_USER_WRITE/*PERM_WRITE*/) == 0)
+    {
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException(
+                 "Not enough permissions to move source node.");
+    }
+
+    if (!dest->isAbsolute()) {
+        dest = src->getPath() + *dest;
+    }
+
+    if ( (*src == *dest) || (src->getPath() == dest->getFullPath()) ) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Destination is same as source.");
+    }
+
+    NodePtr parent;
+    try {
+        parent = Node::resolve(Path::create(dest->getPath()));
+        if (!parent->checkPermission(parent->getPath(), "rw", parent->getType())) {
+           LOGE("parent directory:%s permissions is not rw (mode is 0x%x)",
+                parent->getPath()->getFullPath().c_str(),
+                parent->getMode());
+           throw DeviceAPI::Common::IOException("Not enough permissions");
+        }
+    } catch (const DeviceAPI::Common::NotFoundException& ex) {
+        LOGW("Exception caught %s", ex.getMessage().c_str());
+        aEvent->setExceptionCode(ExceptionCodes::NotFoundException);
+        LOGW("throw NotFoundException");
+        throw ex;
+    }
+    if (parent->getType() != NT_DIRECTORY) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Destination's parent node is not directory.");
+    }
+
+    errno = 0;
+    struct stat info;
+    memset(&info, 0, sizeof(info));
+    int status = lstat(dest->getFullPath().c_str(), &info);
+    if ((status != 0) && (errno != ENOENT)) {
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException(
+                 "No access to platform destination node.");
+    }
+
+    LOGD("%s",dest->getFullPath().c_str());
+
+    if (S_ISDIR(info.st_mode) && srcNode->getType() == NT_FILE) {
+            dest->append("/" + src->getName());
+            memset(&info, 0, sizeof(info));
+            status = lstat(dest->getFullPath().c_str(), &info);
+            if ((status != 0) && (errno != ENOENT)) {
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::IOException(
+                        "No access to platform destination node.");
+            }
+    }
+
+        if (status == 0 && 0 == (aEvent->getOptions() & OPT_OVERWRITE)) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Overwrite is not set.");
+    }
+
+    errno = 0;
+
+    LOGD("%s", dest->getFullPath().c_str());
+
+    if (0 != ::rename(src->getFullPath().c_str(), dest->getFullPath().c_str()))
+    {
+        int error = errno;
+        switch (error)
+        {
+            case EXDEV:
+            {
+                    LOGD("%x %x", srcNode->getMode(), PM_USER_READ);
+                if ((srcNode->getMode() & PM_USER_READ /*PERM_READ*/) == 0)
+                {
+                    LOGW("throw InvalidValuesException");
+                    throw DeviceAPI::Common::InvalidValuesException(
+                             "Not enough permissions to move source node.");
+                }
+                if (0 == status) {
+                    //destination exist. Need to be removed
+                    try {
+                        NodePtr node = Node::resolve(dest);
+                        node->remove(aEvent->getOptions());
+                    } catch (const Commons::Exception& ex) {
+                        LOGW("Exception: %s", ex.GetMessage().c_str());
+                        aEvent->setExceptionCode(ex.getCode());
+                        LOGW("Exception while removing dest directory");
+                    } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+                        LOGW("Exception: %s ", ex.getMessage().c_str());
+                        reportErrorCode(aEvent, ex.getName(), ex.getMessage());
+                    }
+                }
+
+                copyElement(src->getFullPath(),
+                            dest->getFullPath());
+                //remove source files
+                try {
+                    NodePtr node = Node::resolve(aEvent->getSource());
+                    node->remove(aEvent->getOptions());
+                } catch(Commons::Exception ex) {
+                    LOGW("Exception caught: %s", ex.GetMessage().c_str());
+                } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+                    LOGW("BasePlatformException caught and "
+                         "ignored Exception: %s", ex.getMessage().c_str());
+                }
+
+
+                break;
+            }
+        default:
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::IOException(
+                    "Unsopported errno during rename");
+        }
+    }
+    aEvent->setResult(Node::resolve(dest));
+}
+
+void Manager::moveEnd(EventMovePtr aEvent)
+{
+    LOGD("Entered");
+    aEvent->callSuccessCallback();
+}
+
+void Manager::addLocalStorage(std::string label,
+                              std::vector<StoragePropertiesPtr> &storageList)
+{
+    StoragePropertiesPtr storage(new StorageProperties());
+    storage->setId(0xff);
+    storage->setLabel(label);
+    storage->setType(StorageProperties::TYPE_INTERNAL);
+
+    storage_state_e currentState;
+    storage_get_state(0, &currentState);
+    storage->setState((short)currentState);
+
+    storageList.insert(storageList.end(), storage);
+}
+
+void Manager::addWidgetStorage(const std::string &key, const std::string &value)
+{
+    setupLocation(key, value.c_str());
+
+    if (key == "wgt-package")
+    {
+        m_subrootlist[LT_WGTPKG] = key;
+    }
+    else if (key == "wgt-private")
+    {
+        m_subrootlist[LT_WGTPRV] = key;
+    }
+    else if (key == "wgt-private-tmp")
+    {
+        m_subrootlist[LT_WGTPRVTMP] = key;
+    }
+}
+
+void Manager::setContext(JSContextRef context)
+{
+    m_context = context;
+}
+
+JSContextRef Manager::getContext() const
+{
+    return m_context;
+}
+
+void Manager::setupLocation(std::string location, const char* path)
+{
+    LOGD("enter %s,%s", location.c_str(), path);
+
+    if (!Utils::nodeExists(path)) {
+        try {
+            Utils::makePath(path, 0755);
+        } catch (const Commons::Exception& ex) {
+            LOGW("Exception caught: %s", ex.GetMessage().c_str());
+            return;
+        } catch (const DeviceAPI::Common::BasePlatformException& ex) {
+            LOGW("caught BasePlatformException and ignore: %s",
+                  ex.getMessage().c_str());
+        }
+    }
+    m_locations[location] = Path::create(path);
+}
+
+
+void Manager::storageChangeEnd(EventStorageStateChangedPtr aEvent)
+{
+    StoragePropertiesPtr storage = aEvent->getResult();
+    Converter converter(aEvent->getContext());
+    JSValueRef result = converter.toJSValueRef(storage,
+                                               aEvent->getContext(),
+                                               &Manager::getInstance());
+    aEvent->callSuccessCallback(result);
+}
+
+void Manager::emitStorageChange(StoragePropertiesPtr aStorageChange)
+{
+    for (auto i = m_watchers.begin(); i != m_watchers.end(); ++i)
+    {
+        auto event = i->second;
+        StoragePropertiesPtr storageItem(
+            new StorageProperties(*(aStorageChange)));
+        event->setResult(storageItem);
+        Utils::executeThreadAndMainFunctions<EventStorageStateChangedPtr>(
+                event,
+                Utils::ENoFunction,
+                Utils::ENoFunction,
+                Manager::storageChangeEnd);
+    }
+}
+
+
+void Manager::getCurrentStorageStateForWatch()
+{
+    int ret = STORAGE_ERROR_NONE;
+    std::string label("");
+    storage_type_e type;
+    storage_state_e state;
+    RootList::const_iterator it = m_rootlist.begin();
+    for (; it != m_rootlist.end(); ++it) {
+        label = it->first;
+        if (label.compare("") != 0) {
+            StoragePropertiesPtr storageItem(new StorageProperties());
+            ret = storage_get_type(it->second, &type);
+            if (ret != STORAGE_ERROR_NONE) {
+                LOGE("IO error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+                throw DeviceAPI::Common::IOException(FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+            }
+            ret = storage_get_state(it->second, &state);
+            if (ret != STORAGE_ERROR_NONE) {
+                LOGE("IO error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+                throw DeviceAPI::Common::IOException(FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+            }
+
+            storageItem->setId(it->second);
+            storageItem->setLabel(it->first);
+            storageItem->setType(static_cast<short>(type));
+            storageItem->setState(static_cast<short>(state));
+            emitStorageChange(storageItem);
+        }
+    }
+}
+
+void Manager::StorageStateHasChanged(int storage, storage_state_e state)
+{
+    StoragePropertiesPtr storageItem(new StorageProperties());
+    int ret = STORAGE_ERROR_NONE;
+    std::string label;
+    storage_type_e type;
+
+    RootList::const_iterator it = m_rootlist.begin();
+    for (; it != m_rootlist.end(); ++it) {
+        if (it->second == storage) {
+            label = it->first;
+            break;
+        }
+    }
+    ret = storage_get_type(storage, &type);
+    if (ret != STORAGE_ERROR_NONE) {
+        LOGE("IO error : %d , %s", ret, FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+        throw DeviceAPI::Common::IOException(FilesystemErrorUtil::getFilesystemErrorMessage(ret).c_str());
+    }
+
+    if (label.compare("") != 0) {
+        storageItem->setId(storage);
+        storageItem->setLabel(label);
+        storageItem->setType(static_cast<short>(type));
+        storageItem->setState(static_cast<short>(state));
+        emitStorageChange(storageItem);
+    }
+}
+
+} // namespace Filesystem
+} // namespace DeviceAPI
+
diff --git a/src/Filesystem/Manager.h b/src/Filesystem/Manager.h
new file mode 100755 (executable)
index 0000000..9b7f6ef
--- /dev/null
@@ -0,0 +1,192 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef TIZENAPIS_FILESYSTEMMANAGER_H_
+#define TIZENAPIS_FILESYSTEMMANAGER_H_
+
+#include <string>
+#include <map>
+#include <vector>
+#include <cstddef>
+#include <map>
+#include <vector>
+#include <string>
+#include <cstddef>
+#include <Commons/EventReceiver.h>
+#include <storage/storage.h>
+#include "EventResolve.h"
+#include "EventGetStorage.h"
+#include "EventListStorages.h"
+#include "EventStorageStateChanged.h"
+#include "EventCopy.h"
+#include "EventMove.h"
+#include "EventRemove.h"
+#include "Enums.h"
+#include "Path.h"
+#include "Node.h"
+#include "FilesystemErrorUtil.h"
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+typedef std::vector<PathPtr> LocationPaths;
+typedef std::vector<LocationType> LocationTypes;
+typedef std::map<std::string, PathPtr> StorageList;
+
+class Manager : public Common::SecurityAccessor
+{
+public:
+    //! \brief Singleton interface
+    //! \return reference to Manager
+    static Manager& getInstance();
+    //! \brief Checks if file exists.
+    //! @param real file path.
+    //! @return true when file exists, false otherwise.
+    //! @throw PlatformException If unable to validate if file exists.
+    static bool fileExists(const std::string& file);
+    static bool getSupportedDeviceCB(int storage,
+                                     storage_type_e type,
+                                     storage_state_e state,
+                                     const char* path,
+                                     void* user_data);
+
+    static bool getSupportedVirtualPathCB(int storage,
+                                     storage_type_e type,
+                                     storage_state_e state,
+                                     const char* path,
+                                     void* user_data);
+    ~Manager();
+
+    //! \brief Gets base path.
+    //! @return Valid path or empty shared pointer.
+    PathPtr getBasePath() const;
+
+    StorageList getStorageList() const;
+    //! \brief Gets path for specified location type.
+    //! @param type Location type @see WrtPlugins::Api::Filesystem::LocationType.
+    //! @return Valid path or empty shared pointer.
+    PathPtr getLocationPath(
+        LocationType type) const;
+    //! \brief Gets paths to default locations.
+    //! @return Paths to predefined virtual locations.
+    LocationPaths getLocationPaths() const;
+    //! \biref Gets locations supported by platform.
+    //! @return Supported locations.
+    LocationTypes getLocations() const;
+    //! \brief Gets filesystem node.
+    //! @param event Get node event @see Api::Filesystem::EventGetNode.
+    //! @remarks Asynchronous.
+    void getNode(const EventResolvePtr& event);
+
+    void getStorage(const EventGetStoragePtr& event);
+
+    static void listStorages(const EventListStoragesPtr& event);
+
+    //! \brief Gets maximum length of filesystem path.
+    //! @return Maximum path length.
+    std::size_t getMaxPathLength() const;
+    //! \brief Copies node to specified destination.
+    //! @param event Copy node event @see Api::Filesystem::EventCopy.
+    //! @remarks Asynchronous.
+    void copy(EventCopyPtr event);
+    //! \brief Moves node to specified destination.
+    //! @param event Move node event @see Api::Filesystem::EventMove.
+    //! @remarks Asynchronous.
+    void move(const EventMovePtr& event);
+    //! \brief Removes node.
+    //! @param event Remove node event @see Api::Filesystem::EventRemove.
+    //! @remarks Asynchronous.
+    void remove(EventRemovePtr removeData);
+    //! \brief Finds nodes.
+    //! @param event Find nodes event @see Api::Filesystem::EventFind.
+    //! @remarks Asynchronous.
+
+    long addStorageStateChangeListener(EventStorageStateChangedPtr callback);
+    void removeStorageStateChangeListener(long id);
+    static void storageStateChangedCB(int storage,
+                                      storage_state_e state,
+                                      void* /*user_data*/);
+    static void getCurrentStorageStateForWatch();
+    static void StorageStateHasChanged(
+            int storage,
+            storage_state_e state);
+    static void emitStorageChange(StoragePropertiesPtr aStorageChange);
+
+    void addWidgetStorage(const std::string& key, const std::string& value);
+
+    JSContextRef getContext() const;
+    void setContext(JSContextRef context);
+
+protected:
+
+    bool matchFilters(const std::string& name,
+                      const struct stat& info,
+                      const FiltersMap& filter);
+
+    void addLocalStorage(std::string label,
+                         std::vector<StoragePropertiesPtr>& storageList);
+
+private:
+    //! Private constructor for Singleton pattern
+    Manager();
+    //! Private copy constructor for Noncopyable pattern
+    Manager(const Manager &);
+    //! Private copy operator for Noncopyable pattern
+    const Manager &operator=(const Manager &);
+
+    typedef std::map<std::string, PathPtr> Locations;
+    typedef std::map<std::string, int> RootList;
+    typedef std::map<LocationType, std::string> SubRootList;
+    static void setupLocation(std::string location, const char* path);
+
+    static void copyElement(const std::string& src,
+                            const std::string& dest,
+                            bool recursive = true);
+
+    static void removeBegin(EventRemovePtr aEvent);
+    static void removeWorker(EventRemovePtr aEvent);
+    static void removeEnd(EventRemovePtr aEvent);
+    static void getStorageBegin(EventGetStoragePtr aEvent);
+    static void getStorageEnd(EventGetStoragePtr aEvent);
+    static void listStoragesEnd(EventListStoragesPtr aEvent);
+    static void copyBegin(EventCopyPtr aEvent);
+    static void copyWorker(EventCopyPtr aEvent);
+    static void copyEnd(EventCopyPtr aEvent);
+    static void resolveWorker(EventResolvePtr aEvent);
+    static void resolveEnd(EventResolvePtr aEvent);
+    static void moveWorker(EventMovePtr aEvent);
+    static void moveEnd(EventMovePtr aEvent);
+    static void storageChangeEnd(EventStorageStateChangedPtr aEvent);
+
+    typedef std::map<long, EventStorageStateChangedPtr> WatcherContainer;
+    static WatcherContainer m_watchers;
+    static RootList m_rootlist;
+    static SubRootList m_subrootlist;
+    static Locations m_locations; ///< Paths to default locations.
+    static const std::size_t m_maxPathLength; ///< Maximum path length.
+
+    JSContextRef m_context;
+
+};
+
+} // namespace Filesystem
+} // namespace DeviceAPI
+
+#endif // TIZENAPIS_FILESYSTEMMANAGER_H_
+
diff --git a/src/Filesystem/Node.cpp b/src/Filesystem/Node.cpp
new file mode 100755 (executable)
index 0000000..c941253
--- /dev/null
@@ -0,0 +1,881 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Node.cpp
+ */
+
+#include "Node.h"
+
+#include <algorithm>
+#include <memory>
+#include <typeinfo>
+#include <sys/types.h>
+#include <cstdio>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <pcrecpp.h>
+#include <sstream>
+#include <Logger.h>
+#include <PlatformException.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include <Export.h>
+
+#include "Enums.h"
+#include "Manager.h"
+#include "Stream.h"
+#include "Path.h"
+#include "NodeFilterMatcher.h"
+#include "JSErrors.h"
+#include "JSFilestream.h"
+#include "FilesystemPathUtils.h"
+#include "Converter.h"
+
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+struct EventHandler{
+    EventReadTextPtr ptr;
+};
+
+#define MAX_NODE_LENGTH 256
+bool Node::checkPermission(const PathPtr &path, const std::string &mode, NodeType type)
+{
+    switch (type)
+    {
+    case NT_DIRECTORY:
+    {
+        DIR* dir = opendir(path->getFullPath().c_str());
+
+        if (!dir) {
+            LOGW("throw InvalidValuesException");
+            throw DeviceAPI::Common::InvalidValuesException(
+                    "Node has been deleted from platform.");
+        }
+
+        if (closedir(dir) != 0) {
+            LOGW("throw InvalidValuesException");
+            throw DeviceAPI::Common::InvalidValuesException(
+                    "Could not close platform node.");
+        }
+
+        if (mode == "r")
+            return true;
+
+        std::stringstream ss;
+        time_t now;
+        time(&now);
+        ss << now;
+        PathPtr tempFilePath = Path::create(path->getFullPath());
+        tempFilePath->append(ss.str());
+        try
+        {
+            createAsFileInternal(tempFilePath);
+            removeAsFile(tempFilePath);
+        }
+        catch (const DeviceAPI::Common::BasePlatformException& ex)
+        {
+            LOGW("Exception: %s", ex.getMessage().c_str());
+            return false;
+        }
+
+        if (mode == "rw" || mode == "w"  || mode == "a") {
+            return true;
+        }
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException("invalid mode");
+    }
+    break;
+    case NT_FILE:
+    {
+        std::fstream stream;
+        std::ios_base::openmode modeBit = std::fstream::binary;
+
+        if (mode == "r")
+        {
+            modeBit |=     std::fstream::in;
+        }
+        else if (mode == "rw" || mode == "w" || mode == "a")
+        {
+            modeBit |=     std::fstream::app;
+        }
+        else
+        {
+            LOGW("throw InvalidValuesException");
+            throw DeviceAPI::Common::InvalidValuesException("invalid mode");
+        }
+
+        stream.open(path->getFullPath().c_str(), modeBit);
+
+        if (stream.is_open())
+        {
+            stream.close();
+            return true;
+        }
+        return false;
+    }
+    break;
+    }
+    return false;
+}
+
+NodePtr DLL_EXPORT Node::resolve(const PathPtr& path)
+{
+    LOGD("Entered path:[%s]", path->getFullPath().c_str());
+
+    struct stat info;
+    struct stat syminfo;
+
+    if (lstat(path->getFullPath().c_str(), &info) != 0) {
+        LOGE("File:[%s] error no:%d", path->getFullPath().c_str(), errno);
+
+        switch (errno)
+        {
+        case EACCES:
+            LOGW("throw InvalidValuesException for file:[%s]", path->getFullPath().c_str());
+            throw DeviceAPI::Common::InvalidValuesException("Node access denied");
+            break;
+        case ENOENT:
+            LOGW("throw NotFoundException for file:[%s]", path->getFullPath().c_str());
+            throw DeviceAPI::Common::NotFoundException("NotFoundError");
+            break;
+        default:
+            LOGW("throw IOException for file:[%s]", path->getFullPath().c_str());
+            throw DeviceAPI::Common::IOException("Platform exception fail");
+        }
+    }
+
+    if (!S_ISDIR(info.st_mode) & !S_ISREG(info.st_mode) && !S_ISLNK(info.st_mode)) {
+        LOGW("throw IOException for file:[%s]", path->getFullPath().c_str());
+        throw DeviceAPI::Common::IOException(
+                 "Platform node is of unsupported type.");
+    }
+
+    NodeType type = S_ISDIR(info.st_mode) ? NT_DIRECTORY : NT_FILE;
+
+    if (S_ISLNK(info.st_mode)) {
+        syminfo = stat(path);
+
+        type = S_ISDIR(syminfo.st_mode) ? NT_DIRECTORY : NT_FILE;
+        LOGD("%x", type);
+    }
+
+    auto result = std::shared_ptr<Node>(new Node(path, type));
+
+    LOGD("Finished execution for file:[%s] type:%s", path->getFullPath().c_str(),
+         type == NT_DIRECTORY ? "directory" : "file");
+    return result;
+}
+
+PathPtr Node::getPath() const
+{
+    return Path::create(m_path->getFullPath());
+}
+
+NodePtr Node::getChild(const PathPtr& path)
+{
+    if (m_type != NT_DIRECTORY) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Not a directory.");
+    }
+    return Node::resolve(*m_path + *path);
+}
+
+NodeType Node::getType() const
+{
+    return m_type;
+}
+
+int Node::getPermissions() const
+{
+    return m_perms;
+}
+
+void Node::setPermissions(int perms)
+{
+    m_perms = perms;
+}
+
+Node::NameList Node::getChildNames() const
+{
+    if (m_type != NT_DIRECTORY) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Node is not directory.");
+    }
+
+    if ((m_perms & PERM_READ) == 0) {
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException("No permission.");
+    }
+
+    DIR* dir = opendir(m_path->getFullPath().c_str());
+    if (!dir) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Node has been deleted from platform.");
+    }
+
+    NameList result;
+    errno = 0;
+    struct dirent *entry = NULL;
+    while ((entry = readdir(dir))) {
+        if (!strcmp(entry->d_name, ".") || !strncmp(entry->d_name, "..", 2)) {
+            continue;
+        }
+        result.push_back(entry->d_name);
+    }
+    if (errno != 0) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Error while reading directory.");
+    }
+
+    if (closedir(dir) != 0) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Could not close platform node.");
+    }
+
+    return result;
+}
+
+NodeList Node::getChildNodes(const NodeFilterPtr& filter) const
+{
+    if (m_type != NT_DIRECTORY) {
+        LOGW("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Node is not directory.");
+        LOGW("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+    }
+
+    if ((m_perms & PERM_READ) == 0) {
+        LOGW("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException("No permission.");
+    }
+
+    DIR* dir = opendir(m_path->getFullPath().c_str());
+    if (!dir) {
+        LOGW("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Node has been deleted from platform.");
+    }
+
+    errno = 0;
+    NodeList result;
+    struct dirent *entry = NULL;
+    while ((entry = readdir(dir))) {
+        if (!strcmp(entry->d_name, ".") || !strncmp(entry->d_name, "..", 2)) {
+            continue;
+        }
+        try {
+            NodePtr node = Node::resolve(*m_path + entry->d_name);
+            node->setPermissions(getPermissions()); // inherit access rights
+            if (NodeFilterMatcher::match(node, filter)) {
+                result.push_back(node);
+            }
+        }
+        catch (const DeviceAPI::Common::BasePlatformException& ex)
+        {
+            LOGW("caught BasePlatformException ignored");
+        }
+    }
+
+    if (errno != 0) {
+        LOGW("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Error while reading directory.");
+    }
+
+    if (closedir(dir) != 0) {
+        LOGW("Path %s Perm %d", m_path->getFullPath().c_str(), m_perms);
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Could not close platform node.");
+    }
+
+    return result;
+}
+
+
+void Node::getChildNodesWorker(EventListNodesPtr aEvent)
+{
+    NodeList list = aEvent->getNode()->getChildNodes(aEvent->getFilter());
+    aEvent->setResult(list);
+}
+
+void Node::getChildNodesEnd(EventListNodesPtr aEvent)
+{
+    // Convert results into JSCore
+    auto result = aEvent->getResult();
+    Converter converter(aEvent->getContext());
+
+    JSValueRef jsResult = converter.toJSValueRef(
+            result,
+            aEvent->getParentPermissions(),
+            aEvent->getContext());
+    aEvent->callSuccessCallback(jsResult);
+}
+
+void Node::getChildNodes(const EventListNodesPtr& event)
+{
+    LOGD("getChildNodes begin");
+    // This function executes three functions:
+    // 1. Main initialization.
+    // 2. Worker thread.
+    // 3. Main results relay.
+    Utils::executeThreadAndMainFunctions<EventListNodesPtr>(
+        event,
+        Utils::ENoFunction,
+        Node::getChildNodesWorker,
+        Node::getChildNodesEnd);
+    LOGD("getChildNodes end");
+}
+
+NodePtr Node::createChild(
+        const PathPtr& path,
+        NodeType type,
+        int options)
+{
+    if (m_type != NT_DIRECTORY) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Parent node is not a directory.");
+    }
+
+    if ((m_perms & PERM_WRITE) == 0) {
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException(
+                "Not enough permissions.");
+    }
+
+    PathPtr childPath = *m_path + *path;
+    if (exists(childPath)) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Node already exists.");
+    }
+
+    NodePtr result;
+    switch (type) {
+    case NT_FILE:
+        result = createAsFile(childPath, options);
+        break;
+    case NT_DIRECTORY:
+        result = createAsDirectory(childPath, options);
+        break;
+    default:
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Unsupported node type.");
+    }
+    if (!!result) {
+        result->m_perms = m_perms;
+    } else {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Node creation error");
+    }
+
+    return result;
+}
+
+StreamPtr Node::open(int mode)
+{
+    if (m_type == NT_DIRECTORY) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Cannot attach stream to directory.");
+    }
+
+    if (((mode & AM_READ) && ((m_perms & PERM_READ) == 0)) ||
+        (((mode & AM_WRITE) ||
+          (mode & AM_APPEND)) && ((m_perms & PERM_WRITE) == 0))) {
+        LOGW("throw InvalidValuesException");
+        throw DeviceAPI::Common::InvalidValuesException(
+                "Not enough permissions.");
+    }
+
+    auto stream = std::shared_ptr<Stream>(new Stream(shared_from_this(), mode));
+    return stream;
+}
+
+void Node::openBegin(EventOpenPtr aEvent)
+{
+    StreamPtr result = aEvent->getNode()->open(aEvent->getMode());
+    result->setCharSet(aEvent->getCharSet());
+    aEvent->setResult(result);
+}
+
+void Node::openEnd(EventOpenPtr aEvent)
+{
+    // Convert results into JSCore
+    auto result = aEvent->getResult();
+    Converter converter(aEvent->getContext());
+
+    JSObjectRef object = JSFilestream::makeJSObject(aEvent->getContext(), result,
+            &Manager::getInstance());
+
+    JSValueRef jsResult = converter.toJSValueRef(object);
+    aEvent->callSuccessCallback(jsResult);
+}
+
+void Node::open(const EventOpenPtr& event)
+{
+    LOGD("Open begin");
+    // This function executes three functions:
+    // 1. Main initialization.
+    // 2. Worker thread.
+    // 3. Main results relay.
+    Utils::executeThreadAndMainFunctions<EventOpenPtr>(
+        event,
+        openBegin,
+        Utils::ENoFunction,
+        openEnd);
+    LOGD("Open end");
+}
+
+void DLL_EXPORT Node::remove(int options)
+{
+    switch (m_type) {
+    case NT_FILE:
+        removeAsFile(m_path);
+        break;
+    case NT_DIRECTORY:
+        removeAsDirectory(m_path, (options & OPT_RECURSIVE));
+        break;
+    default:
+        LOGE("throw UnknownError");
+        throw DeviceAPI::Common::UnknownException(
+                "Not supported value of m_type");
+    }
+}
+
+unsigned long long Node::getSize() const
+{
+    if (m_type == NT_DIRECTORY) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Getting size for directories is not supported.");
+    }
+
+    struct stat info = stat(m_path);
+    if (!S_ISREG(info.st_mode)) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Specified node is not a regular file.");
+    }
+
+    return info.st_size;
+}
+
+std::time_t Node::getCreated() const
+{
+    return stat(m_path).st_ctime;
+}
+
+std::time_t Node::getModified() const
+{
+    return stat(m_path).st_mtime;
+}
+
+// TODO Optimize it, maybe store a flag indicating that node is a root.
+NodePtr Node::getParent() const
+{
+    LocationPaths roots = Manager::getInstance().getLocationPaths();
+    for (LocationPaths::iterator it = roots.begin(); it != roots.end(); ++it) {
+        if (*(*it) == *m_path) {
+            return NodePtr();
+        }
+    }
+    NodePtr parent = Node::resolve(Path::create(m_path->getPath()));
+    parent->setPermissions(getPermissions());
+    return parent;
+}
+
+int Node::getMode() const
+{
+    int result = 0;
+    struct stat info = stat(m_path);
+    if (info.st_mode & S_IRUSR) { result |= PM_USER_READ; }
+    if (info.st_mode & S_IWUSR) { result |= PM_USER_WRITE; }
+    if (info.st_mode & S_IXUSR) { result |= PM_USER_EXEC; }
+    if (info.st_mode & S_IRGRP) { result |= PM_GROUP_READ; }
+    if (info.st_mode & S_IWGRP) { result |= PM_GROUP_WRITE; }
+    if (info.st_mode & S_IXGRP) { result |= PM_GROUP_EXEC; }
+    if (info.st_mode & S_IROTH) { result |= PM_OTHER_READ; }
+    if (info.st_mode & S_IWOTH) { result |= PM_OTHER_WRITE; }
+    if (info.st_mode & S_IXOTH) { result |= PM_OTHER_EXEC; }
+    return result;
+}
+
+void Node::readBegin(EventReadTextPtr aEvent)
+{
+    auto thiz = aEvent->getNode();
+    // Check access privileges
+    if (thiz->m_type != NT_FILE) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Node is not a file.");
+    }
+    if ((thiz->m_perms & PERM_READ) == 0) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("No permission.");
+    }
+    // Open stream
+    auto stream =
+        std::shared_ptr<Stream>(new Stream(thiz->shared_from_this(), AM_READ));
+    aEvent->setStream(stream);
+}
+
+void Node::readWorker(EventReadTextPtr aEvent)
+{
+    // Read file in text mode
+    std::string buffer;
+    auto inputStream = aEvent->getStream();
+    while (!inputStream->isEof()) {
+        buffer += inputStream->getLine();
+        if (!inputStream->isEof()) {
+            buffer += "\n";
+        }
+    }
+    //Convert string into UTF8
+    auto currentEncoding = aEvent->getCharSet();
+    std::shared_ptr<std::string> utf8OutStr(new std::string());
+    if (!buffer.empty()) {
+        Utils::toUTF8String(currentEncoding,
+                            buffer.c_str(),
+                            buffer.size(),
+                            *utf8OutStr);
+    }
+    aEvent->setResult(utf8OutStr);
+}
+
+void Node::readEnd(EventReadTextPtr aEvent)
+{
+    // Convert results into JSCore
+    auto stream = aEvent->getStream();
+    stream->close();
+    auto nativeResult = aEvent->getResult();
+    Converter converter(aEvent->getContext());
+
+    JSValueRef jsResult = converter.toJSValueRef(*nativeResult);
+    aEvent->callSuccessCallback(jsResult);
+}
+
+gboolean Node::readAsTextCallbackExecutor(void* aEvent)
+{
+    LOGD("Entered");
+    EventHandler* handl = static_cast<EventHandler*>(aEvent);
+    if (!handl) {
+        LOGE("handl is NULL");
+        return false;
+    }
+
+    auto event = handl->ptr;
+    try{
+        JSContextRef context = event->getContext();
+        if (!DeviceAPI::Common::GlobalContextManager::getInstance()->
+                isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            delete handl;
+            return false;
+        }
+
+        if (event->isError()) {
+            LOGE("Error callback invoke");
+            event->callErrorCallback(
+                    DeviceAPI::Common::JSWebAPIErrorFactory::makeErrorObject(context,
+                    event->getExceptionName(),event->getExceptionMessage()));
+        } else {
+            event->callSuccessCallback(
+                    DeviceAPI::Common::JSUtil::toJSValueRef(context, *event->getResult()));
+        }
+
+    } catch(...){
+        LOGE("Exception");
+        delete handl;
+    }
+
+    if (handl) {
+        delete handl;
+    }
+
+    return false;
+}
+
+void* Node::readAsTextThread(void* handler)
+{
+    EventHandler* handl = static_cast<EventHandler*>(handler);
+    auto event = handl->ptr;
+    try{
+        auto node = event->getNode();
+        // Check access privileges
+        if (NT_FILE != node->m_type) {
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::IOException("Node is not a file.");
+        }
+        if (0 == (node->m_perms & PERM_READ)) {
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::IOException("No permission.");
+        }
+        // Open stream
+        auto inputStream =
+            std::shared_ptr<Stream>(new Stream(node->shared_from_this(), AM_READ));
+        std::string buffer;
+        while (!inputStream->isEof()) {
+            buffer += inputStream->getLine();
+            if (!inputStream->isEof()) {
+                buffer += "\n";
+            }
+        }
+        inputStream->close();
+        //Convert string into UTF8
+        auto currentEncoding = event->getCharSet();
+        std::shared_ptr<std::string> utf8OutStr(new std::string());
+        if (!buffer.empty()) {
+            Utils::toUTF8String(currentEncoding,
+                                buffer.c_str(),
+                                buffer.size(),
+                                *utf8OutStr);
+        }
+        event->setResult(utf8OutStr);
+
+        guint id = g_idle_add(readAsTextCallbackExecutor, handler);
+        if (!id) {
+            LOGE("g_idle_add fails");
+            delete handl;
+        }
+    }catch(const  DeviceAPI::Common::BasePlatformException& err){
+        LOGE("Error %s , message %s", err.getName().c_str(), err.getMessage().c_str());
+        event->setException(err.getName(), err.getMessage());
+        event->setIsError(true);
+        delete handl;
+    }
+    catch(...){
+        LOGE("Unknown Exception");
+        event->setException("", "Unknown error");
+        event->setIsError(true);
+        delete handl;
+    }
+    return NULL;
+}
+
+void Node::readAsText(const EventReadTextPtr& aReadData)
+{
+    EventHandler* handl = new EventHandler();
+    handl->ptr = aReadData;
+    pthread_t thread;
+    if(pthread_create(&thread, NULL, readAsTextThread,
+            static_cast<void*>(handl))) {
+        LOGE("Thread creation failed");
+        delete handl;
+        throw DeviceAPI::Common::UnknownException("Thread creation failed");
+    }
+    if(pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+bool Node::exists(const PathPtr& path)
+{
+    struct stat info;
+    memset(&info, 0, sizeof(struct stat));
+    int status = lstat(path->getFullPath().c_str(), &info);
+
+    if (0 == status)
+    {
+        return true;
+    }
+    else if (ENAMETOOLONG == errno)
+    {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("file name is too long");
+    }
+    else if (errno != ENOENT)
+    {
+        return true;
+    }
+    return false;
+}
+
+struct stat Node::stat(const PathPtr& path)
+{
+    struct stat result;
+    memset(&result, 0, sizeof(struct stat));
+    if (::stat(path->getFullPath().c_str(),
+                &result) != 0)
+    {
+        LOGE("File: %s", path->getFullPath().c_str());
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Node does not exist or no access");
+    }
+    return result;
+}
+
+Node::Node(const PathPtr& path, NodeType type):
+    m_path(path),
+    m_type(type),
+    m_perms(PERM_NONE)
+{
+}
+
+NodePtr Node::createAsFile(const PathPtr& path,
+                           int /* options */)
+{
+    createAsFileInternal(path);
+    return std::shared_ptr<Node>(new Node(path, NT_FILE));
+}
+
+void Node::createAsFileInternal(const PathPtr& path)
+{
+    FILE* file = std::fopen(path->getFullPath().c_str(), "wb");
+    if (!file) {
+        LOGW("fopen fails IOException throw for path [%s]",
+             path->getFullPath().c_str());
+        throw DeviceAPI::Common::IOException(
+                 "Platform node could not be created.");
+    }
+    std::fclose(file);
+}
+
+NodePtr Node::createAsDirectory(const PathPtr& path,
+                                int options)
+{
+    if (options & OPT_RECURSIVE) {
+        auto parts = Utils::getParts(path);
+        for (auto it = parts.begin(); it != parts.end(); ++it) {
+            if (!exists(*it)) { createAsDirectoryInternal(*it); }
+        }
+    }
+    createAsDirectoryInternal(path);
+    return std::shared_ptr<Node>(new Node(path, NT_DIRECTORY));
+}
+
+void Node::createAsDirectoryInternal(const PathPtr& path)
+{
+    if (mkdir(path->getFullPath().c_str(), S_IRWXU | S_IRWXG | S_IROTH |
+              S_IXOTH) != 0) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Platform node could not be created.");
+    }
+}
+
+void Node::removeAsFile(const PathPtr& path)
+{
+    auto fullPath = path->getFullPath();
+    if (unlink(fullPath.c_str()) != 0) {
+        LOGW("remove [%s]", fullPath.c_str());
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Error while removing platform node.");
+    }
+}
+
+void Node::removeAsDirectory(const PathPtr& path,
+        bool recursive)
+{
+    if (recursive) {
+        DIR* dir = opendir(path->getFullPath().c_str());
+        if (!dir) {
+            LOGW("File %s", path->getFullPath().c_str());
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::IOException(
+                     "Node does not exist or access denied.");
+        }
+        errno = 0;
+        struct dirent *entry = NULL;
+        while ((entry = readdir(dir))) {
+            if (!strcmp(entry->d_name, ".") || !strncmp(entry->d_name, "..", 2)) {
+                continue;
+            }
+            PathPtr subPath = *path + entry->d_name;
+            struct stat info;
+            memset(&info, 0, sizeof(struct stat));
+            if (lstat(subPath->getFullPath().c_str(), &info) == 0) {
+                try {
+                    if (S_ISDIR(info.st_mode)) {
+                        removeAsDirectory(subPath, true);
+                    } else if (S_ISREG(info.st_mode)) {
+                        removeAsFile(subPath);
+                    }
+                }
+                catch (const DeviceAPI::Common::BasePlatformException& ex)
+                {
+                }
+                // TODO: Not sure if above exception should be swallowed.
+            }
+        }
+        closedir(dir);
+    }
+
+    errno = 0;
+    if (rmdir(path->getFullPath().c_str()) != 0) {
+        if (errno == EEXIST) {
+            LOGW("throw IOException");
+            throw DeviceAPI::Common::IOException("Node has child nodes.");
+        }
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                 "Error while removing platform node.");
+    }
+}
+
+std::string Node::toUri(int /*widgetId*/) const
+{
+    // TODO I believe moving this feature to WrtWrapper would make more sense.
+    return "file://" + m_path->getFullPath();
+}
+
+bool Node::isSubPath(std::string aDirPath, PathPtr aFilePath)
+{
+    auto myPath = aDirPath;
+    if(!myPath.empty() && myPath[myPath.length()-1] != Path::getSeparator()) {
+        myPath += Path::getSeparator();
+        LOGD("updated aDirPath to:%s", aDirPath.c_str());
+    }
+
+    auto childPath = aFilePath->getFullPath();
+    bool isSubP = strncmp(myPath.c_str(), childPath.c_str(), myPath.size()) == 0;
+
+    LOGD("aDirPath:%s myPath:%s aFilePath:%s isSubP:%d",
+            aDirPath.c_str(),
+            myPath.c_str(),
+            aFilePath->getFullPath().c_str(),
+            isSubP);
+
+    return isSubP;
+}
+
+bool Node::isSubPath(PathPtr aPath) const
+{
+    LOGD("Entered thisPath:%s aPath: %s",
+            this->getPath()->getFullPath().c_str(),
+            aPath->getFullPath().c_str());
+
+    resolve(aPath);
+
+    bool isSubP = isSubPath(m_path->getFullPath(), aPath);
+    LOGD("thisPath:%s aPath: %s isSubP:%d",
+            this->getPath()->getFullPath().c_str(),
+            aPath->getFullPath().c_str(),
+            isSubP);
+    return isSubP;
+}
+
+}
+}
diff --git a/src/Filesystem/Node.h b/src/Filesystem/Node.h
new file mode 100644 (file)
index 0000000..7476cba
--- /dev/null
@@ -0,0 +1,208 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Node.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_NODE_H_
+#define TIZENAPIS_FILESYSTEM_NODE_H_
+
+#include <ctime>
+#include <cstddef>
+#include <sys/stat.h>
+#include <set>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <vector>
+#include <ctime>
+#include <Export.h>
+
+#include "Enums.h"
+#include "EventListNodes.h"
+#include "EventOpen.h"
+#include "EventReadText.h"
+#include "NodeTypes.h"
+#include "NodeFilter.h"
+#include "FilesystemUtils.h"
+
+namespace DeviceAPI
+{
+namespace Filesystem
+{
+
+class Node;
+typedef std::shared_ptr<Node> NodePtr;
+typedef std::vector<NodePtr> NodeList;
+typedef NodeList::iterator NodeListIterator;
+
+class Stream;
+typedef std::shared_ptr<Stream> StreamPtr;
+
+class Path;
+typedef std::shared_ptr<Path> PathPtr;
+
+class DLL_EXPORT Node : public std::enable_shared_from_this<Node>
+{
+public:
+    typedef std::vector<std::string> NameList;
+    typedef NameList::iterator NodeListIterator;
+
+    //! \brief Resolves Path into Node
+    //!
+    //! This function creates Node wich represent folder or file
+    //! in file system.
+    //! @return Node smart pointer
+    static NodePtr resolve(const PathPtr& path);
+    //! \brief Checks if path can be accessed
+    //!
+    //! Function opens path and base at reqested mode and type verifies access
+    //! priviliges. If type is NT_DIRECTORY, then functions open directory.
+    //! If mode is readonly, then function returns true. If mode is other than
+    //! "r", then function checksm, if write is possible. If type is NT_FILE,
+    //! then function open file for read mode for "r" mode! and for R/W
+    //! for other mode.
+    //!
+    //! @param path virtual path in filesystem
+    //! @param mode access mode: "r", "rw"
+    //! @param type folder or file
+    //! @return true if access is granted, false if not
+    bool checkPermission(const PathPtr& path,
+                         const std::string& mode,
+                         NodeType type);
+    //! \brief Gets path of current node.
+    //! @return Node's path.
+    PathPtr getPath() const;
+    //! \brief Gets type of current node.
+    //! @return Node's type.
+    NodeType getType() const;
+    //! \brief Gets permissions of the virtual node (not real filesystem node).
+    //! @return Node's permissions.
+    int getPermissions() const;
+    //! \brief Sets permissions on the virtual node (not real filesystem node).
+    //! @param perms Node's permissions @see Api::Filesystem::Permissions.
+    void setPermissions(int perms);
+    //! \brief Gets size of this node.
+    //! @return Size.
+    unsigned long long getSize() const;
+    //! \brief Gets creation date of this node.
+    //! @return Date.
+    std::time_t getCreated() const;
+    //! \brief Gets last modification date of this node.
+    //! @return Date.
+    std::time_t getModified() const;
+    //! \brief Gets parent of this node.
+    //! @return Parent node or NULL if no parent (e.g. in case of a root node).
+    NodePtr getParent() const;
+    //! \brief Gets platform permissions.
+    //! @return Platform permissions (set of flags from @see Permissions enum).
+    int getMode() const;
+    //! \brief Gets direct child of this node.
+    //! @param path Path to the child node.
+    //! @return Ptr to the child node.
+    //! @remarks Ownership passed to the caller.
+    NodePtr getChild(const PathPtr& path);
+    //! \brief Gets list of names of direct child nodes.
+    //! @return Names of child nodes.
+    NameList getChildNames() const;
+    //! \brief Gets list of direct child nodes.
+    //! @return Child nodes.
+    //! @remarks Ownership passed to the caller.
+    //! @deprecated
+    NodeList getChildNodes(
+        const NodeFilterPtr& filter =
+            NodeFilterPtr()) const;
+    //! \brief Gets list of direct descendant nodes.
+    //! @param event Get child nodes event.
+    static void getChildNodes(const EventListNodesPtr& event);
+    //! \brief Creates child of current node.
+    //! @param path Path to the node to create.
+    //! @param type Type of the node @see Api::Filesystem::NodeType.
+    //! @param options Additional options see remarks (no options by default).
+    //! @return Ptr to newly created node.
+    //! @remarks
+    //! Valid options:
+    //! - OPT_RECURSIVE - attempt to create all necessary sub-directories
+    NodePtr createChild(
+        const PathPtr& path,
+        NodeType,
+        int options = OPT_NONE);
+    //! \brief Gets stream for this node.
+    //! @param mode @see Api::Filesystem::AccessMode.
+    //! @return Stream connected with current node.
+    //! @deprecated Use async version of thi method instead.
+    StreamPtr open(int mode);
+    //! \brief Gets stream for this node.
+    //! @param mode @see Api::Filesystem::AccessMode.
+    //! @return Stream connected with current node.
+    static void open(const EventOpenPtr& event);
+    //! \brief Removes underlying filesystem node.
+    //! @param options Removal options (by default removal is recursive).
+    //! @remarks Synchronous.
+    //! Valid options:
+    //! - OPT_RECURSIVE - remove node recursively.
+    void remove(int options);
+
+    static void readAsText(const EventReadTextPtr& event);
+    static void* readAsTextThread(void* aEvent);
+    static gboolean readAsTextCallbackExecutor(void* aEvent);
+
+    void onStreamClose(const StreamPtr& stream);
+
+    std::string toUri(int widgetId) const;
+
+    bool isSubPath(PathPtr aPath) const;
+    static bool isSubPath(std::string aDirPath, PathPtr aFilePath);
+
+private:
+    static bool exists(const PathPtr& path);
+    static struct stat stat(const PathPtr& path);
+
+    Node(const PathPtr& path,
+         NodeType type);
+
+    NodePtr createAsFile(const PathPtr& path,
+                         int options);
+    void createAsFileInternal(const PathPtr& path);
+
+    NodePtr createAsDirectory(const PathPtr& path,
+                              int options);
+    void createAsDirectoryInternal(const PathPtr& path);
+
+    void removeAsFile(const PathPtr& path);
+    void removeAsDirectory(const PathPtr& path,
+                           bool recursive);
+    static void getChildNodesWorker(EventListNodesPtr aEvent);
+    static void getChildNodesEnd(EventListNodesPtr aEvent);
+    static void openBegin(EventOpenPtr aEvent);
+    static void openEnd(EventOpenPtr aEvent);
+    static void readBegin(EventReadTextPtr aEvent);
+    static void readWorker(EventReadTextPtr aEvent);
+    static void readEnd(EventReadTextPtr aEvent);
+
+    PathPtr m_path;
+    NodeType m_type;
+    int m_perms;
+
+};
+
+} // Filesystem
+} // TizenApis
+
+#endif /* TIZENAPIS_FILESYSTEM_NODE_H_ */
+
diff --git a/src/Filesystem/NodeFilter.cpp b/src/Filesystem/NodeFilter.cpp
new file mode 100644 (file)
index 0000000..880a745
--- /dev/null
@@ -0,0 +1,122 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        NodeFilter.cpp
+ */
+
+#include "NodeFilter.h"
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+NodeFilter::NodeFilter()
+{
+    initOptionalPair(m_name);
+    initOptionalPair(m_created.min);
+    initOptionalPair(m_created.max);
+    initOptionalPair(m_modified.min);
+    initOptionalPair(m_modified.max);
+    initOptionalPair(m_size.min);
+    initOptionalPair(m_size.max);
+}
+OptionalString NodeFilter::getName() const
+{
+    return m_name;
+}
+
+void NodeFilter::setName(const OptionalString& name)
+{
+    m_name = name;
+}
+
+OptionalDate NodeFilter::getMinCreated() const
+{
+    return m_created.min;
+}
+
+void NodeFilter::setMinCreated(const OptionalDate& date)
+{
+    m_created.min = date;
+}
+
+OptionalDate NodeFilter::getMaxCreated() const
+{
+    return m_created.max;
+}
+
+void NodeFilter::setMaxCreated(const OptionalDate& date)
+{
+    m_created.max = date;
+}
+
+void NodeFilter::setCreated(const OptionalDate& date)
+{
+    m_created.min = m_created.max = date;
+}
+
+OptionalDate NodeFilter::getMinModified() const
+{
+    return m_modified.min;
+}
+
+void NodeFilter::setMinModified(const OptionalDate& date)
+{
+    m_modified.min = date;
+}
+
+OptionalDate NodeFilter::getMaxModified() const
+{
+    return m_modified.max;
+}
+
+void NodeFilter::setMaxModified(const OptionalDate& date)
+{
+    m_modified.max = date;
+}
+
+void NodeFilter::setModified(const OptionalDate& date)
+{
+    m_modified.min = m_modified.max = date;
+}
+
+OptionalSize NodeFilter::getMinSize() const
+{
+    return m_size.min;
+}
+
+void NodeFilter::setMinSize(const OptionalSize& size)
+{
+    m_size.min = size;
+}
+
+OptionalSize NodeFilter::getMaxSize() const
+{
+    return m_size.max;
+}
+
+void NodeFilter::setMaxSize(const OptionalSize& size)
+{
+    m_size.max = size;
+}
+
+void NodeFilter::setSize(const OptionalSize& size)
+{
+    m_size.min = m_size.max = size;
+}
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/NodeFilter.h b/src/Filesystem/NodeFilter.h
new file mode 100644 (file)
index 0000000..7abfb14
--- /dev/null
@@ -0,0 +1,92 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        NodeFilter.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_NODEFILTER_H_
+#define TIZENAPIS_FILESYSTEM_NODEFILTER_H_
+
+#include <ctime>
+#include <cstddef>
+#include <string>
+#include <utility>
+#include <memory>
+#include <Commons/Range.h>
+
+namespace DeviceAPI {
+namespace Filesystem {
+typedef std::pair<bool, std::string> OptionalString;
+typedef std::pair<bool, std::time_t> OptionalDate;
+typedef std::pair<bool, unsigned long long> OptionalSize;
+
+template <class taType>
+inline std::pair<bool, taType> makeOptionalPair(taType aValue)
+{
+    return std::make_pair(true, aValue);
+}
+
+template <class taType>
+inline void initOptionalPair(std::pair<bool, taType>& aPair)
+{
+    aPair.first = false;
+}
+
+class NodeFilter
+{
+  public:
+    NodeFilter();
+    OptionalString getName() const;
+    void setName(const OptionalString& name);
+
+    OptionalDate getMinCreated() const;
+    void setMinCreated(const OptionalDate& date);
+
+    OptionalDate getMaxCreated() const;
+    void setMaxCreated(const OptionalDate& date);
+
+    void setCreated(const OptionalDate& date);
+
+    OptionalDate getMinModified() const;
+    void setMinModified(const OptionalDate& date);
+
+    OptionalDate getMaxModified() const;
+    void setMaxModified(const OptionalDate& date);
+
+    void setModified(const OptionalDate& date);
+
+    OptionalSize getMinSize() const;
+    void setMinSize(const OptionalSize& size);
+
+    OptionalSize getMaxSize() const;
+    void setMaxSize(const OptionalSize& size);
+
+    void setSize(const OptionalSize& size);
+
+  private:
+    OptionalString m_name;
+    WrtDeviceApis::Commons::Range<OptionalDate> m_created;
+    WrtDeviceApis::Commons::Range<OptionalDate> m_modified;
+    WrtDeviceApis::Commons::Range<OptionalSize> m_size;
+};
+
+typedef std::shared_ptr<NodeFilter> NodeFilterPtr;
+} // Filesystem
+} // TizenApis
+
+#endif // TIZENAPIS_FILESYSTEM_NODEFILTER_H_
diff --git a/src/Filesystem/NodeFilterMatcher.cpp b/src/Filesystem/NodeFilterMatcher.cpp
new file mode 100755 (executable)
index 0000000..9ec0f7b
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        NodeFilterMatcher.cpp
+ */
+
+#include "NodeFilterMatcher.h"
+#include "Path.h"
+
+#include <pcrecpp.h>
+
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+bool NodeFilterMatcher::match(const NodePtr& value,
+        const NodeFilterPtr& filter)
+{
+    if (filter) {
+        if (!matchString(value->getPath()->getName(), filter->getName())) {
+            return false;
+        }
+
+        if (!matchRange(value->getCreated(),
+                        filter->getMinCreated(),
+                        filter->getMaxCreated())) {
+            return false;
+        }
+
+        if (!matchRange(value->getModified(),
+                        filter->getMinModified(),
+                        filter->getMaxModified())) {
+            return false;
+        }
+
+        if (!matchRange(value->getSize(),
+                        filter->getMinSize(),
+                        filter->getMaxSize())) {
+            return false;
+        }
+    }
+    return true;
+}
+
+
+bool NodeFilterMatcher::matchString(const std::string& value,
+        const OptionalString& filter)
+{
+    if (filter.first) {
+        pcrecpp::RE_Options reoption;
+        reoption.set_caseless(true);
+        return pcrecpp::RE(filter.second, reoption).PartialMatch(value);
+    }
+    return true;
+}
+
+template<typename Type>
+bool NodeFilterMatcher::matchRange(const Type& value,
+        const std::pair<bool, Type>& min,
+        const std::pair<bool, Type>& max)
+{
+    if ((min.first && (value < min.second)) ||
+        (max.first && (value > max.second))) {
+        return false;
+    }
+    return true;
+}
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/NodeFilterMatcher.h b/src/Filesystem/NodeFilterMatcher.h
new file mode 100644 (file)
index 0000000..985c34a
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        NodeFilterMatcher.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_NODEFILTERMATCHER_H_
+#define TIZENAPIS_FILESYSTEM_NODEFILTERMATCHER_H_
+
+#include <string>
+#include <utility>
+#include "Node.h"
+#include "NodeFilter.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+class NodeFilterMatcher
+{
+  public:
+    static bool match(const NodePtr& value,
+            const NodeFilterPtr& filter);
+
+  private:
+    static bool matchString(const std::string& value,
+            const OptionalString& filter);
+
+    template<typename Type>
+    static bool matchRange(const Type& value,
+            const std::pair<bool, Type>& min,
+            const std::pair<bool, Type>& max);
+
+  private:
+    NodeFilterMatcher();
+};
+} // Filesystem
+} // TizenApis
+
+#endif // TIZENAPIS_FILESYSTEM_NODEFILTERMATCHER_H_
diff --git a/src/Filesystem/NodeTypes.h b/src/Filesystem/NodeTypes.h
new file mode 100644 (file)
index 0000000..c207b23
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        NodeTypes.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_NODETYPES_H_
+#define TIZENAPIS_FILESYSTEM_NODETYPES_H_
+
+#include <vector>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Filesystem {
+class Node;
+
+typedef std::shared_ptr<Node> NodePtr;
+
+typedef std::vector<NodePtr> NodeList;
+typedef NodeList::iterator NodeListIterator;
+} // Filesystem
+} // TizenApis
+
+#endif // TIZENAPIS_FILESYSTEM_NODETYPES_H_
diff --git a/src/Filesystem/Path.cpp b/src/Filesystem/Path.cpp
new file mode 100755 (executable)
index 0000000..4729554
--- /dev/null
@@ -0,0 +1,174 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Path.cpp
+ */
+
+#include <memory>
+#include <algorithm>
+#include <iterator>
+#include <stdlib.h>
+#include <limits.h>
+#include <PlatformException.h>
+#include <Commons/StringUtils.h>
+#include "Path.h"
+#include <Logger.h>
+#include <Export.h>
+
+
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Filesystem {
+const Path::SeparatorType Path::m_pathSeparator = '/';
+
+PathPtr DLL_EXPORT Path::create(const std::string& path)
+{
+    auto result = std::shared_ptr<Path>(new Path());
+    result->reset(path);
+    return result;
+}
+
+std::string Path::getFullPath() const
+{
+    return m_fullPath;
+}
+
+std::string Path::getPath() const
+{
+    return m_path;
+}
+
+std::string Path::getName() const
+{
+    return m_name;
+}
+
+PathPtr Path::append(const std::string& path)
+{
+    reset(m_fullPath + m_pathSeparator + path);
+    return shared_from_this();
+}
+
+PathPtr Path::append(const PathPtr& path)
+{
+    reset(m_fullPath + m_pathSeparator + path->getFullPath());
+    return shared_from_this();
+}
+
+bool Path::isAbsolute() const
+{
+    return (!m_fullPath.empty() && (m_fullPath[0] == m_pathSeparator));
+}
+
+Path::SeparatorType Path::getSeparator()
+{
+    return m_pathSeparator;
+}
+
+bool Path::isValid(const std::string& str)
+{
+    return !str.empty();
+}
+
+PathPtr Path::clone() const
+{
+    return Path::create(m_fullPath);
+}
+
+Path::Path()
+{
+}
+
+void Path::reset(const std::string& str)
+{
+    if (!isValid(str)) {
+        LOGD("Invalid string %s", str.c_str());
+        LOGW("throw NotFoundException");
+        throw DeviceAPI::Common::NotFoundException("Invalid path");
+    }
+    std::string tmp = Commons::String::unique(/*Commons::String::trim*/(
+                                                  str), m_pathSeparator);
+    if (m_pathSeparator == tmp.back()) {
+        tmp.erase(tmp.end() - 1, tmp.end());
+    }
+    std::string::size_type pos = tmp.find_last_of(m_pathSeparator);
+    if (std::string::npos == pos) {
+        m_fullPath = m_name = tmp;
+        m_path.clear();
+    } else {
+        if (0 == pos) {
+            m_fullPath = m_path = m_pathSeparator;
+        } else {
+            m_fullPath = m_path = tmp.substr(0, pos);
+            m_fullPath += m_pathSeparator;
+        }
+        m_name = tmp.substr(pos + 1);
+        m_fullPath += m_name;
+    }
+}
+
+PathPtr operator+(const Path& lhs, const Path& rhs)
+{
+    return Path::create(lhs.getFullPath())->append(rhs.getFullPath());
+}
+
+PathPtr operator+(const Path& lhs, const std::string& rhs)
+{
+    return Path::create(lhs.getFullPath())->append(rhs);
+}
+
+PathPtr operator+(const std::string& lhs, const Path& rhs)
+{
+    return Path::create(lhs)->append(rhs.getFullPath());
+}
+
+bool operator==(const Path& lhs, const Path& rhs)
+{
+    return (lhs.getFullPath() == rhs.getFullPath());
+}
+
+bool operator==(const Path& lhs, const std::string& rhs)
+{
+    return (lhs.getFullPath() == rhs);
+}
+
+bool operator==(const std::string& lhs, const Path& rhs)
+{
+    return (lhs == rhs.getFullPath());
+}
+
+bool operator!=(const Path& lhs, const Path& rhs)
+{
+    return (lhs.getFullPath() != rhs.getFullPath());
+}
+
+bool operator!=(const Path& lhs, const std::string& rhs)
+{
+    return (lhs.getFullPath() != rhs);
+}
+
+bool operator!=(const std::string& lhs, const Path& rhs)
+{
+    return (lhs != rhs.getFullPath());
+}
+
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/Path.h b/src/Filesystem/Path.h
new file mode 100644 (file)
index 0000000..a1f9ab0
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Path.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_PATH_H_
+#define TIZENAPIS_FILESYSTEM_PATH_H_
+
+#include <string>
+#include <vector>
+#include <memory>
+#include <Export.h>
+
+#include "FilesystemUtils.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class Path;
+typedef std::shared_ptr<Path> PathPtr;
+
+class DLL_EXPORT Path : public std::enable_shared_from_this<Path>
+{
+public:
+    typedef char SeparatorType;
+    static PathPtr create(const std::string& path);
+    static Path::SeparatorType getSeparator();
+    std::string getFullPath() const;
+    std::string getPath() const;
+    std::string getName() const;
+    PathPtr append(const std::string& path);
+    PathPtr append(const PathPtr& path);
+    bool isAbsolute() const;
+    PathPtr clone() const;
+
+private:
+    /**
+     * Checks whether specified string is a valid path.
+     * @param path String to verify.
+     * @return True when string is a valid path, false otherwise.
+     */
+    static bool isValid(const std::string& str);
+    Path();
+    void reset(const std::string& str);
+    static const SeparatorType m_pathSeparator; ///< Path separator.
+    std::string m_fullPath; ///< Full path.
+    std::string m_path;   ///< Base path.
+    std::string m_name;   ///< Last part of the path.
+};
+
+PathPtr operator+(const Path& lhs, const Path& rhs);
+
+PathPtr operator+(const Path& lhs, const std::string& rhs);
+
+PathPtr operator+(const std::string& lhs, const Path& rhs);
+
+bool operator==(const Path& lhs, const Path& rhs);
+
+bool operator==(const Path& lhs, const std::string& rhs);
+
+bool operator==(const std::string& lhs, const Path& rhs);
+
+bool operator!=(const Path& lhs, const Path& rhs);
+
+bool operator!=(const Path& lhs, const std::string& rhs);
+
+bool operator!=(const std::string& lhs, const Path& rhs);
+
+
+} // Filesystem
+} // TizenApis
+
+#endif /* TIZENAPIS_FILESYSTEM_PATH_H_ */
diff --git a/src/Filesystem/StorageProperties.cpp b/src/Filesystem/StorageProperties.cpp
new file mode 100755 (executable)
index 0000000..fdb3f06
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        StorageProperties.cpp
+ */
+
+#include "StorageProperties.h"
+
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+StorageProperties::StorageProperties() :
+        id(0),
+        label(""),
+        type(0),
+        state(0),
+        fullpath("")
+{
+}
+
+StorageProperties::StorageProperties(const StorageProperties& src) :
+    id(src.id),
+    label(src.label),
+    type(src.type),
+    state(src.state),
+    fullpath(src.fullpath)
+{
+}
+
+void StorageProperties::setId (const int Id)
+{
+    id = Id;
+}
+
+void StorageProperties::setLabel (const std::string &Label)
+{
+    label = Label;
+}
+
+void StorageProperties::setType (const short Type)
+{
+    type = Type;
+}
+
+void StorageProperties::setState (const short State)
+{
+    state = State;
+}
+
+void StorageProperties::setFullPath (const std::string &FullPath)
+{
+    fullpath = FullPath;
+}
+
+int StorageProperties::getId() const
+{
+    return id;
+}
+
+std::string StorageProperties::getLabel() const
+{
+    return label;
+}
+
+short StorageProperties::getType() const
+{
+    return type;
+}
+
+short StorageProperties::getState() const
+{
+    return state;
+}
+
+std::string StorageProperties::getFullPath() const
+{
+    return fullpath;
+}
+} // Filesystem
+} // TizenApis
diff --git a/src/Filesystem/StorageProperties.h b/src/Filesystem/StorageProperties.h
new file mode 100644 (file)
index 0000000..020227c
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        StorageProperties.h
+ */
+
+#ifndef TIZENAPIS_API_FILESYSTEM_STORAGE_PROPERTIES_H_
+#define TIZENAPIS_API_FILESYSTEM_STORAGE_PROPERTIES_H_
+
+#include <memory>
+#include <string>
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+class StorageProperties;
+typedef std::shared_ptr<StorageProperties> StoragePropertiesPtr;
+
+class StorageProperties
+{
+private:
+    int id;
+    std::string label;
+    short type;
+    short state;
+    std::string fullpath;
+public:
+    enum StorageType
+    {
+        TYPE_INTERNAL = 0,
+        TYPE_EXTERNAL,
+    };
+
+    enum StorageState
+    {
+        STATE_UNMOUNTABLE = -2,
+        STATE_REMOVED = -1,
+        STATE_MOUNTED = 0,
+        STATE_MOUNTED_READONLY = 1,
+    };
+
+    void setId (const int Id);
+    void setLabel (const std::string &Label);
+    void setType (const short Type);
+    void setState (const short State);
+    void setFullPath (const std::string &FullPath);
+
+    int getId() const;
+    std::string getLabel() const;
+    short getType() const;
+    short getState() const;
+    std::string getFullPath() const;
+
+    StorageProperties();
+    StorageProperties(const StorageProperties& src);
+};
+} // Filesystem
+} // TizenApis
+
+#endif //TIZENAPIS_API_FILESYSTEM_STORAGE_PROPERTIES_H_
diff --git a/src/Filesystem/Stream.cpp b/src/Filesystem/Stream.cpp
new file mode 100755 (executable)
index 0000000..575c5f4
--- /dev/null
@@ -0,0 +1,342 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Stream.cpp
+ */
+
+#include "Stream.h"
+
+#include <stdio.h>
+#include <new>
+#include <Logger.h>
+#include <PlatformException.h>
+
+#include "Node.h"
+#include "Path.h"
+
+
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+
+namespace DeviceAPI {
+namespace Filesystem {
+Stream::Stream(const NodePtr& parent,
+        int mode) :
+    m_mode(mode)
+{
+    LOGD("Stream created this %p", this);
+    std::ios_base::openmode mode_ = std::ios_base::binary;
+    if (mode & AM_READ) { mode_ |= std::ios_base::in; }
+    if (mode & AM_WRITE) { mode_ |= std::ios_base::out; }
+    else if (mode & AM_APPEND) {
+        mode_ |= (std::ios_base::app | std::ios_base::out);
+    }
+    auto path = parent->getPath()->getFullPath();
+    LOGD("Open stream path %s mode ios %d mode JS %d",
+         path.c_str(),
+         mode_,
+         mode);
+    m_stream.open(path.c_str(), mode_);
+    if (!m_stream) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Could not open stream.");
+    }
+}
+
+Stream::~Stream()
+{
+    LOGD("Stream destroyed %p", this);
+    close();
+}
+
+StreamPtr Stream::write(bool arg)
+{
+    return write_(arg);
+}
+
+StreamPtr Stream::write(unsigned char arg)
+{
+    return write_(arg);
+}
+
+StreamPtr Stream::write(char arg)
+{
+    return write_(arg);
+}
+
+StreamPtr Stream::write(int arg)
+{
+    return write_(arg);
+}
+
+StreamPtr Stream::write(double arg)
+{
+    return write_(arg);
+}
+
+StreamPtr Stream::write(const std::string& arg)
+{
+    return write_(arg);
+}
+
+StreamPtr Stream::write(const unsigned char* arg, int size)
+{
+    checkForWriting();
+
+    if (!(m_stream.write(reinterpret_cast<const char *>(arg), size))) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                "Error while writing to the stream.");
+    }
+    m_stream.flush();
+
+    return shared_from_this();
+}
+
+StreamPtr Stream::read(bool& arg)
+{
+    return read_(arg);
+}
+
+StreamPtr Stream::read(unsigned char& arg)
+{
+    return read_(arg);
+}
+
+StreamPtr Stream::read(char& arg)
+{
+    return read_(arg);
+}
+
+StreamPtr Stream::read(int& arg)
+{
+    return read_(arg);
+}
+
+StreamPtr Stream::read(double& arg)
+{
+    return read_(arg);
+}
+
+StreamPtr Stream::read(std::string& arg)
+{
+    return read_(arg);
+}
+
+void Stream::setCharSet(const std::string &charSet)
+{
+    m_charSet = charSet;
+}
+
+std::string Stream::getCharSet() const
+{
+    return m_charSet;
+}
+
+
+template <class taValue>
+taValue* Stream::getValues(std::size_t aNum, std::fstream& aStream)
+{
+    checkForReading();
+
+    std::size_t maxChars = aNum + 1;
+    taValue* result = NULL;
+    try {
+        result = new taValue[maxChars];
+        memset(result, 0, maxChars * sizeof(taValue));
+
+    } catch(std::bad_alloc) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Couldn't allocate output buffer.");
+    }
+    aStream.read(reinterpret_cast<char*>(result), aNum * sizeof(taValue));
+
+    if (aStream.bad()) {
+        LOGW("throw IOException");
+        delete[] result;
+        throw DeviceAPI::Common::IOException(
+                "Error while reading from the stream.");
+    }
+
+    return result;
+}
+
+char* Stream::getChars(std::size_t num)
+{
+    return getValues<char>(num, m_stream);
+}
+
+unsigned char* Stream::getBytes(std::size_t num)
+{
+    return getValues<unsigned char>(num, m_stream);
+}
+
+std::size_t Stream::getCount() const
+{
+    if (!isOpen()) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Stream is closed.");
+    }
+
+    if (!isReadable()) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Stream is not readable.");
+    }
+
+    return m_stream.gcount();
+}
+
+std::string Stream::getLine()
+{
+    checkForReading();
+
+    std::string result;
+    std::getline(m_stream, result);
+
+    return result;
+}
+
+bool Stream::isOpen() const
+{
+    return m_stream.is_open();
+}
+
+bool Stream::isEof() const
+{
+    return m_stream.eof();
+}
+
+void Stream::close()
+{
+    if (isOpen()) {
+        m_stream.close();
+    }
+}
+
+int Stream::getMode() const
+{
+    return m_mode;
+}
+
+long Stream::getPosition() const
+{
+    return static_cast<long>(m_stream.tellg());
+}
+
+void Stream::setPosition(long position)
+{
+    if (m_stream.rdstate() & std::ios_base::eofbit) {
+        m_stream.clear();
+    }
+    if (!(m_stream.seekg(position)) || !(m_stream.seekp(position))) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Could not set position.");
+    }
+}
+
+unsigned long long Stream::getSize() const
+{
+    std::fstream::streampos pos = m_stream.tellg();
+    if (pos == -1) {
+        return 0;
+    }
+
+    if (!m_stream.seekg(0, std::_S_end)) {
+        return 0;
+    }
+
+    unsigned long long result = m_stream.tellg();
+    m_stream.seekg(pos, std::_S_beg);
+
+    return result + 1;
+}
+
+template<typename T>
+StreamPtr Stream::write_(T arg)
+{
+    checkForWriting();
+
+    if (!(m_stream << arg)) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                "Error while writing to the stream.");
+    }
+    m_stream.flush();
+
+    return shared_from_this();
+}
+
+template<typename T>
+StreamPtr Stream::read_(T& arg)
+{
+    checkForReading();
+
+    if (!(m_stream >> arg)) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException(
+                "Error while reading from the stream.");
+    }
+
+    return shared_from_this();
+}
+
+bool Stream::isReadable() const
+{
+    return (m_mode & AM_READ);
+}
+
+bool Stream::isWriteable() const
+{
+    return ((m_mode & AM_WRITE) || (m_mode & AM_APPEND));
+}
+
+void Stream::checkForReading() const
+{
+    if (!isOpen()) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Stream is closed.");
+    }
+
+    if (isEof()) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Stream is marked as EOF.");
+    }
+
+    if (!isReadable()) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Stream is not readable.");
+    }
+}
+
+void Stream::checkForWriting() const
+{
+    if (!isOpen()) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Stream is closed.");
+    }
+
+    if (!isWriteable()) {
+        LOGW("throw IOException");
+        throw DeviceAPI::Common::IOException("Stream is not writeable.");
+    }
+}
+} // Filesystem
+} // TizenApis
+
diff --git a/src/Filesystem/Stream.h b/src/Filesystem/Stream.h
new file mode 100644 (file)
index 0000000..5024522
--- /dev/null
@@ -0,0 +1,124 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Stream.h
+ */
+
+#ifndef TIZENAPIS_FILESYSTEM_STREAM_H_
+#define TIZENAPIS_FILESYSTEM_STREAM_H_
+
+#include <cstddef>
+#include <fstream>
+#include <memory>
+#include <Logger.h>
+#include "Enums.h"
+#include "FilesystemUtils.h"
+#include <PlatformException.h>
+#include <SecurityAccessor.h>
+
+namespace DeviceAPI {
+namespace Filesystem {
+class Node;
+typedef std::shared_ptr<Node> NodePtr;
+
+
+class Stream;
+typedef std::shared_ptr<Stream> StreamPtr;
+
+struct StreamHolder {
+    StreamPtr ptr;
+};
+
+class Stream : public std::enable_shared_from_this<Stream> , public Common::SecurityAccessor
+{
+    friend class Node;
+
+public:
+    ~Stream();
+
+    StreamPtr write(bool arg);
+    StreamPtr write(unsigned char arg);
+    StreamPtr write(char arg);
+    StreamPtr write(int arg);
+    StreamPtr write(double arg);
+    StreamPtr write(const std::string& arg);
+    StreamPtr write(const unsigned char* arg, int size);
+
+    StreamPtr read(bool& arg);
+    StreamPtr read(unsigned char& arg);
+    StreamPtr read(char& arg);
+    StreamPtr read(int& arg);
+    StreamPtr read(double& arg);
+    StreamPtr read(std::string& arg);
+
+    void setCharSet(const std::string &charSet);
+    std::string getCharSet() const;
+
+    /**
+     *  Return value should be dealocated by programmer
+     */
+    unsigned char* getBytes(std::size_t num);
+
+    std::size_t getCount() const;
+
+    /**
+     *  Return value should be dealocated by programmer
+     */
+    char* getChars(std::size_t num);
+
+    std::string getLine();
+
+    bool isOpen() const;
+    bool isEof() const;
+
+    void close();
+
+    long getPosition() const;
+    void setPosition(long position);
+
+    int getMode() const;
+
+    unsigned long long getSize() const;
+
+private:
+    template<typename T>
+    StreamPtr read_(T& arg);
+    template<typename T>
+    StreamPtr write_(T arg);
+
+    inline bool isReadable() const;
+    inline bool isWriteable() const;
+    void checkForReading() const;
+    void checkForWriting() const;
+
+    Stream(const NodePtr& parent,
+            int mode);
+
+    int m_mode;
+    mutable std::fstream m_stream;
+    std::string m_charSet;
+
+    template <class taValue>
+    taValue* getValues(std::size_t aNum, std::fstream& aStream);
+
+};
+
+} // Filesystem
+} // TizenApis
+
+#endif /* TIZENAPIS_FILESYSTEM_STREAM_H_ */
diff --git a/src/Filesystem/config.xml b/src/Filesystem/config.xml
new file mode 100644 (file)
index 0000000..42c4ef2
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+  <library-name>libwrt-plugins-tizen-filesystem.so</library-name>
+  <feature-install-uri>filesystem.install.uri</feature-install-uri>
+
+  <api-feature>
+      <name>http://tizen.org/privilege/filesystem.read</name>
+      <device-capability>filesystem.read</device-capability>
+  </api-feature>
+
+  <api-feature>
+      <name>http://tizen.org/privilege/filesystem.write</name>
+      <device-capability>filesystem.write</device-capability>
+  </api-feature>
+
+</plugin-properties>
diff --git a/src/Filesystem/plugin_config.cpp b/src/Filesystem/plugin_config.cpp
new file mode 100644 (file)
index 0000000..edd1c52
--- /dev/null
@@ -0,0 +1,365 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        plugin_config.cpp
+ */
+
+#include <map>
+#include <utility>
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <Export.h>
+#include "Enums.h"
+
+#include "plugin_config_impl.h"
+#include "plugin_config.h"
+
+#define FILESYSTEM_FEATURE_API_READ "http://tizen.org/privilege/filesystem.read"
+#define FILESYSTEM_FEATURE_API_WRITE "http://tizen.org/privilege/filesystem.write"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+
+#pragma GCC visibility push(default)
+const char* FILESYSTEM_PARAM_LOCATION = "param:location";
+const char* FILESYSTEM_DEVICE_CAP_READ = "filesystem.read";
+const char* FILESYSTEM_DEVICE_CAP_WRITE = "filesystem.write";
+
+const char* FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID = "manager_resolve";
+const char* FILESYSTEM_FUNCTION_API_MGR_RESOLVE = "resolve";
+
+const char* FILESYSTEM_FUNCTION_API_GET_STORAGE = "getStorage";
+const char* FILESYSTEM_FUNCTION_API_LIST_STORAGE = "listStorage";
+const char* FILESYSTEM_FUNCTION_API_ADD_STORAGE_LISTENER = "addStorageStateChangeListener";
+const char* FILESYSTEM_FUNCTION_API_REMOVE_STORAGE_LISTENER = "removeStorageStateChangeListener";
+
+const char* FILESYSTEM_FUNCTION_API_RESOLVE = "resolve";
+const char* FILESYSTEM_FUNCTION_API_TO_URI = "toURI";
+const char* FILESYSTEM_FUNCTION_API_LIST_FILES = "listFiles";
+const char* FILESYSTEM_FUNCTION_API_OPEN_STREAM = "openStream";
+const char* FILESYSTEM_FUNCTION_API_READ_AS_TEXT = "readAsText";
+const char* FILESYSTEM_FUNCTION_API_COPY_TO = "copyTo";
+const char* FILESYSTEM_FUNCTION_API_MOVE_TO = "moveTo";
+const char* FILESYSTEM_FUNCTION_API_CREATE_DIR = "createDirectory";
+const char* FILESYSTEM_FUNCTION_API_CREATE_FILE = "createFile";
+const char* FILESYSTEM_FUNCTION_API_DELETE_DIR = "deleteDirectory";
+const char* FILESYSTEM_FUNCTION_API_DELETE_FILE = "deleteFile";
+
+const char* FILESYSTEM_FUNCTION_API_CLOSE = "close";
+const char* FILESYSTEM_FUNCTION_API_READ = "read";
+const char* FILESYSTEM_FUNCTION_API_READ_BYTES = "readBytes";
+const char* FILESYSTEM_FUNCTION_API_READ_BASE64 = "readBase64";
+const char* FILESYSTEM_FUNCTION_API_WRITE = "write";
+const char* FILESYSTEM_FUNCTION_API_WRITE_BYTES = "writeBytes";
+const char* FILESYSTEM_FUNCTION_API_WRITE_BASE64 = "writeBase64";
+#pragma GCC visibility pop
+
+static WrtDeviceApis::Commons::FunctionMapping createFilesystemFunctions();
+
+static WrtDeviceApis::Commons::FunctionMapping FilesystemFunctions =
+    createFilesystemFunctions();
+
+#pragma GCC visibility push(default)
+DEFINE_FUNCTION_GETTER(Filesystem, FilesystemFunctions);
+#pragma GCC visibility pop
+
+static WrtDeviceApis::Commons::FunctionMapping createFilesystemFunctions()
+{
+    using namespace WrtDeviceApis::Commons;
+
+    /**
+     * Device capabilities
+     */
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_FILESYSTEM_READ,
+                          FILESYSTEM_DEVICE_CAP_READ);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_FILESYSTEM_WRITE,
+                          FILESYSTEM_DEVICE_CAP_WRITE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_FILESYSTEM_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_FILESYSTEM_READ, DEVICE_CAP_FILESYSTEM_READ);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_FILESYSTEM_WRITE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_FILESYSTEM_WRITE,
+                       DEVICE_CAP_FILESYSTEM_WRITE);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_READ, FILESYSTEM_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_WRITE, FILESYSTEM_FEATURE_API_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(FILESYSTEM_FEATURES_FILESYSTEM_READ);
+
+    ACE_ADD_API_FEATURE(FILESYSTEM_FEATURES_FILESYSTEM_READ,
+                        FEATURE_READ);
+
+    ACE_CREATE_FEATURE_LIST(FILESYSTEM_FEATURES_FILESYSTEM_WRITE);
+
+    ACE_ADD_API_FEATURE(FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+                        FEATURE_WRITE);
+
+    /**
+     * Functions
+     */
+
+    FunctionMapping FilesystemMapping;
+
+    AceFunction mgrResolveFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_MGR_RESOLVE,
+            FILESYSTEM_FUNCTION_API_MGR_RESOLVE,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST); // check of device-cap will be done inside resolve()
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID,
+                                 mgrResolveFunc));
+
+    AceFunction getStorageFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_STORAGE,
+            FILESYSTEM_FUNCTION_API_GET_STORAGE,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_GET_STORAGE,
+                                 getStorageFunc));
+
+    AceFunction listStorageFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_LIST_STORAGE,
+            FILESYSTEM_FUNCTION_API_LIST_STORAGE,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_LIST_STORAGE,
+                                 listStorageFunc));
+
+    AceFunction addStorageListenerFunc = ACE_CREATE_FUNCTION(
+                FUNCTION_ADD_STORAGE_LISTENER,
+                FILESYSTEM_FUNCTION_API_ADD_STORAGE_LISTENER,
+                FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+                EMPTY_DEVICE_LIST);
+
+        FilesystemMapping.insert(std::make_pair(
+                                     FILESYSTEM_FUNCTION_API_ADD_STORAGE_LISTENER,
+                                     addStorageListenerFunc));
+
+        AceFunction removeStorageListenerFunc = ACE_CREATE_FUNCTION(
+                FUNCTION_REMOVE_STORAGE_LISTENER,
+                FILESYSTEM_FUNCTION_API_REMOVE_STORAGE_LISTENER,
+                FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+                EMPTY_DEVICE_LIST);
+
+        FilesystemMapping.insert(std::make_pair(
+                                     FILESYSTEM_FUNCTION_API_REMOVE_STORAGE_LISTENER,
+                                     removeStorageListenerFunc));
+
+    AceFunction resolveFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_RESOLVE,
+            FILESYSTEM_FUNCTION_API_RESOLVE,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_RESOLVE,
+                                 resolveFunc));
+
+    AceFunction toUriFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_TO_URI,
+            FILESYSTEM_FUNCTION_API_TO_URI,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_TO_URI,
+                                 toUriFunc));
+
+    AceFunction listFilesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_LIST_FILES,
+            FILESYSTEM_FUNCTION_API_LIST_FILES,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_LIST_FILES,
+                                 listFilesFunc));
+
+    AceFunction openStreamFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_OPEN_STREAM,
+            FILESYSTEM_FUNCTION_API_OPEN_STREAM,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_OPEN_STREAM,
+                                 openStreamFunc));
+
+    AceFunction readAsTextFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_READ_AS_TEXT,
+            FILESYSTEM_FUNCTION_API_READ_AS_TEXT,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_READ_AS_TEXT,
+                                 readAsTextFunc));
+
+
+
+
+    AceFunction copyToFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_COPY_TO,
+            FILESYSTEM_FUNCTION_API_COPY_TO,
+            FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_COPY_TO,
+                                 copyToFunc));
+
+    AceFunction moveToFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_MOVE_TO,
+            FILESYSTEM_FUNCTION_API_MOVE_TO,
+            FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_MOVE_TO,
+                                 moveToFunc));
+
+    AceFunction createDirFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CREATE_DIR,
+            FILESYSTEM_FUNCTION_API_CREATE_DIR,
+            FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_CREATE_DIR,
+                                 createDirFunc));
+
+    AceFunction createFileFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CREATE_FILE,
+            FILESYSTEM_FUNCTION_API_CREATE_FILE,
+            FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_CREATE_FILE,
+                                 createFileFunc));
+
+    AceFunction deleteDirFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_DELETE_DIR,
+            FILESYSTEM_FUNCTION_API_DELETE_DIR,
+            FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_DELETE_DIR,
+                                 deleteDirFunc));
+
+    AceFunction deleteFileFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_DELETE_FILE,
+            FILESYSTEM_FUNCTION_API_DELETE_FILE,
+            FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_DELETE_FILE,
+                                 deleteFileFunc));
+
+    AceFunction closeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CLOSE,
+            FILESYSTEM_FUNCTION_API_CLOSE,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_CLOSE,
+                                 closeFunc));
+
+    AceFunction readFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_READ,
+            FILESYSTEM_FUNCTION_API_READ,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_READ,
+                                 readFunc));
+
+    AceFunction readBytesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_READ_BYTES,
+            FILESYSTEM_FUNCTION_API_READ_BYTES,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_READ_BYTES,
+                                 readBytesFunc));
+
+    AceFunction readBase64Func = ACE_CREATE_FUNCTION(
+            FUNCTION_READ_BASE64,
+            FILESYSTEM_FUNCTION_API_READ_BASE64,
+            FILESYSTEM_FEATURES_FILESYSTEM_READ,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_READ_BASE64,
+                                 readBase64Func));
+
+    AceFunction writeFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_WRITE,
+            FILESYSTEM_FUNCTION_API_WRITE,
+            FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_WRITE,
+                                 writeFunc));
+
+    AceFunction writeBytesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_WRITE_BYTES,
+            FILESYSTEM_FUNCTION_API_WRITE_BYTES,
+            FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_WRITE_BYTES,
+                                 writeBytesFunc));
+
+    AceFunction writeBase64Func = ACE_CREATE_FUNCTION(
+            FUNCTION_WRITE_BASE64,
+            FILESYSTEM_FUNCTION_API_WRITE_BASE64,
+            FILESYSTEM_FEATURES_FILESYSTEM_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    FilesystemMapping.insert(std::make_pair(
+                                 FILESYSTEM_FUNCTION_API_WRITE_BASE64,
+                                 writeBase64Func));
+
+    return FilesystemMapping;
+}
+
+}
+}
diff --git a/src/Filesystem/plugin_config.h b/src/Filesystem/plugin_config.h
new file mode 100644 (file)
index 0000000..c14fb63
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        plugin_config.h
+ */
+
+#ifndef _FILESYSTEM_PLUGIN_CONFIG_H_
+#define _FILESYSTEM_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Filesystem {
+DECLARE_FUNCTION_GETTER(Filesystem);
+}
+}
+
+namespace WrtDeviceApis {
+namespace Commons {
+#define FILESYSTEM_CHECK_ACCESS(functionName) \
+    WrtDeviceApis::Commons::aceCheckAccess<AceFunctionGetter, \
+    WrtDeviceApis::Commons::DefaultArgsVerifier<> >(                \
+        getFilesystemFunctionData,         \
+        functionName)
+}
+}
+
+#endif
diff --git a/src/Filesystem/plugin_config_impl.h b/src/Filesystem/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..fb05ce1
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _FILESYSTEM_PLUGIN_CONFIG_IMPL_H_
+#define _FILESYSTEM_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_FILESYSTEM_FILESYSTEM_MANAGER_CLASS "filesystem"
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+extern const char* FILESYSTEM_FUNCTION_API_MGR_RESOLVE_ID;
+extern const char* FILESYSTEM_FUNCTION_API_GET_STORAGE;
+extern const char* FILESYSTEM_FUNCTION_API_LIST_STORAGE;
+extern const char* FILESYSTEM_FUNCTION_API_ADD_STORAGE_LISTENER;
+extern const char* FILESYSTEM_FUNCTION_API_REMOVE_STORAGE_LISTENER;
+
+extern const char* FILESYSTEM_FUNCTION_API_RESOLVE;
+extern const char* FILESYSTEM_FUNCTION_API_TO_URI;
+extern const char* FILESYSTEM_FUNCTION_API_LIST_FILES;
+extern const char* FILESYSTEM_FUNCTION_API_OPEN_STREAM;
+extern const char* FILESYSTEM_FUNCTION_API_READ_AS_TEXT;
+extern const char* FILESYSTEM_FUNCTION_API_COPY_TO;
+extern const char* FILESYSTEM_FUNCTION_API_MOVE_TO;
+extern const char* FILESYSTEM_FUNCTION_API_CREATE_DIR;
+extern const char* FILESYSTEM_FUNCTION_API_CREATE_FILE;
+extern const char* FILESYSTEM_FUNCTION_API_DELETE_DIR;
+extern const char* FILESYSTEM_FUNCTION_API_DELETE_FILE;
+
+extern const char* FILESYSTEM_FUNCTION_API_CLOSE;
+extern const char* FILESYSTEM_FUNCTION_API_READ;
+extern const char* FILESYSTEM_FUNCTION_API_READ_BYTES;
+extern const char* FILESYSTEM_FUNCTION_API_READ_BASE64;
+extern const char* FILESYSTEM_FUNCTION_API_WRITE;
+extern const char* FILESYSTEM_FUNCTION_API_WRITE_BYTES;
+extern const char* FILESYSTEM_FUNCTION_API_WRITE_BASE64;
+
+} // namespace DeviceAPI
+} // namespace Filesystem
+
+#endif // _FILESYSTEM_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/Filesystem/plugin_initializer.cpp b/src/Filesystem/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..665c26c
--- /dev/null
@@ -0,0 +1,127 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+
+#include "JSFile.h"
+#include "JSFilestream.h"
+#include "JSFilesystemManager.h"
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Filesystem {
+
+const char* getNameOfAceSecurityStatus(AceSecurityStatus status) {
+    switch(status) {
+        case AceSecurityStatus::AccessGranted: return "AccessGranted";
+        case AceSecurityStatus::AccessDenied: return "AccessDenied";
+        case AceSecurityStatus::PrivacyDenied: return "PrivacyDenied";
+        case AceSecurityStatus::InternalError: return "InternalError";
+        default:
+            return "Unknown";
+    }
+}
+
+AceSecurityStatus fsysAceCheckAccessFunction(const char* functionName)
+{
+    AceSecurityStatus status = FILESYSTEM_CHECK_ACCESS(functionName);
+
+    LOGD("FILESYSTEM_CHECK_ACCESS for func: %s returned: %s", functionName,
+            getNameOfAceSecurityStatus(status));
+
+    return status;
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerFSFileSetter, Manager, gSecurityAccessor);
+
+class_definition_options_t filesystemOption = {
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerFSFileSetter,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[SEC\\filesystem] on_widget_start_callback (%d)", widgetId);
+
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, fsysAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[SEC\\filesystem] on_widget_stop_callback (%d)", widgetId);
+
+    std::string name = "FileSystem";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch(...) {
+        LOGE("WrtAccess initialization failed");
+    }
+
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\filesystem] on_frame_unload_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\filesystem] on_frame_load_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_FILESYSTEM_FILESYSTEM_MANAGER_CLASS,
+        (js_class_template_getter)DeviceAPI::Filesystem::JSFilesystemManager::getClassRef,
+        &filesystemOption)
+PLUGIN_CLASS_MAP_END
+
+} // Filesystem
+} // DeviceAPI
diff --git a/src/HumanActivityMonitor/CMakeLists.txt b/src/HumanActivityMonitor/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..eeaf76b
--- /dev/null
@@ -0,0 +1,55 @@
+SET(TARGET_NAME ${humanactivitymonitor_target})
+SET(DESTINATION_NAME ${humanactivitymonitor_dest})
+SET(TARGET_IMPL_NAME ${humanactivitymonitor_impl})
+
+pkg_check_modules(platform_pkgs_humanactivitymonitor REQUIRED
+    glib-2.0
+    capi-system-info
+    libcore-context-manager
+    sensor
+)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${TOP}/HumanActivityMonitor
+    ${platform_pkgs_humanactivitymonitor_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSMotionManager.cpp
+    JSPedometerInfo.cpp
+    MotionManager.cpp
+    PedometerInfo.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${platform_pkgs_humanactivitymonitor_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/humanactivitymonitor
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/HumanActivityMonitor/ContextTypes.h b/src/HumanActivityMonitor/ContextTypes.h
new file mode 100755 (executable)
index 0000000..b94ab7c
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _PEDOMETER_TYPES_H_
+#define _PEDOMETER_TYPES_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+//HAM Type
+#define MOTION_ENUM_TYPE_PEDOMETER "PEDOMETER"
+#define MOTION_ENUM_TYPE_WRIST_UP "WRIST_UP"
+#define MOTION_ENUM_TYPE_HRM "HRM"
+#define MOTION_ENUM_TYPE_GPS "GPS"
+
+// Enum PedometerStepStatus
+#define TIZEN_PEDOMETER_STEP_STATUS_NOT_MOVING "NOT_MOVING"
+#define TIZEN_PEDOMETER_STEP_STATUS_WALKING "WALKING"
+#define TIZEN_PEDOMETER_STEP_STATUS_RUNNING "RUNNING"
+#define TIZEN_PEDOMETER_STEP_STATUS_UNKOWN "UNKOWN"
+
+// PEDOMETER Attributes
+#define TIZEN_PEDOMETER_INFO_STEP_STATUS "stepStatus"
+#define TIZEN_PEDOMETER_INFO_SPEED "speed"
+#define TIZEN_PEDOMETER_INFO_WALKING_FREQUENCY "walkingFrequency"
+
+#define TIZEN_PEDOMETER_INFO_CUMULATIVE_DISTANCE "cumulativeDistance"
+#define TIZEN_PEDOMETER_INFO_CUMULATIVE_CALORIE "cumulativeCalorie"
+#define TIZEN_PEDOMETER_INFO_CUMULATIVE_TOTAL_STEP_COUNT "cumulativeTotalStepCount"
+#define TIZEN_PEDOMETER_INFO_CUMULATIVE_WALK_STEP_COUNT "cumulativeWalkStepCount"
+#define TIZEN_PEDOMETER_INFO_CUMULATIVE_RUN_STEP_COUNT "cumulativeRunStepCount"
+
+#define PEDOMETER_INFO_ACCUMULATIVE_DISTANCE "accumulativeDistance"
+#define PEDOMETER_INFO_ACCUMULATIVE_CALORIE "accumulativeCalorie"
+#define PEDOMETER_INFO_ACCUMULATIVE_TOTAL_STEP_COUNT "accumulativeTotalStepCount"
+#define PEDOMETER_INFO_ACCUMULATIVE_WALK_STEP_COUNT "accumulativeWalkStepCount"
+#define PEDOMETER_INFO_ACCUMULATIVE_RUN_STEP_COUNT "accumulativeRunStepCount"
+
+#define TIZEN_PEDOMETER_INFO_STEP_COUNT_DIFFERENCES "stepCountDifferences"
+#define TIZEN_PEDOMETER_INFO_STEP_COUNT_DIFFERENCE "stepCountDifference"
+#define TIZEN_PEDOMETER_INFO_TIMESTAMP "timestamp"
+
+// HRM Attributes
+#define TIZEN_HRM_INFO_HEART_RATE "heartRate"
+#define TIZEN_HRM_INFO_RR_INTERVAL "rRInterval"
+
+//GPS Attributes
+#define TIZEN_GPS_INFO_GPS_INFO "gpsInfo"
+#define TIZEN_GPS_INFO_LATITUDE "latitude"
+#define TIZEN_GPS_INFO_LONGITUDE "longitude"
+#define TIZEN_GPS_INFO_ALTITUDE "altitude"
+#define TIZEN_GPS_INFO_SPEED "speed"
+#define TIZEN_GPS_INFO_ERROR_RANGE "errorRange"
+#define TIZEN_GPS_INFO_TIME_STAMP "timestamp"
+
+//Platform Feature
+#define TIZEN_PLATFORM_FEATURE_PEDOMETER "tizen.org/feature/sensor.pedometer"
+#define TIZEN_PLATFORM_FEATURE_WRIST_UP "tizen.org/feature/sensor.wrist_up"
+#define TIZEN_PLATFORM_FEATURE_HRM "tizen.org/feature/sensor.heart_rate_monitor"
+
+} // Context
+} // DeviceAPI
+
+#endif // _PEDOMETER_TYPES_H_
diff --git a/src/HumanActivityMonitor/JSMotionManager.cpp b/src/HumanActivityMonitor/JSMotionManager.cpp
new file mode 100755 (executable)
index 0000000..935a788
--- /dev/null
@@ -0,0 +1,321 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <cstring>
+
+#include "plugin_config.h"
+#include "JSMotionManager.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+using namespace std;
+
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+JSClassDefinition JSMotionManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "MotionManager",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSMotionManager::m_function[] = {
+    { MOTION_API_GET_CONTEXT_INFO, JSMotionManager::getContextInfo, kJSPropertyAttributeNone },
+    { MOTION_API_SET_ACCUMULATIVE_PEDOMETER_LISTENER, JSMotionManager::setAccumulativePedometerListener, kJSPropertyAttributeNone },
+    { MOTION_API_UNSET_ACCUMULATIVE_PEDOMETER_LISTENER, JSMotionManager::unsetAccumulativePedometerListener, kJSPropertyAttributeNone },
+    { MOTION_API_START, JSMotionManager::setChangeListener, kJSPropertyAttributeNone },
+    { MOTION_API_STOP, JSMotionManager::unsetChangeListener, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSMotionManager::m_jsClassRef = JSClassCreate(JSMotionManager::getClassInfo());
+
+const JSClassRef JSMotionManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSMotionManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSMotionManager::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSMotionManager::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+JSValueRef JSMotionManager::getContextInfo(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    string contextType;
+
+    try {
+
+        AceSecurityStatus status = HUMANACTIVITYMONITOR_CHECK_ACCESS(MOTION_API_GET_CONTEXT_INFO);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        contextType = validator.toString(0);
+
+        if(!strcmp(MOTION_ENUM_TYPE_PEDOMETER,contextType.c_str())){
+            // successCallback
+            JSObjectRef successCB = validator.toFunction(1);
+            if (successCB) {
+                PedometerSuccessCallbackPtr pedometerGetCB(new PedometerSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+                pedometerGetCB->setSuccessCallback(successCB);
+
+                // errorCallback
+                JSObjectRef errCB = validator.toFunction(2, true);
+                if(errCB){
+                    pedometerGetCB->setErrorCallback(errCB);
+                }
+
+                // perform
+                MotionManager::getInstance()->getContextInfo(pedometerGetCB);
+
+            }else{
+                LOGE("argument type mismatch");
+                throw TypeMismatchException("argument type mismatch");
+            }
+
+        }else if(!strcmp(MOTION_ENUM_TYPE_WRIST_UP,contextType.c_str()) || !strcmp(MOTION_ENUM_TYPE_HRM,contextType.c_str())){
+            LOGE("Not supported");
+            throw NotSupportedException("Not supported");
+        }else{
+            LOGE("argument type mismatch");
+            throw TypeMismatchException("Type mismatch");
+        }
+
+        return JSValueMakeUndefined(context);
+
+    } catch (const TypeMismatchException &err) {
+        LOGE("Type Mismatch Exception");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const DeviceAPI::Common::BasePlatformException &err) {
+        LOGE("throw exception");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSMotionManager::setChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("enter");
+
+    try {
+        AceSecurityStatus status = HUMANACTIVITYMONITOR_CHECK_ACCESS(MOTION_API_START);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+        string contextType;
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(1, true);
+
+        contextType = validator.toString(0);
+
+        if(!strcmp(MOTION_ENUM_TYPE_PEDOMETER,contextType.c_str())){
+
+            PedometerSuccessCallbackPtr pedometerCB(new PedometerSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+            if (successCB) {
+                pedometerCB->setSuccessCallback(successCB);
+            }
+            MotionManager::getInstance()->setChangeListener(pedometerCB);
+
+        }else if(!strcmp(MOTION_ENUM_TYPE_WRIST_UP,contextType.c_str())){
+
+            WristUpSuccessCallbackPtr wristupCB(new WristUpSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+            if (successCB) {
+                wristupCB->setSuccessCallback(successCB);
+            }
+            MotionManager::getInstance()->setChangeListener(wristupCB);
+
+        }else if(!strcmp(MOTION_ENUM_TYPE_HRM,contextType.c_str())){
+
+            HRMSuccessCallbackPtr hrmCB(new HRMSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+            if (successCB) {
+                hrmCB->setSuccessCallback(successCB);
+            }
+            MotionManager::getInstance()->setChangeListener(hrmCB);
+
+        }else if(!strcmp(MOTION_ENUM_TYPE_GPS,contextType.c_str())){
+            AceSecurityStatus status = HUMANACTIVITYMONITOR_CHECK_ACCESS(MOTION_API_START);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+            GPSSuccessCallbackPtr gpsCB(new GPSSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+            if (successCB) {
+                gpsCB->setSuccessCallback(successCB);
+            }
+            MotionManager::getInstance()->setChangeListener(gpsCB);
+
+        }else{
+               throw TypeMismatchException("Type Mismatch");
+        }
+
+        return JSValueMakeUndefined(context);
+
+    } catch (const DeviceAPI::Common::BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+
+
+JSValueRef JSMotionManager::unsetChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("enter");
+
+    try {
+        AceSecurityStatus status = HUMANACTIVITYMONITOR_CHECK_ACCESS(MOTION_API_STOP);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+        string contextType;
+        ArgumentValidator validator(context, argumentCount, arguments);
+        contextType = validator.toString(0);
+
+
+        if(!strcmp(MOTION_ENUM_TYPE_PEDOMETER,contextType.c_str()) || !strcmp(MOTION_ENUM_TYPE_WRIST_UP,contextType.c_str())
+            || !strcmp(MOTION_ENUM_TYPE_HRM,contextType.c_str()) || !strcmp(MOTION_ENUM_TYPE_GPS,contextType.c_str())){
+            AceSecurityStatus status = HUMANACTIVITYMONITOR_CHECK_ACCESS(MOTION_API_START);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+            MotionManager::getInstance()->unsetChangeListener(GlobalContextManager::getInstance()->getGlobalContext(context), contextType.c_str());
+        }else{
+               throw TypeMismatchException("Type Mismatch");
+        }
+
+        return JSValueMakeUndefined(context);
+
+    } catch (const DeviceAPI::Common::BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+
+
+JSValueRef JSMotionManager::setAccumulativePedometerListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+
+    try {
+
+        AceSecurityStatus status = HUMANACTIVITYMONITOR_CHECK_ACCESS(MOTION_API_START);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        PedometerSuccessCallbackPtr pedometerCB(new PedometerSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            pedometerCB->setSuccessCallback(successCB);
+        }
+        MotionManager::getInstance()->setAccumulativePedometerListener(pedometerCB);
+
+        return JSValueMakeUndefined(context);
+
+    } catch (const DeviceAPI::Common::BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+
+}
+
+JSValueRef JSMotionManager::unsetAccumulativePedometerListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try {
+        AceSecurityStatus status = HUMANACTIVITYMONITOR_CHECK_ACCESS(MOTION_API_STOP);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        MotionManager::getInstance()->unsetAccumulativePedometerListener(GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        return JSValueMakeUndefined(context);
+
+    } catch (const DeviceAPI::Common::BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+
+}
+
+} // Context
+} // DeviceAPI
diff --git a/src/HumanActivityMonitor/JSMotionManager.h b/src/HumanActivityMonitor/JSMotionManager.h
new file mode 100755 (executable)
index 0000000..a3a64a8
--- /dev/null
@@ -0,0 +1,108 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_JS_PEDOMETER_MANAGER_H__
+#define __TIZEN_JS_PEDOMETER_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "MotionManager.h"
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+class JSMotionManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getContextInfo(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setAccumulativePedometerListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetAccumulativePedometerListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Context
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/HumanActivityMonitor/JSPedometerInfo.cpp b/src/HumanActivityMonitor/JSPedometerInfo.cpp
new file mode 100755 (executable)
index 0000000..435036b
--- /dev/null
@@ -0,0 +1,779 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#include <JSUtil.h>
+#include <CommonsJavaScript/Converter.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+#include "JSPedometerInfo.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+JSClassDefinition JSPedometerInfo::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "PedometerInfo",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSPedometerInfo::m_property[] = {
+    { TIZEN_PEDOMETER_INFO_STEP_STATUS, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_SPEED, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_WALKING_FREQUENCY, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_CUMULATIVE_DISTANCE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_CUMULATIVE_CALORIE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_CUMULATIVE_TOTAL_STEP_COUNT, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_CUMULATIVE_WALK_STEP_COUNT, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_CUMULATIVE_RUN_STEP_COUNT, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_STEP_COUNT_DIFFERENCES, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+
+
+JSClassRef JSPedometerInfo::m_jsClassRef = JSClassCreate(JSPedometerInfo::getClassInfo());
+
+const JSClassRef JSPedometerInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSPedometerInfo::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSPedometerInfo::createJSObject(JSContextRef context, PedometerInfo* pedometerInfo)
+{
+    pedometerInfo->m_jSStepDiffrence = JSPedometerInfo::StepDifferenceArraytoJSValueRef(context, pedometerInfo->getStepDifference(), pedometerInfo->getTimeStamp(), pedometerInfo->getTimeStampLength());
+
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(pedometerInfo));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    pedometerInfo->setContext(context);
+    JSValueProtect(context, pedometerInfo->m_jSStepDiffrence);
+
+    return jsValueRef;
+}
+
+JSValueRef JSPedometerInfo::StepDifferenceArraytoJSValueRef(JSContextRef context, int* stepDiff, int64_t* timeStamp, int timeStampLength)
+{
+    int index = 0;
+
+    JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
+    if (NULL == jsResult) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    for(index=0 ; index<timeStampLength ; index++){
+        StepDifferenceInfoPtr stepDiffInfo(new StepDifferenceInfo(stepDiff[index], timeStamp[index]));
+
+        JSValueRef jsObject = JSStepDifferenceInfo::createJSObject(context, stepDiffInfo);
+        if (!jsObject) {
+            throw UnknownException("object creation error");
+        }
+
+        if (!JSSetArrayElement(context, jsResult, index, jsObject)) {
+            throw UnknownException("object creation error");
+        }
+    }
+    return jsResult;
+
+}
+
+
+void JSPedometerInfo::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSPedometerInfo::finalize(JSObjectRef object)
+{
+    PedometerInfo* priv = static_cast<PedometerInfo*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSValueUnprotect(priv->getContext(), priv->m_jSStepDiffrence);
+        LOGD("js value unprotected");
+        delete priv;
+    }
+}
+
+JSValueRef JSPedometerInfo::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    PedometerInfo* priv = static_cast<PedometerInfo*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Private object is NULL");
+        throw TypeMismatchException("Private object is NULL");
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_STEP_STATUS)) {
+        std::string statusString("");
+        statusString.append(priv->getStepStatusString());
+        return JSUtil::toJSValueRef(context, statusString);
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_SPEED)) {
+        return JSUtil::toJSValueRef(context, priv->getSpeed());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_WALKING_FREQUENCY)) {
+        return JSUtil::toJSValueRef(context, priv->getWalkingFrequency());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_CUMULATIVE_DISTANCE)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeDistance());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_CUMULATIVE_CALORIE)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeCalorie());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_CUMULATIVE_TOTAL_STEP_COUNT)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeTotalStepCount());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_CUMULATIVE_WALK_STEP_COUNT)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeWalkStepCount());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_CUMULATIVE_RUN_STEP_COUNT)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeRunStepCount());
+    }else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_STEP_COUNT_DIFFERENCES)) {
+        return priv->m_jSStepDiffrence;
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+JSClassDefinition JSHRMInfo::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "HRMInfo",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSHRMInfo::m_property[] = {
+    { TIZEN_HRM_INFO_HEART_RATE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_HRM_INFO_RR_INTERVAL, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+
+
+JSClassRef JSHRMInfo::m_jsClassRef = JSClassCreate(JSHRMInfo::getClassInfo());
+
+const JSClassRef JSHRMInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSHRMInfo::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSHRMInfo::createJSObject(JSContextRef context, HRMInfo* hrmInfo)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(hrmInfo));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+    return jsValueRef;
+}
+
+
+void JSHRMInfo::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSHRMInfo::finalize(JSObjectRef object)
+{
+    HRMInfo* priv = static_cast<HRMInfo*>(JSObjectGetPrivate(object));
+    if (priv) {
+        delete priv;
+    }
+}
+
+JSValueRef JSHRMInfo::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    long value = 0;
+    HRMInfo* priv = static_cast<HRMInfo*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is NULL");
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_HRM_INFO_HEART_RATE)) {
+        value = (long)priv->getHeartRate();
+        return JSUtil::toJSValueRef(context, value);
+    } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_HRM_INFO_RR_INTERVAL)) {
+        value = (long)priv->getRRInterval();
+        return JSUtil::toJSValueRef(context, value);
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+
+JSClassDefinition JSAccumulativePedometerInfo::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "PedometerInfo",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSAccumulativePedometerInfo::m_property[] = {
+    { TIZEN_PEDOMETER_INFO_STEP_STATUS, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_SPEED, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_WALKING_FREQUENCY, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PEDOMETER_INFO_ACCUMULATIVE_DISTANCE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PEDOMETER_INFO_ACCUMULATIVE_CALORIE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PEDOMETER_INFO_ACCUMULATIVE_TOTAL_STEP_COUNT, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PEDOMETER_INFO_ACCUMULATIVE_WALK_STEP_COUNT, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { PEDOMETER_INFO_ACCUMULATIVE_RUN_STEP_COUNT, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_STEP_COUNT_DIFFERENCES, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSAccumulativePedometerInfo::m_jsClassRef = JSClassCreate(JSAccumulativePedometerInfo::getClassInfo());
+
+const JSClassRef JSAccumulativePedometerInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSAccumulativePedometerInfo::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSAccumulativePedometerInfo::createJSObject(JSContextRef context, PedometerInfo* pedometerInfo)
+{
+    pedometerInfo->m_jSStepDiffrence = JSPedometerInfo::StepDifferenceArraytoJSValueRef(context, pedometerInfo->getStepDifference(), pedometerInfo->getTimeStamp(), pedometerInfo->getTimeStampLength());
+
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(pedometerInfo));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    pedometerInfo->setContext(context);
+    JSValueProtect(context, pedometerInfo->m_jSStepDiffrence);
+
+    return jsValueRef;
+}
+
+
+JSValueRef JSAccumulativePedometerInfo::StepDifferenceArraytoJSValueRef(JSContextRef context, int* stepDiff, int64_t* timeStamp, int timeStampLength)
+{
+    int index = 0;
+
+    JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
+    if (NULL == jsResult) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    for(index=0 ; index<timeStampLength ; index++){
+        StepDifferenceInfoPtr stepDiffInfo(new StepDifferenceInfo(stepDiff[index], timeStamp[index]));
+
+        JSValueRef jsObject = JSStepDifferenceInfo::createJSObject(context, stepDiffInfo);
+        if (!jsObject) {
+            throw UnknownException("object creation error");
+        }
+
+        if (!JSSetArrayElement(context, jsResult, index, jsObject)) {
+            throw UnknownException("object creation error");
+        }
+    }
+    return jsResult;
+
+}
+
+void JSAccumulativePedometerInfo::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSAccumulativePedometerInfo::finalize(JSObjectRef object)
+{
+    PedometerInfo* priv = static_cast<PedometerInfo*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSValueUnprotect(priv->getContext(), priv->m_jSStepDiffrence);
+        LOGD("js value unprotected");
+        delete priv;
+    }
+}
+
+JSValueRef JSAccumulativePedometerInfo::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    PedometerInfo* priv = static_cast<PedometerInfo*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is NULL");
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_STEP_STATUS)) {
+        std::string statusString("");
+        statusString.append(priv->getStepStatusString());
+        return JSUtil::toJSValueRef(context, statusString);
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_SPEED)) {
+        return JSUtil::toJSValueRef(context, priv->getSpeed());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_WALKING_FREQUENCY)) {
+        return JSUtil::toJSValueRef(context, priv->getWalkingFrequency());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_ACCUMULATIVE_DISTANCE)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeDistance());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_ACCUMULATIVE_CALORIE)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeCalorie());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_ACCUMULATIVE_TOTAL_STEP_COUNT)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeTotalStepCount());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_ACCUMULATIVE_WALK_STEP_COUNT)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeWalkStepCount());
+    } else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_ACCUMULATIVE_RUN_STEP_COUNT)) {
+        return JSUtil::toJSValueRef(context, priv->getCumulativeRunStepCount());
+    }else if (JSStringIsEqualToUTF8CString(propertyName, PEDOMETER_INFO_STEP_COUNT_DIFFERENCES)) {
+        return priv->m_jSStepDiffrence;
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+GPSInfoArrayHolder::GPSInfoArrayHolder()
+{
+    LOGD("enter");
+}
+
+GPSInfoArrayHolder::~GPSInfoArrayHolder()
+{
+    LOGD("enter");
+    m_GPSInfoList.clear();
+}
+
+void GPSInfoArrayHolder::setContext(JSContextRef ctx)
+{
+    LOGD("enter");
+    m_JSContext = ctx;
+}
+
+JSContextRef GPSInfoArrayHolder::getContext()
+{
+    LOGD("enter");
+    return m_JSContext;
+}
+
+
+void GPSInfoArrayHolder::pushGPSInfo(double latitude, double longitude, double altitude, double speed,  double errorRange, int64_t timeStamp)
+{
+    LOGD("enter %f , %f , %f , %f , %f , %d", latitude, longitude, altitude, speed, errorRange, timeStamp);
+    GPInfoPtr gpsInfoPtr(new GPSInfo(latitude, longitude, altitude, speed, errorRange, timeStamp));
+    m_GPSInfoList.push_back(gpsInfoPtr);
+}
+
+JSClassDefinition JSGPSInfoArray::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "GPSInfoArray",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSGPSInfoArray::m_property[] = {
+    { TIZEN_GPS_INFO_GPS_INFO, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+
+
+JSClassRef JSGPSInfoArray::m_jsClassRef = JSClassCreate(JSGPSInfoArray::getClassInfo());
+
+const JSClassRef JSGPSInfoArray::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSGPSInfoArray::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSGPSInfoArray::createJSObject(JSContextRef context, double* latitude, double* longitude,  double* altitude, double* speed,  double* errorRange, int64_t* timeStamp, int totalCnt)
+{
+    GPSInfoArrayHolder* holder = new GPSInfoArrayHolder();
+    int index = 0;
+
+    for(index = 0 ; index<totalCnt ; index++){
+        if(errorRange != NULL){
+            holder->pushGPSInfo(latitude[index], longitude[index], altitude[index], speed[index], errorRange[index], timeStamp[index]);
+        }else{
+            LOGE("error range is null");
+            holder->pushGPSInfo(latitude[index], longitude[index], altitude[index], speed[index], 0, timeStamp[index]);
+        }
+    }
+    holder->m_JSGPSInfoArray = JSGPSInfoArray::gpsInfoArraytoJSValueRef(context, holder);
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(holder));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+    holder->setContext(context);
+    JSValueProtect(context, holder->m_JSGPSInfoArray);
+
+    LOGD("end");
+    return jsValueRef;
+}
+
+
+void JSGPSInfoArray::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSGPSInfoArray::finalize(JSObjectRef object)
+{
+    GPSInfoArrayHolder* priv = static_cast<GPSInfoArrayHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSValueUnprotect(priv->getContext(), priv->m_JSGPSInfoArray);
+        LOGD("js value unprotected");
+        delete priv;
+    }
+}
+
+JSValueRef JSGPSInfoArray::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    GPSInfoArrayHolder* priv = static_cast<GPSInfoArrayHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        return JSValueMakeUndefined(context);
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_GPS_INFO_GPS_INFO)) {
+        return priv->m_JSGPSInfoArray;
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSGPSInfoArray::gpsInfoArraytoJSValueRef(JSContextRef context, GPSInfoArrayHolder* holder)
+{
+
+    std::list<GPInfoPtr>::iterator iterList = holder->m_GPSInfoList.begin();
+    GPInfoPtr gpsInfo = NULL;
+    int index = 0;
+
+    JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
+    if (NULL == jsResult) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    while(iterList != holder->m_GPSInfoList.end()){
+        gpsInfo = *iterList;
+
+        JSValueRef jsObject = JSGPSInfo::createJSObject(context, gpsInfo);
+        if (!jsObject) {
+            throw UnknownException("object creation error");
+        }
+
+        if (!JSSetArrayElement(context, jsResult, index, jsObject)) {
+            throw UnknownException("object creation error");
+        }
+
+        index++;
+        iterList++;
+    }
+    return jsResult;
+
+}
+
+// GPSInforHolder
+GPSInfoHolder::GPSInfoHolder(GPInfoPtr gpsInfo)
+{
+    m_GPSInfo = gpsInfo;
+}
+
+GPSInfoHolder::~GPSInfoHolder()
+{
+
+}
+
+
+// GPS Info
+JSClassDefinition JSGPSInfo::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "GPSInfo",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSGPSInfo::m_property[] = {
+    { TIZEN_GPS_INFO_LATITUDE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_GPS_INFO_LONGITUDE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_GPS_INFO_ALTITUDE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_GPS_INFO_SPEED, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_GPS_INFO_ERROR_RANGE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_GPS_INFO_TIME_STAMP, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+
+
+JSClassRef JSGPSInfo::m_jsClassRef = JSClassCreate(JSGPSInfo::getClassInfo());
+
+const JSClassRef JSGPSInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSGPSInfo::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSGPSInfo::createJSObject(JSContextRef context, GPInfoPtr gpsInfo)
+{
+    GPSInfoHolder* gpsInforHolder = new GPSInfoHolder(gpsInfo);
+
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(gpsInforHolder));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+    return jsValueRef;
+}
+
+
+void JSGPSInfo::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSGPSInfo::finalize(JSObjectRef object)
+{
+    GPSInfoHolder* priv = static_cast<GPSInfoHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        delete priv;
+    }
+}
+
+JSValueRef JSGPSInfo::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    GPSInfoHolder* priv = static_cast<GPSInfoHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        return JSValueMakeUndefined(context);
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_GPS_INFO_LATITUDE)) {
+        return JSUtil::toJSValueRef(context, priv->m_GPSInfo->getLatitude());
+    }else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_GPS_INFO_LONGITUDE)) {
+        return JSUtil::toJSValueRef(context, priv->m_GPSInfo->getLongitude());
+    }else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_GPS_INFO_ALTITUDE)) {
+        return JSUtil::toJSValueRef(context, priv->m_GPSInfo->getAltitude());
+    }else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_GPS_INFO_SPEED)) {
+        return JSUtil::toJSValueRef(context, priv->m_GPSInfo->getSpeed());
+    }else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_GPS_INFO_ERROR_RANGE)) {
+        return JSUtil::toJSValueRef(context, priv->m_GPSInfo->getErrorRange());
+    }else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_GPS_INFO_TIME_STAMP)) {
+        return JSUtil::toJSValueRef(context, priv->m_GPSInfo->getTimeStamp());
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+StepDifferenceInfoHolder::StepDifferenceInfoHolder(StepDifferenceInfoPtr stepDifferenceInfo)
+{
+    LOGD("enter");
+
+    m_StepDifferenceInfo = stepDifferenceInfo;
+}
+
+StepDifferenceInfoHolder::~StepDifferenceInfoHolder()
+{
+
+}
+
+JSClassDefinition JSStepDifferenceInfo::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "JSStepDifferenceInfo",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSStepDifferenceInfo::m_property[] = {
+    { TIZEN_PEDOMETER_INFO_STEP_COUNT_DIFFERENCE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PEDOMETER_INFO_TIMESTAMP, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+
+
+JSClassRef JSStepDifferenceInfo::m_jsClassRef = JSClassCreate(JSStepDifferenceInfo::getClassInfo());
+
+const JSClassRef JSStepDifferenceInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSStepDifferenceInfo::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSStepDifferenceInfo::createJSObject(JSContextRef context, StepDifferenceInfoPtr stepDifferenceInfo)
+{
+    LOGD("enter");
+
+    StepDifferenceInfoHolder* stepDifferenceHolder = new StepDifferenceInfoHolder(stepDifferenceInfo);
+
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(stepDifferenceHolder));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+    LOGD("enter");
+    return jsValueRef;
+}
+
+
+void JSStepDifferenceInfo::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSStepDifferenceInfo::finalize(JSObjectRef object)
+{
+    StepDifferenceInfoHolder* priv = static_cast<StepDifferenceInfoHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        delete priv;
+    }
+}
+
+JSValueRef JSStepDifferenceInfo::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    long int stepDiff = 0;
+    StepDifferenceInfoHolder* priv = static_cast<StepDifferenceInfoHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        return JSValueMakeUndefined(context);
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PEDOMETER_INFO_STEP_COUNT_DIFFERENCE)) {
+        stepDiff = priv->m_StepDifferenceInfo->getStepDifference();
+        return JSUtil::toJSValueRef(context, stepDiff);
+    }else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PEDOMETER_INFO_TIMESTAMP)) {
+        return JSUtil::toJSValueRef(context, priv->m_StepDifferenceInfo->getTimeStamp());
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+} // Context
+} // DeviceAPI
diff --git a/src/HumanActivityMonitor/JSPedometerInfo.h b/src/HumanActivityMonitor/JSPedometerInfo.h
new file mode 100755 (executable)
index 0000000..ebe0c5b
--- /dev/null
@@ -0,0 +1,297 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_PEDOMETER_INFO_H__
+#define __TIZEN_JS_PEDOMETER_INFO_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <JSUtil.h>
+
+#include "PedometerInfo.h"
+#include "MotionManager.h"
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+class JSPedometerInfo
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, PedometerInfo* pedometerInfo);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    static JSValueRef StepDifferenceArraytoJSValueRef(JSContextRef context, int* stepDiff, int64_t* timeStamp, int timeStampLength);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+class JSHRMInfo
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, HRMInfo* hrmInfo);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+class JSAccumulativePedometerInfo
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, PedometerInfo* pedometerInfo);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    static JSValueRef StepDifferenceArraytoJSValueRef(JSContextRef context, int* stepDiff, int64_t* timeStamp, int timeStampLength);
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+class GPSInfoArrayHolder {
+public:
+    GPSInfoArrayHolder();
+    virtual ~GPSInfoArrayHolder();
+    void setContext(JSContextRef ctx);
+    JSContextRef getContext();
+    void pushGPSInfo(double latitude, double longitude, double altitude, double speed,  double errorRange, int64_t timeStamp);
+
+    std::list<GPInfoPtr> m_GPSInfoList;
+    JSValueRef m_JSGPSInfoArray;
+    JSContextRef m_JSContext;
+private:
+};
+
+class GPSInfoHolder {
+public:
+    GPSInfoHolder(GPInfoPtr gpsInfo);
+    virtual ~GPSInfoHolder();
+
+    GPInfoPtr m_GPSInfo;
+private:
+};
+
+
+
+class StepDifferenceInfoHolder {
+public:
+    StepDifferenceInfoHolder(StepDifferenceInfoPtr stepDifferenceInfo);
+    virtual ~StepDifferenceInfoHolder();
+
+    StepDifferenceInfoPtr m_StepDifferenceInfo;
+private:
+};
+
+
+class JSGPSInfoArray
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, double* latitude, double* longitude,  double* altitude, double* speed,  double* errorRange, int64_t* timeStamp, int totalCnt);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    static JSValueRef gpsInfoArraytoJSValueRef(JSContextRef context, GPSInfoArrayHolder* holder);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+class JSGPSInfo
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, GPInfoPtr gpsInfo);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+
+class JSStepDifferenceInfo
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, StepDifferenceInfoPtr stepDifferenceInfo);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+} // Context
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/HumanActivityMonitor/MotionManager.cpp b/src/HumanActivityMonitor/MotionManager.cpp
new file mode 100755 (executable)
index 0000000..ac93fc7
--- /dev/null
@@ -0,0 +1,943 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <map>
+#include <glib.h>
+
+#include <gesture_recognition.h>
+#include <JSWebAPIErrorFactory.h>
+#include <system_info.h>
+
+#include "GlobalContextManager.h"
+#include "MotionManager.h"
+#include "PedometerInfo.h"
+#include "JSPedometerInfo.h"
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+MotionManager* MotionManager::getInstance(){
+    static MotionManager instance;
+    return &instance;
+}
+
+MotionManager::MotionManager()
+{
+    LOGD("*## enter ##*");
+
+    int ret =  0;
+    double dData = 0.0;
+
+    mHRMHandle = 0;
+
+    mPedometerB = false;
+    mWristUpB = false;
+    mHRMB = false;
+    mGPSB = false;
+
+    ret = system_info_get_platform_bool(TIZEN_PLATFORM_FEATURE_PEDOMETER, &mPedometerB);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        LOGE("system info unknown error : %d", ret);
+        throw UnknownException("system info unknown error");
+    }
+
+    ret = system_info_get_platform_bool(TIZEN_PLATFORM_FEATURE_HRM, &mHRMB);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        LOGE("system info unknown error : %d", ret);
+        throw UnknownException("system info unknown error");
+    }
+
+    ret = gesture_is_supported(GESTURE_WRIST_UP , &mWristUpB);
+    if(ret != GESTURE_ERROR_NONE){
+        LOGE("gesture unknown error : %d ", ret);
+    }
+
+    LOGD("enter %d , %d , %d , %d", mPedometerB , mWristUpB, mHRMB , mGPSB);
+
+
+    mBaseInit = false;
+    mBasePedometerInfo = new PedometerInfo();
+    if(mBasePedometerInfo == NULL){
+        LOGE("base pedometer memory allocation failed");
+    }else{
+        mBasePedometerInfo->setStepStatus(0);
+        mBasePedometerInfo->setSpeed(dData);
+        mBasePedometerInfo->setWalkingFrequency(dData);
+        mBasePedometerInfo->setCumulativeDistance(dData);
+        mBasePedometerInfo->setCumulativeCalorie(dData);
+        mBasePedometerInfo->setCumulativeTotalStepCount(dData);
+        mBasePedometerInfo->setCumulativeWalkStepCount(dData);
+        mBasePedometerInfo->setCumulativeRunStepCount(dData);
+    }
+
+    LOGD("end");
+
+}
+
+MotionManager::~MotionManager()
+{
+    LOGD("enter");
+    if(mBasePedometerInfo != NULL){
+        delete mBasePedometerInfo;
+    }
+    LOGD("end");
+}
+
+gboolean MotionManager::callPedometerSuccessCallback(void* data)
+{
+    LOGD("enter");
+    PedometerSuccessCallbackHolder* holder = static_cast<PedometerSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback(holder->mJSPedometerInfo);
+    JSValueUnprotect(holder->ptr->getContext(), holder->mJSPedometerInfo);
+    delete holder;
+    return false;
+}
+
+gboolean MotionManager::callWristUpSuccessCallback(void* data)
+{
+    LOGD("enter");
+    WristUpSuccessCallbackHolder* holder = static_cast<WristUpSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback(JSValueMakeNull(holder->ptr->getContext()));
+    delete holder;
+    return false;
+}
+
+gboolean MotionManager::callHRMSuccessCallback(void* data)
+{
+    LOGD("enter");
+    HRMSuccessCallbackHolder* holder = static_cast<HRMSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback(holder->mJSHRMInfo);
+    JSValueUnprotect(holder->ptr->getContext(), holder->mJSHRMInfo);
+    delete holder;
+    return false;
+}
+
+gboolean MotionManager::callGPSSuccessCallback(void* data)
+{
+    LOGD("enter");
+    GPSSuccessCallbackHolder* holder = static_cast<GPSSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback(holder->mJSGPSArray);
+    JSValueUnprotect(holder->ptr->getContext(), holder->mJSGPSArray);
+    delete holder;
+    return false;
+}
+
+
+void MotionManager::broadcast_wristup_info()
+{
+    guint bGIdleRet = 0;
+    WristUpSuccessCallbackHolder* holder = NULL;
+    std::map<JSContextRef, WristUpSuccessCallbackPtr>::iterator iter;
+
+    for(iter = mWristupCallbackMap.begin() ; iter != mWristupCallbackMap.end() ; ++iter){
+        holder = new WristUpSuccessCallbackHolder();
+        holder->ptr = iter->second;
+        bGIdleRet = g_idle_add(callWristUpSuccessCallback, holder);
+        if (!bGIdleRet) {
+            LOGE("g_idle_add fails");
+        }
+    }
+
+}
+
+void MotionManager::broadcast_hrm_info(int heartRate, int rrInterval)
+{
+    guint bGIdleRet = 0;
+    HRMInfo* hrmInfo = NULL;
+    HRMSuccessCallbackHolder* holder = NULL;
+    std::map<JSContextRef, HRMSuccessCallbackPtr>::iterator iter;
+    int total = mHRMCallbackMap.size();
+
+    if(total <= 0){
+        return;
+    }
+
+    for(iter = mHRMCallbackMap.begin() ; iter != mHRMCallbackMap.end() ; ++iter){
+        hrmInfo = new HRMInfo(heartRate, rrInterval);
+        holder = new HRMSuccessCallbackHolder();
+        if((hrmInfo == NULL) || (holder == NULL)){
+            return;
+        }
+
+        holder->ptr = iter->second;
+        holder->mJSHRMInfo = JSHRMInfo::createJSObject(holder->ptr->getContext(), hrmInfo);
+        JSValueProtect(holder->ptr->getContext(), holder->mJSHRMInfo);
+        bGIdleRet = g_idle_add(callHRMSuccessCallback, holder);
+        if (!bGIdleRet) {
+            LOGE("g_idle_add fails");
+        }
+    }
+
+}
+
+void MotionManager::broadcast_gps_info(double* latitude, double* longitude, double* altitude, double* speed, double* errorRange, int64_t* timeStamp, int totalCnt)
+{
+    guint bGIdleRet = 0;
+    GPSSuccessCallbackHolder* holder = NULL;
+    std::map<JSContextRef, GPSSuccessCallbackPtr>::iterator iter;
+    int total = mGPSCallbackMap.size();
+
+    if(total <= 0){
+        return;
+    }
+
+    for(iter = mGPSCallbackMap.begin() ; iter != mGPSCallbackMap.end() ; ++iter){
+
+        holder = new GPSSuccessCallbackHolder();
+        if(holder == NULL){
+            return;
+        }
+
+        holder->ptr = iter->second;
+        holder->mJSGPSArray= JSGPSInfoArray::createJSObject(holder->ptr->getContext(), latitude, longitude, altitude, speed,  errorRange, timeStamp, totalCnt);
+        JSValueProtect(holder->ptr->getContext(), holder->mJSGPSArray);
+
+        bGIdleRet = g_idle_add(callGPSSuccessCallback, holder);
+        if (!bGIdleRet) {
+            LOGE("g_idle_add fails");
+        }
+    }
+
+}
+
+
+
+void MotionManager::broadcast_pedometer_info(PedometerInfo* curPedometerInfo)
+{
+    bool bInit = false;
+    double dValue = 0.0;
+    guint bGIdleRet = 0;
+    int stepStatus = 0;
+    PedometerInfo* pedometerInfo = NULL;
+    PedometerInfo* basePedometerInfo = NULL;
+    PedometerSuccessCallbackHolder* holder = NULL;
+    std::map<JSContextRef, PedometerSuccessCallbackPtr>::iterator iter;
+
+    if(mBaseInit == false){
+        mBasePedometerInfo->setCumulativeDistance(curPedometerInfo->getCumulativeDistance());
+        mBasePedometerInfo->setCumulativeCalorie(curPedometerInfo->getCumulativeCalorie());
+        mBasePedometerInfo->setCumulativeTotalStepCount(curPedometerInfo->getCumulativeTotalStepCount());
+        mBasePedometerInfo->setCumulativeWalkStepCount(curPedometerInfo->getCumulativeWalkStepCount());
+        mBasePedometerInfo->setCumulativeRunStepCount(curPedometerInfo->getCumulativeRunStepCount());
+        mBaseInit = true;
+    }
+
+    if(NULL == curPedometerInfo){
+        LOGE("enter");
+        return;
+    }
+
+
+    for(iter = mPedometerCallbackMap.begin() ; iter != mPedometerCallbackMap.end() ; ++iter){
+
+        PedometerSuccessCallbackPtr callback = iter->second;
+        bInit = callback->getPedometerInit();
+        basePedometerInfo = callback->getPedometerInfo();
+
+        if(bInit == false){
+            basePedometerInfo->setCumulativeDistance(curPedometerInfo->getCumulativeDistance());
+            basePedometerInfo->setCumulativeCalorie(curPedometerInfo->getCumulativeCalorie());
+            basePedometerInfo->setCumulativeTotalStepCount(curPedometerInfo->getCumulativeTotalStepCount());
+            basePedometerInfo->setCumulativeWalkStepCount(curPedometerInfo->getCumulativeWalkStepCount());
+            basePedometerInfo->setCumulativeRunStepCount(curPedometerInfo->getCumulativeRunStepCount());
+            callback->setPedometerInit(true);
+            LOGD("base pedometer init");
+            return;
+        }
+
+        pedometerInfo = new PedometerInfo();
+        if(pedometerInfo == NULL){
+            LOGE("PedometerInfo memory allocation fail");
+            return;
+        }
+
+        pedometerInfo->setStepStatus(curPedometerInfo->getStepStatus());
+        pedometerInfo->setSpeed(curPedometerInfo->getSpeed());
+        pedometerInfo->setWalkingFrequency(curPedometerInfo->getWalkingFrequency());
+
+        dValue = curPedometerInfo->getCumulativeDistance() - basePedometerInfo->getCumulativeDistance();
+        pedometerInfo->setCumulativeDistance(pedometerInfo->convertSimpleDouble(dValue));
+
+        dValue = curPedometerInfo->getCumulativeCalorie() - basePedometerInfo->getCumulativeCalorie();
+        pedometerInfo->setCumulativeCalorie(pedometerInfo->convertSimpleDouble(dValue));
+
+        dValue = curPedometerInfo->getCumulativeTotalStepCount() - basePedometerInfo->getCumulativeTotalStepCount();
+        pedometerInfo->setCumulativeTotalStepCount(pedometerInfo->convertSimpleDouble(dValue));
+
+        dValue = curPedometerInfo->getCumulativeWalkStepCount() - basePedometerInfo->getCumulativeWalkStepCount();
+        pedometerInfo->setCumulativeWalkStepCount(pedometerInfo->convertSimpleDouble(dValue));
+
+        dValue = curPedometerInfo->getCumulativeRunStepCount() - basePedometerInfo->getCumulativeRunStepCount();
+        pedometerInfo->setCumulativeRunStepCount(pedometerInfo->convertSimpleDouble(dValue));
+
+        // For step diffrence
+        pedometerInfo->setStepDifference(curPedometerInfo->getStepDifference());
+        pedometerInfo->setTimeStamp(curPedometerInfo->getTimeStamp());
+        pedometerInfo->setTimeStampLength(curPedometerInfo->getTimeStampLength());
+
+        holder = new PedometerSuccessCallbackHolder();
+        holder->ptr = callback;
+        holder->mJSPedometerInfo = JSPedometerInfo::createJSObject(callback->getContext(), pedometerInfo);
+        JSValueProtect(callback->getContext(), holder->mJSPedometerInfo);
+        bGIdleRet = g_idle_add(callPedometerSuccessCallback, holder);
+        if (!bGIdleRet) {
+            LOGE("g_idle_add fails");
+        }
+
+    }
+
+    for(iter = mAccumulatviePedometerCallbackMap.begin() ; iter != mAccumulatviePedometerCallbackMap.end() ; ++iter){
+
+        PedometerSuccessCallbackPtr callback = iter->second;
+
+        pedometerInfo = new PedometerInfo();
+        if(pedometerInfo == NULL){
+            LOGE("PedometerInfo memory allocation fail");
+            return;
+        }
+
+        pedometerInfo->setStepStatus(curPedometerInfo->getStepStatus());
+        pedometerInfo->setSpeed(curPedometerInfo->getSpeed());
+        pedometerInfo->setWalkingFrequency(curPedometerInfo->getWalkingFrequency());
+
+        pedometerInfo->setCumulativeDistance(pedometerInfo->convertSimpleDouble(curPedometerInfo->getCumulativeDistance()));
+        pedometerInfo->setCumulativeCalorie(pedometerInfo->convertSimpleDouble( curPedometerInfo->getCumulativeCalorie()));
+        pedometerInfo->setCumulativeTotalStepCount(pedometerInfo->convertSimpleDouble(curPedometerInfo->getCumulativeTotalStepCount()));
+        pedometerInfo->setCumulativeWalkStepCount(pedometerInfo->convertSimpleDouble(curPedometerInfo->getCumulativeWalkStepCount()));
+        pedometerInfo->setCumulativeRunStepCount(pedometerInfo->convertSimpleDouble(curPedometerInfo->getCumulativeRunStepCount()));
+
+
+        // For step diffrence
+        pedometerInfo->setStepDifference(curPedometerInfo->getStepDifference());
+        pedometerInfo->setTimeStamp(curPedometerInfo->getTimeStamp());
+        pedometerInfo->setTimeStampLength(curPedometerInfo->getTimeStampLength());
+
+        holder = new PedometerSuccessCallbackHolder();
+        holder->ptr = callback;
+        holder->mJSPedometerInfo = JSAccumulativePedometerInfo::createJSObject(callback->getContext(), pedometerInfo);
+        JSValueProtect(callback->getContext(), holder->mJSPedometerInfo);
+        bGIdleRet = g_idle_add(callPedometerSuccessCallback, holder);
+        if (!bGIdleRet) {
+            LOGE("g_idle_add fails");
+        }
+
+    }
+
+
+    if(curPedometerInfo != NULL){
+        if(curPedometerInfo->getStepDifference()){
+            free(curPedometerInfo->getStepDifference());
+            curPedometerInfo->setStepDifference(NULL);
+        }
+
+        if(curPedometerInfo->getTimeStamp()){
+            free(curPedometerInfo->getTimeStamp());
+            curPedometerInfo->setTimeStamp(NULL);
+        }
+
+        delete curPedometerInfo;
+        curPedometerInfo = NULL;
+    }
+
+    LOGD("end");
+}
+
+
+void MotionManager::broadcast_get_pedometer_info(PedometerInfo* curPedometerInfo)
+{
+    bool bInit = false;
+    double dValue = 0.0;
+    guint bGIdleRet = 0;
+    int stepStatus = 0;
+    PedometerInfo* pedometerInfo = NULL;
+    PedometerInfo* basePedometerInfo = NULL;
+    PedometerSuccessCallbackHolder* holder = NULL;
+    PedometerSuccessCallbackPtr callback = NULL;
+    PedometerSuccessCallbackPtr startCallback = NULL;
+    std::map<JSContextRef, PedometerSuccessCallbackPtr>::iterator iter;
+    std::list<PedometerSuccessCallbackPtr>::iterator iterList = mPedometerGetCallbackList.begin();
+
+    LOGD("enter");
+
+    if(curPedometerInfo == NULL){
+        LOGE("enter");
+        return;
+
+    }
+
+    while(iterList != mPedometerGetCallbackList.end()){
+        callback = *iterList;
+
+        iter = mPedometerCallbackMap.find(callback->getContext());
+        if(iter != mPedometerCallbackMap.end()){
+            startCallback = iter->second;
+            bInit = startCallback->getPedometerInit();
+            basePedometerInfo = startCallback->getPedometerInfo();
+
+            if(bInit == false){
+                basePedometerInfo->setCumulativeDistance(curPedometerInfo->getCumulativeDistance());
+                basePedometerInfo->setCumulativeCalorie(curPedometerInfo->getCumulativeCalorie());
+                basePedometerInfo->setCumulativeTotalStepCount(curPedometerInfo->getCumulativeTotalStepCount());
+                basePedometerInfo->setCumulativeWalkStepCount(curPedometerInfo->getCumulativeWalkStepCount());
+                basePedometerInfo->setCumulativeRunStepCount(curPedometerInfo->getCumulativeRunStepCount());
+                callback->setPedometerInit(true);
+            }
+
+            pedometerInfo = new PedometerInfo();
+            if(pedometerInfo == NULL){
+                LOGD("PedometerInfo memory allocation fail");
+                return;
+            }
+
+            pedometerInfo->setStepStatus(curPedometerInfo->getStepStatus());
+            pedometerInfo->setSpeed(curPedometerInfo->getSpeed());
+            pedometerInfo->setWalkingFrequency(curPedometerInfo->getWalkingFrequency());
+
+            dValue = curPedometerInfo->getCumulativeDistance() - basePedometerInfo->getCumulativeDistance();
+            pedometerInfo->setCumulativeDistance(pedometerInfo->convertSimpleDouble(dValue));
+
+            dValue = curPedometerInfo->getCumulativeCalorie() - basePedometerInfo->getCumulativeCalorie();
+            pedometerInfo->setCumulativeCalorie(pedometerInfo->convertSimpleDouble(dValue));
+
+            dValue = curPedometerInfo->getCumulativeTotalStepCount() - basePedometerInfo->getCumulativeTotalStepCount();
+            pedometerInfo->setCumulativeTotalStepCount(pedometerInfo->convertSimpleDouble(dValue));
+            //LOGD("Total Step "<<dValue);
+
+            dValue = curPedometerInfo->getCumulativeWalkStepCount() - basePedometerInfo->getCumulativeWalkStepCount();
+            pedometerInfo->setCumulativeWalkStepCount(pedometerInfo->convertSimpleDouble(dValue));
+
+            dValue = curPedometerInfo->getCumulativeRunStepCount() - basePedometerInfo->getCumulativeRunStepCount();
+            pedometerInfo->setCumulativeRunStepCount(pedometerInfo->convertSimpleDouble(dValue));
+
+            // For step diffrence
+            pedometerInfo->setStepDifference(curPedometerInfo->getStepDifference());
+            pedometerInfo->setTimeStamp(curPedometerInfo->getTimeStamp());
+            pedometerInfo->setTimeStampLength(curPedometerInfo->getTimeStampLength());
+
+
+            holder = new PedometerSuccessCallbackHolder();
+            holder->ptr = callback;
+            holder->mJSPedometerInfo = JSPedometerInfo::createJSObject(callback->getContext(), pedometerInfo);
+            JSValueProtect(callback->getContext(), holder->mJSPedometerInfo);
+            bGIdleRet = g_idle_add(callPedometerSuccessCallback, holder);
+            if (!bGIdleRet) {
+                LOGD("g_idle_add fails");
+            }
+
+        }
+        ++iterList;
+    }
+
+    mPedometerGetCallbackList.clear();
+
+    if(curPedometerInfo != NULL){
+        if(curPedometerInfo->getStepDifference()){
+            free(curPedometerInfo->getStepDifference());
+            curPedometerInfo->setStepDifference(NULL);
+        }
+
+        if(curPedometerInfo->getTimeStamp()){
+            free(curPedometerInfo->getTimeStamp());
+            curPedometerInfo->setTimeStamp(NULL);
+        }
+        delete curPedometerInfo;
+        curPedometerInfo = NULL;
+    }
+
+    LOGD("enter");
+
+}
+
+void MotionManager::hrm_changed_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data)
+{
+    MotionManager* contextManager = static_cast<MotionManager*>(user_data);
+    if(contextManager ==  NULL){
+        LOGE("context manager null");
+        return;
+    }
+
+    contextManager->broadcast_hrm_info(data->values[0] , data->values[2]);
+}
+
+void MotionManager::wrist_up_changed_cb(void* user_data)
+{
+    MotionManager* contextManager = NULL;
+    contextManager = static_cast<MotionManager*>(user_data);
+    if(contextManager ==  NULL){
+        LOGE("context manager null");
+        return;
+    }
+
+    contextManager->broadcast_wristup_info();
+}
+
+void MotionManager::gps_changed_cb(int num_of_location, void *user_data)
+{
+    LOGD("enter");
+    int ret = 0;
+    MotionManager* contextManager = NULL;
+    double *latitude = NULL, *longitude = NULL, *altitude = NULL, *speed = NULL, *errorRange = NULL;
+    int64_t* timeStamp = NULL;
+
+    contextManager = static_cast<MotionManager*>(user_data);
+    if(contextManager ==  NULL){
+        LOGE("context manager null");
+        return;
+    }
+
+    contextManager->broadcast_gps_info(latitude, longitude, altitude, speed, errorRange, timeStamp, num_of_location);
+    LOGD("end %d", num_of_location);
+}
+
+
+void MotionManager::pedometer_changed_cb(void* user_data)
+{
+    LOGD("enter");
+
+    double dData = 0.0;
+    int* stepDiff = NULL;
+    int arrayLength = 0;
+    int64_t* timeStamp = NULL;
+    int status = 0;
+    PedometerInfo* pedometerInfo = NULL;
+
+    MotionManager* contextManager = static_cast<MotionManager*>(user_data);
+    if(contextManager ==  NULL){
+        LOGE("context manager null");
+        return;
+    }
+
+    pedometerInfo = new PedometerInfo();
+    if(pedometerInfo == NULL){
+        LOGE("PedometerInfo memory allocation fail");
+        return;
+    }
+
+    pedometerInfo->setStepStatus(status);
+    pedometerInfo->setSpeed(dData);
+    pedometerInfo->setWalkingFrequency(dData);
+    pedometerInfo->setCumulativeDistance(dData);
+    pedometerInfo->setCumulativeCalorie(dData);
+    pedometerInfo->setCumulativeTotalStepCount(dData);
+    pedometerInfo->setCumulativeWalkStepCount(dData);
+    pedometerInfo->setCumulativeRunStepCount(dData);
+    pedometerInfo->setStepDifference(stepDiff);
+    pedometerInfo->setTimeStamp(timeStamp);
+    pedometerInfo->setTimeStampLength(arrayLength);
+
+    contextManager->broadcast_pedometer_info(pedometerInfo);
+}
+
+
+void MotionManager::pedometer_get_info_cb(void* user_data)
+{
+    LOGD("enter");
+
+    int* stepDiff = NULL;
+    int arrayLength = 0;
+    int64_t* timeStamp = NULL;
+    double dData = 0.0;
+    PedometerInfo* pedometerInfo = NULL;
+
+
+    MotionManager* contextManager = static_cast<MotionManager*>(user_data);
+    if(contextManager ==  NULL){
+        LOGE("context manager null");
+        return;
+    }
+
+    pedometerInfo = new PedometerInfo();
+    if(pedometerInfo == NULL){
+        LOGE("PedometerInfo memory allocation fail");
+        return;
+    }
+
+    pedometerInfo->setStepStatus(0);
+    pedometerInfo->setSpeed(dData);
+    pedometerInfo->setWalkingFrequency(dData);
+    pedometerInfo->setCumulativeDistance(dData);
+    pedometerInfo->setCumulativeCalorie(dData);
+    pedometerInfo->setCumulativeTotalStepCount(dData);
+    pedometerInfo->setCumulativeWalkStepCount(dData);
+    pedometerInfo->setCumulativeRunStepCount(dData);
+    pedometerInfo->setStepDifference(stepDiff);
+    pedometerInfo->setTimeStamp(timeStamp);
+    pedometerInfo->setTimeStampLength(arrayLength);
+
+    contextManager->broadcast_get_pedometer_info(pedometerInfo);
+
+}
+
+
+void MotionManager::getContextInfo(PedometerSuccessCallbackPtr callback)
+{
+
+    int ret = 0;
+    std::map<JSContextRef, PedometerSuccessCallbackPtr>::iterator iter;
+
+    LOGD("enter");
+
+    if(mPedometerB == false){
+        LOGE("pedometer not supported");
+        throw NotSupportedException("pedometer not supported");
+    }
+
+    if(callback == NULL){
+        LOGE("callback function is null");
+        throw InvalidValuesException("callback function is null");
+    }
+
+    iter = mPedometerCallbackMap.find(callback->getContext());
+    if(iter == mPedometerCallbackMap.end()){
+        LOGE("Not yet start");
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "service not available");
+        callback->callErrorCallback(error);
+        return;
+    }
+
+    mPedometerGetCallbackList.push_back(callback);
+    LOGD("end");
+
+}
+
+
+void MotionManager::setChangeListener(PedometerSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    std::map<JSContextRef, PedometerSuccessCallbackPtr>::iterator iter;
+
+    if(mPedometerB == false){
+        LOGE("pedometer not supported");
+        throw NotSupportedException("pedometer not supported");
+    }
+
+    iter = mPedometerCallbackMap.find(callback->getContext());
+    if(iter != mPedometerCallbackMap.end()){
+        mPedometerCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+
+    mPedometerCallbackMap[callback->getContext()] = callback;
+    LOGD("pedometer start");
+
+}
+
+
+
+void MotionManager::setChangeListener(WristUpSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    std::map<JSContextRef, WristUpSuccessCallbackPtr>::iterator iter;
+
+    if(mWristUpB == false){
+        LOGE("wrist up not supported");
+        throw NotSupportedException("wrist up not supported");
+    }
+
+    iter = mWristupCallbackMap.find(callback->getContext());
+    if(iter != mWristupCallbackMap.end()){
+        mWristupCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+    mWristupCallbackMap[callback->getContext()] = callback;
+    LOGD("wrist up  start");
+
+}
+
+void MotionManager::setChangeListener(HRMSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret =  0;
+    int total = mHRMCallbackMap.size();
+    std::map<JSContextRef, HRMSuccessCallbackPtr>::iterator iter;
+
+    if(mHRMB == false){
+        LOGE("hrm not supported");
+        throw NotSupportedException("hrm not supported");
+    }
+
+    if(total <= 0){
+        LOGD("HRM callback register");
+        sensor_t accel_sensor;
+        accel_sensor = sensord_get_sensor(BIO_HRM_SENSOR);
+        mHRMHandle = sensord_connect(accel_sensor);
+        bool ret = sensord_register_event(mHRMHandle, BIO_HRM_EVENT_CHANGE_STATE, 100, 0, MotionManager::hrm_changed_cb , this);
+        LOGE("register ret : %d", ret);
+        ret = sensord_start(mHRMHandle, SENSOR_OPTION_ALWAYS_ON);
+        LOGE("start ret : %d", ret);
+    }
+
+    iter = mHRMCallbackMap.find(callback->getContext());
+    if(iter != mHRMCallbackMap.end()){
+        mHRMCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+    mHRMCallbackMap[callback->getContext()] = callback;
+    LOGD("hrm  start");
+
+
+}
+
+
+void MotionManager::setChangeListener(GPSSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret =  0;
+    int total = mGPSCallbackMap.size();
+    std::map<JSContextRef, GPSSuccessCallbackPtr>::iterator iter;
+
+    if(mGPSB == false){
+        LOGE("gps not supported");
+        throw NotSupportedException("gps not supported");
+    }
+
+    iter = mGPSCallbackMap.find(callback->getContext());
+    if(iter != mGPSCallbackMap.end()){
+        mGPSCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+    mGPSCallbackMap[callback->getContext()] = callback;
+    LOGD("gps start");
+
+}
+
+
+void MotionManager::unsetChangeListener(JSContextRef globalCtx, const char* type)
+{
+    int total = 0;
+    int ret = 0;
+
+    LOGD("enter");
+
+    if(!strcmp(MOTION_ENUM_TYPE_PEDOMETER, type)){
+        if(mPedometerB == false){
+            LOGE("pedometer not supported");
+            throw NotSupportedException("pedometer not supported");
+        }
+        mPedometerCallbackMap.erase(globalCtx);
+    }else if(!strcmp(MOTION_ENUM_TYPE_WRIST_UP, type)){
+        if(mWristUpB == false){
+            LOGE("wrist up not supported");
+            throw NotSupportedException("wrist up not supported");
+        }
+        mWristupCallbackMap.erase(globalCtx);
+    }else if(!strcmp(MOTION_ENUM_TYPE_HRM, type)){
+        if(mHRMB == false){
+            LOGE("hrm not supported");
+            throw NotSupportedException("hrm not supported");
+        }
+        mHRMCallbackMap.erase(globalCtx);
+
+        total = mHRMCallbackMap.size();
+        if(total <= 0){
+            bool ret = sensord_unregister_event(mHRMHandle, BIO_HRM_EVENT_CHANGE_STATE);
+            LOGE("unregister ret : %d", ret);
+            ret = sensord_stop(mHRMHandle);
+            LOGE("stop ret : %d", ret);
+            ret = sensord_disconnect(mHRMHandle);
+            LOGE("disconnect ret : %d", ret);
+            mHRMHandle = 0;
+        }
+    }else if(!strcmp(MOTION_ENUM_TYPE_GPS, type)){
+        if(mGPSB == false){
+            LOGE("gps not supported");
+            throw NotSupportedException("gps not supported");
+        }
+        mGPSCallbackMap.erase(globalCtx);
+    }else{
+        LOGE("Type Mismatch : %d", type);
+        throw TypeMismatchException("Type Mismatch");
+    }
+
+}
+
+
+void MotionManager::setAccumulativePedometerListener(PedometerSuccessCallbackPtr callback)
+{
+    std::map<JSContextRef, PedometerSuccessCallbackPtr>::iterator iter;
+
+    LOGD("enter");
+    if(mPedometerB == false){
+        LOGE("pedometer not supported");
+        throw NotSupportedException("pedometer not supported");
+    }
+
+    iter = mAccumulatviePedometerCallbackMap.find(callback->getContext());
+    if(iter != mAccumulatviePedometerCallbackMap.end()){
+        mAccumulatviePedometerCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+
+    mAccumulatviePedometerCallbackMap[callback->getContext()] = callback;
+    LOGD("pedometer start");
+
+}
+
+
+void MotionManager::unsetAccumulativePedometerListener(JSContextRef globalCtx)
+{
+    LOGD("enter");
+
+    if(mPedometerB == false){
+        LOGE("pedometer not supported");
+        throw NotSupportedException("pedometer not supported");
+    }
+    mAccumulatviePedometerCallbackMap.erase(globalCtx);
+}
+
+
+void MotionManager::removeCallback(JSContextRef globalCtx)
+{
+    LOGD("enter");
+    mPedometerCallbackMap.erase(globalCtx);
+    mWristupCallbackMap.erase(globalCtx);
+    mHRMCallbackMap.erase(globalCtx);
+    mAccumulatviePedometerCallbackMap.erase(globalCtx);
+    mGPSCallbackMap.erase(globalCtx);
+
+    LOGD("end : %p [ %d , %d , %d , %d , %d , %d ] ", globalCtx,
+            mPedometerCallbackMap.size(), mWristupCallbackMap.size(), mHRMCallbackMap.size(),
+            mAccumulatviePedometerCallbackMap.size(), mGPSCallbackMap.size(), mPedometerGetCallbackList.size());
+
+}
+
+
+PedometerSuccessCallback::PedometerSuccessCallback(JSContextRef globalCtx)
+    :CallbackUserData(globalCtx)
+{
+    double dData = 0.0;
+    int status = 0;
+
+    mPedometerInit = false;
+
+    mPedometerInfo = new PedometerInfo();
+    mPedometerInfo->setStepStatus(status);
+    mPedometerInfo->setSpeed(dData);
+    mPedometerInfo->setWalkingFrequency(dData);
+    mPedometerInfo->setCumulativeDistance(dData);
+    mPedometerInfo->setCumulativeCalorie(dData);
+    mPedometerInfo->setCumulativeTotalStepCount(dData);
+    mPedometerInfo->setCumulativeWalkStepCount(dData);
+    mPedometerInfo->setCumulativeRunStepCount(dData);
+}
+
+PedometerSuccessCallback::~PedometerSuccessCallback()
+{
+    LOGD("enter");
+    if(mPedometerInfo != NULL){
+        delete mPedometerInfo;
+    }
+
+}
+
+
+void PedometerSuccessCallback::setPedometerInit(const bool init)
+{
+    mPedometerInit = init;
+}
+
+bool PedometerSuccessCallback::getPedometerInit() const
+{
+    return mPedometerInit;
+}
+
+
+void PedometerSuccessCallback::setPedometerInfo(PedometerInfo* pedometerInfo)
+{
+    if(pedometerInfo == NULL){
+        return;
+    }
+
+    if(mPedometerInfo != NULL){
+        delete mPedometerInfo;
+    }
+
+    mPedometerInfo = pedometerInfo;
+}
+
+void PedometerSuccessCallback::copyPedometerInfo(PedometerInfo* pedometerInfo)
+{
+    if(pedometerInfo == NULL){
+        return;
+    }
+
+    if(mPedometerInfo != NULL){
+        delete mPedometerInfo;
+    }
+
+    mPedometerInfo = new PedometerInfo();
+    mPedometerInfo->setStepStatus(pedometerInfo->getStepStatus());
+    mPedometerInfo->setSpeed(pedometerInfo->getSpeed());
+    mPedometerInfo->setWalkingFrequency(pedometerInfo->getWalkingFrequency());
+    mPedometerInfo->setCumulativeDistance(pedometerInfo->getCumulativeDistance());
+    mPedometerInfo->setCumulativeCalorie(pedometerInfo->getCumulativeCalorie());
+    mPedometerInfo->setCumulativeTotalStepCount(pedometerInfo->getCumulativeTotalStepCount());
+    mPedometerInfo->setCumulativeWalkStepCount(pedometerInfo->getCumulativeWalkStepCount());
+    mPedometerInfo->setCumulativeRunStepCount(pedometerInfo->getCumulativeRunStepCount());
+
+}
+
+
+PedometerInfo* PedometerSuccessCallback::getPedometerInfo()
+{
+    return mPedometerInfo;
+}
+
+
+WristUpSuccessCallback::WristUpSuccessCallback(JSContextRef globalCtx)
+    :CallbackUserData(globalCtx)
+{
+
+}
+
+WristUpSuccessCallback::~WristUpSuccessCallback()
+{
+    LOGD("enter");
+
+}
+
+
+HRMSuccessCallback::HRMSuccessCallback(JSContextRef globalCtx)
+    :CallbackUserData(globalCtx)
+{
+
+}
+
+HRMSuccessCallback::~HRMSuccessCallback()
+{
+    LOGD("enter");
+
+}
+
+
+GPSSuccessCallback::GPSSuccessCallback(JSContextRef globalCtx)
+    :CallbackUserData(globalCtx)
+{
+
+}
+
+GPSSuccessCallback::~GPSSuccessCallback()
+{
+    LOGD("enter");
+
+}
+
+
+} // Context
+} // DeviceAPI
diff --git a/src/HumanActivityMonitor/MotionManager.h b/src/HumanActivityMonitor/MotionManager.h
new file mode 100755 (executable)
index 0000000..0b484b4
--- /dev/null
@@ -0,0 +1,159 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_PEDOMETER_MANAGER_H__
+#define __TIZEN_PEDOMETER_MANAGER_H__
+
+#include <map>
+#include <list>
+#include <glib.h>
+#include <CallbackUserData.h>
+#include <gesture_recognition.h>
+#include <sensor_internal.h>
+
+#include "PedometerInfo.h"
+#include "ContextTypes.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+class WristUpSuccessCallback : public Common::CallbackUserData
+{
+public:
+    WristUpSuccessCallback(JSContextRef globalCtx);
+    virtual ~WristUpSuccessCallback();
+
+private:
+
+};
+
+class PedometerSuccessCallback : public Common::CallbackUserData
+{
+public:
+    PedometerSuccessCallback(JSContextRef globalCtx);
+    virtual ~PedometerSuccessCallback();
+    void setPedometerInit(const bool init);
+    bool getPedometerInit() const;
+    void setPedometerInfo(PedometerInfo* pedometerInfo);
+    void copyPedometerInfo(PedometerInfo* pedometerInfo);
+    PedometerInfo* getPedometerInfo();
+
+private:
+    PedometerInfo* mPedometerInfo;
+    bool mPedometerInit;
+};
+
+class HRMSuccessCallback : public Common::CallbackUserData
+{
+public:
+    HRMSuccessCallback(JSContextRef globalCtx);
+    virtual ~HRMSuccessCallback();
+
+private:
+
+};
+
+class GPSSuccessCallback : public Common::CallbackUserData
+{
+public:
+    GPSSuccessCallback(JSContextRef globalCtx);
+    virtual ~GPSSuccessCallback();
+private:
+};
+
+typedef std::shared_ptr<PedometerSuccessCallback> PedometerSuccessCallbackPtr;
+typedef std::shared_ptr<WristUpSuccessCallback> WristUpSuccessCallbackPtr;
+typedef std::shared_ptr<HRMSuccessCallback> HRMSuccessCallbackPtr;
+typedef std::shared_ptr<GPSSuccessCallback> GPSSuccessCallbackPtr;
+typedef std::shared_ptr<GPSInfo> GPInfoPtr;
+
+struct PedometerSuccessCallbackHolder {
+    PedometerSuccessCallbackPtr ptr;
+    JSValueRef mJSPedometerInfo;
+    bool mInit;
+};
+
+struct WristUpSuccessCallbackHolder {
+    WristUpSuccessCallbackPtr ptr;
+};
+
+struct HRMSuccessCallbackHolder {
+    HRMSuccessCallbackPtr ptr;
+    JSValueRef mJSHRMInfo;
+};
+
+struct GPSSuccessCallbackHolder {
+    GPSSuccessCallbackPtr ptr;
+    JSValueRef mJSGPSArray;
+};
+
+
+class MotionManager
+{
+public:
+    MotionManager();
+    virtual ~MotionManager();
+    void getContextInfo(PedometerSuccessCallbackPtr callback);
+    void setChangeListener(PedometerSuccessCallbackPtr callback);
+    void setChangeListener(WristUpSuccessCallbackPtr callback);
+    void setChangeListener(HRMSuccessCallbackPtr callback);
+    void setChangeListener(GPSSuccessCallbackPtr callback);
+    void unsetChangeListener(JSContextRef globalCtx, const char* type);
+    void setAccumulativePedometerListener(PedometerSuccessCallbackPtr callback);
+    void unsetAccumulativePedometerListener(JSContextRef globalCtx);
+    void broadcast_wristup_info();
+    void broadcast_pedometer_info(PedometerInfo* curPedometerInfo);
+    void broadcast_hrm_info(int heartRate, int rrInterval);
+    void broadcast_get_pedometer_info(PedometerInfo* curPedometerInfo);
+    void broadcast_gps_info(double* latitude, double* longitude, double* altitude, double* speed, double* errorRange, int64_t* timeStamp, int totalCnt);
+    static gboolean callPedometerSuccessCallback(void* data);
+    static gboolean callWristUpSuccessCallback(void* data);
+    static gboolean callHRMSuccessCallback(void* data);
+    static gboolean callGPSSuccessCallback(void* data);
+    static void hrm_changed_cb(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data);
+    static void wrist_up_changed_cb(void* user_data);
+    static void pedometer_changed_cb(void* user_data);
+    static void pedometer_get_info_cb(void* user_data);
+    static void gps_changed_cb(int num_of_location, void *user_data);
+    static MotionManager* getInstance();
+    void removeCallback(JSContextRef globalCtx);
+
+private:
+    std::map<JSContextRef, PedometerSuccessCallbackPtr> mPedometerCallbackMap;
+    std::map<JSContextRef, WristUpSuccessCallbackPtr> mWristupCallbackMap;
+    std::map<JSContextRef, HRMSuccessCallbackPtr> mHRMCallbackMap;
+    std::map<JSContextRef, PedometerSuccessCallbackPtr> mAccumulatviePedometerCallbackMap;
+    std::map<JSContextRef, GPSSuccessCallbackPtr> mGPSCallbackMap;
+    std::list<PedometerSuccessCallbackPtr> mPedometerGetCallbackList;
+    PedometerInfo* mBasePedometerInfo;
+    int mHRMHandle;
+    bool mBaseInit;
+    bool mPedometerB;
+    bool mWristUpB;
+    bool mHRMB;
+    bool mGPSB;
+
+};
+
+
+} // Context
+} // DeviceAPI
+
+#endif // __TIZEN_PEDOMETER_MANAGER_H__
diff --git a/src/HumanActivityMonitor/PedometerInfo.cpp b/src/HumanActivityMonitor/PedometerInfo.cpp
new file mode 100755 (executable)
index 0000000..53fe6f0
--- /dev/null
@@ -0,0 +1,339 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <math.h>
+
+#include "PedometerInfo.h"
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+PedometerInfo::PedometerInfo():
+    m_stepStatus(-1),
+    m_speed(0.0),
+    m_walkingFrequency(0.0),
+    m_cumulativeDistance(0.0),
+    m_cumulativeCalorie(0.0),
+    m_cumulativeTotalStepCount(0.0),
+    m_cumulativeWalkStepCount(0.0),
+    m_cumulativeRunStepCount(0.0),
+    m_stepDifference(NULL), m_timeStampLength(0), m_timeStamp(NULL)
+{
+}
+
+PedometerInfo::~PedometerInfo()
+{
+    LOGD("enter ");
+}
+
+char* PedometerInfo::getStepStatusString() const
+{
+    LOGD("enter %s", m_stepStatus);
+}
+
+int PedometerInfo::getStepStatus() const
+{
+    return m_stepStatus;
+}
+
+void PedometerInfo::setStepStatus(int stepStatus)
+{
+    m_stepStatus = stepStatus;
+}
+
+double PedometerInfo::getSpeed() const
+{
+    return m_speed;
+}
+
+void PedometerInfo::setSpeed(double speed)
+{
+    m_speed = speed;
+}
+
+double PedometerInfo::getWalkingFrequency() const
+{
+    return m_walkingFrequency;
+}
+
+void PedometerInfo::setWalkingFrequency(double walkingFrequency)
+{
+    m_walkingFrequency = walkingFrequency;
+}
+
+double PedometerInfo::getCumulativeDistance() const
+{
+    return m_cumulativeDistance;
+}
+
+void PedometerInfo::setCumulativeDistance(double cumulativeDistance)
+{
+    m_cumulativeDistance = cumulativeDistance;
+}
+
+double PedometerInfo::getCumulativeCalorie() const
+{
+    return m_cumulativeCalorie;
+}
+
+void PedometerInfo::setCumulativeCalorie(double cumulativeCalorie)
+{
+    m_cumulativeCalorie = cumulativeCalorie;
+}
+
+double PedometerInfo::getCumulativeTotalStepCount() const
+{
+    return m_cumulativeTotalStepCount;
+}
+
+void PedometerInfo::setCumulativeTotalStepCount(double cumulativeTotalStepCount)
+{
+    m_cumulativeTotalStepCount = cumulativeTotalStepCount;
+}
+
+double PedometerInfo::getCumulativeWalkStepCount() const
+{
+    return m_cumulativeWalkStepCount;
+}
+
+void PedometerInfo::setCumulativeWalkStepCount(double cumulativeWalkStepCount)
+{
+    m_cumulativeWalkStepCount = cumulativeWalkStepCount;
+}
+
+
+double PedometerInfo::getCumulativeRunStepCount() const
+{
+    return m_cumulativeRunStepCount;
+}
+
+void PedometerInfo::setCumulativeRunStepCount(double cumulativeRunStepCount)
+{
+    m_cumulativeRunStepCount = cumulativeRunStepCount;
+}
+
+void PedometerInfo::setStepDifference(int* stepDiff)
+{
+    m_stepDifference = stepDiff;
+}
+
+int* PedometerInfo::getStepDifference() const
+{
+    return m_stepDifference;
+}
+
+void PedometerInfo::setTimeStamp(int64_t* timsStamp)
+{
+    m_timeStamp = timsStamp;
+}
+
+int64_t* PedometerInfo::getTimeStamp() const
+{
+    return m_timeStamp;
+}
+
+void PedometerInfo::setTimeStampLength(int timsStampLength)
+{
+    m_timeStampLength = timsStampLength;
+}
+
+int PedometerInfo::getTimeStampLength() const
+{
+    return m_timeStampLength;
+}
+
+void PedometerInfo::setContext(JSContextRef ctx)
+{
+    LOGD("enter");
+    m_JSContext = ctx;
+}
+
+JSContextRef PedometerInfo::getContext()
+{
+    LOGD("enter");
+    return m_JSContext;
+}
+
+
+double PedometerInfo::convertSimpleDouble(double origin)
+{
+    return ((int)(origin*pow(10.0,2)))/pow(10.0,2);
+}
+
+HRMInfo::HRMInfo(int heartRate, int rrInterval)
+{
+    m_heartRate = heartRate;
+    m_RRInterval = rrInterval;
+
+}
+
+HRMInfo::~HRMInfo()
+{
+    LOGD("enter ");
+
+}
+
+void HRMInfo::setHeartRate(int heartRate)
+{
+    m_heartRate = heartRate;
+}
+
+int HRMInfo::getHeartRate() const
+{
+    return m_heartRate;
+
+}
+
+void HRMInfo::setRRInterval(int rrInterval)
+{
+    m_RRInterval = rrInterval;
+}
+
+int HRMInfo::getRRInterval() const
+{
+    return m_RRInterval;
+
+}
+
+//GPS Info
+GPSInfo::GPSInfo(double latitude, double longitude, double altitude, double speed, double errorRange, int64_t timeStamp)
+{
+    m_latitude = latitude;
+    m_longitude = longitude;
+    m_altitude = convertSimpleDouble(altitude);
+    m_speed = convertSimpleDouble(speed);
+    m_errorRange = convertSimpleDouble(errorRange);
+    m_timeStamp= timeStamp/1000;
+
+    LOGD("enter [ %f , %f , %f , %f , %f , %d ]", m_latitude , m_longitude , m_altitude, m_speed, m_errorRange, m_timeStamp);
+}
+
+GPSInfo::~GPSInfo()
+{
+    LOGD("enter ");
+
+}
+
+double GPSInfo::getLatitude() const
+{
+    return m_latitude;
+}
+
+void GPSInfo::setLatitude(double latitude)
+{
+    m_latitude = latitude;
+}
+
+double GPSInfo::getLongitude() const
+{
+    return m_longitude;
+}
+
+void GPSInfo::setLongitude(double longitude)
+{
+    m_longitude = longitude;
+}
+
+double GPSInfo::getAltitude() const
+{
+    return m_altitude;
+}
+
+void GPSInfo::setAltitude(double altitude)
+{
+    m_altitude = altitude;
+}
+
+double GPSInfo::getSpeed() const
+{
+    return m_speed;
+}
+
+void GPSInfo::setSpeed(double speed)
+{
+    m_speed = speed;
+}
+
+double GPSInfo::getErrorRange() const
+{
+    return m_errorRange;
+}
+
+void GPSInfo::setErrorRange(double errorRange)
+{
+    m_errorRange = errorRange;
+}
+
+int64_t GPSInfo::getTimeStamp() const
+{
+    return m_timeStamp;
+}
+
+void GPSInfo::setTimeStamp(int64_t timeStamp)
+{
+    m_timeStamp = timeStamp;
+}
+
+double GPSInfo::convertSimpleDouble(double origin)
+{
+    return ((int)(origin*pow(10.0,2)))/pow(10.0,2);
+}
+
+
+StepDifferenceInfo::StepDifferenceInfo(int stepDifference, int64_t timeStamp)
+{
+    m_stepDifference = stepDifference;
+    m_timeStamp= timeStamp/1000;
+}
+
+StepDifferenceInfo::~StepDifferenceInfo()
+{
+    LOGD("enter ");
+
+}
+
+void StepDifferenceInfo::setStepDifference(int stepDifference)
+{
+    m_stepDifference= stepDifference;
+}
+
+int StepDifferenceInfo::getStepDifference() const
+{
+    return m_stepDifference;
+}
+
+
+void StepDifferenceInfo::setTimeStamp(int64_t timsStamp)
+{
+    m_timeStamp = timsStamp;
+}
+
+int64_t StepDifferenceInfo::getTimeStamp() const
+{
+    return m_timeStamp;
+}
+
+double StepDifferenceInfo::convertSimpleDouble(double origin)
+{
+    return ((int)(origin*pow(10.0,2)))/pow(10.0,2);
+}
+
+} // Context
+} // DeviceAPI
diff --git a/src/HumanActivityMonitor/PedometerInfo.h b/src/HumanActivityMonitor/PedometerInfo.h
new file mode 100755 (executable)
index 0000000..431aba3
--- /dev/null
@@ -0,0 +1,170 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_PEDOMETER_INFO_H__
+#define __TIZEN_PEDOMETER_INFO_H__
+
+#include <MultiCallbackUserData.h>
+#include "ContextTypes.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+class PedometerInfo
+{
+public:
+    PedometerInfo();
+    virtual ~PedometerInfo();
+
+    int getStepStatus() const;
+    char* getStepStatusString() const;
+    void setStepStatus(int stepStatus);
+
+    double getSpeed() const;
+    void setSpeed(double speed);
+
+    double getWalkingFrequency() const;
+    void setWalkingFrequency(double walkingFrequency);
+
+    double getCumulativeDistance() const;
+    void setCumulativeDistance(double cumulativeDistance);
+
+    double getCumulativeCalorie() const;
+    void setCumulativeCalorie(double cumulativeCalorie);
+
+    double getCumulativeTotalStepCount() const;
+    void setCumulativeTotalStepCount(double cumulativeTotalStepCount);
+
+    double getCumulativeWalkStepCount() const;
+    void setCumulativeWalkStepCount(double cumulativeWalkStepCount);
+
+    double getCumulativeRunStepCount() const;
+    void setCumulativeRunStepCount(double cumulativeRunStepCount);
+
+    void setStepDifference(int* stepDiff);
+    int* getStepDifference() const;
+
+    void setTimeStamp(int64_t* timsStamp);
+    int64_t* getTimeStamp() const;
+
+    void setTimeStampLength(int timsStampLength);
+    int getTimeStampLength() const;
+
+    void setContext(JSContextRef ctx);
+    JSContextRef getContext();
+
+    double convertSimpleDouble(double origin);
+
+    JSValueRef m_jSStepDiffrence;
+    JSContextRef m_JSContext;
+
+private:
+    int m_stepStatus;
+    double m_speed;
+    double m_walkingFrequency;
+    double m_cumulativeDistance;
+    double m_cumulativeCalorie;
+    double m_cumulativeTotalStepCount;
+    double m_cumulativeWalkStepCount;
+    double m_cumulativeRunStepCount;
+    int* m_stepDifference;
+    int m_timeStampLength;
+    int64_t* m_timeStamp;
+
+};
+
+class HRMInfo
+{
+public:
+    HRMInfo(int heartRate, int rrInterval);
+    virtual ~HRMInfo();
+
+    int getHeartRate() const;
+    void setHeartRate(int heartRate);
+
+    int getRRInterval() const;
+    void setRRInterval(int rrInterval);
+
+private:
+    int m_heartRate;
+    int m_RRInterval;
+};
+
+
+class GPSInfo
+{
+public:
+    GPSInfo(double latitude, double longitude, double altitude, double speed, double errorRange, int64_t timeStamp);
+    virtual ~GPSInfo();
+
+    double getLatitude() const;
+    void setLatitude(double latitude);
+
+    double getLongitude() const;
+    void setLongitude(double longitude);
+
+    double getAltitude() const;
+    void setAltitude(double altitude);
+
+    double getSpeed() const;
+    void setSpeed(double speed);
+
+    int64_t getTimeStamp() const;
+    void setTimeStamp(int64_t timeStamp);
+
+    double getErrorRange() const;
+    void setErrorRange(double errorRange);
+
+
+    double convertSimpleDouble(double origin);
+
+private:
+    double m_latitude;
+    double m_longitude;
+    double m_altitude;
+    double m_speed;
+    double m_errorRange;
+    int64_t m_timeStamp;
+};
+
+class StepDifferenceInfo
+{
+public:
+    StepDifferenceInfo(int stepDifference, int64_t timeStamp);
+    virtual ~StepDifferenceInfo();
+
+    void setStepDifference(int stepDifference);
+    int getStepDifference() const;
+
+    int64_t getTimeStamp() const;
+    void setTimeStamp(int64_t timeStamp);
+
+    double convertSimpleDouble(double origin);
+
+private:
+    int m_stepDifference;
+    int64_t m_timeStamp;
+};
+
+typedef std::shared_ptr<StepDifferenceInfo> StepDifferenceInfoPtr;
+
+} // Pedometer
+} // DeviceAPI
+
+#endif // __TIZEN_PEDOMETER_INFO_H__
diff --git a/src/HumanActivityMonitor/config.xml b/src/HumanActivityMonitor/config.xml
new file mode 100755 (executable)
index 0000000..a8f414f
--- /dev/null
@@ -0,0 +1,14 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-humanactivitymonitor.so</library-name>
+    <feature-install-uri>humanactivitymonitor.install.uri</feature-install-uri>
+    <api-feature>
+        <name>http://tizen.org/privilege/healthinfo</name>
+        <device-capability>healthinfo</device-capability>
+    </api-feature>
+    <api-feature>
+        <name>http://tizen.org/privilege/medicalinfo</name>
+        <device-capability>medicalinfo</device-capability>
+    </api-feature>
+</plugin-properties>
diff --git a/src/HumanActivityMonitor/plugin_config.cpp b/src/HumanActivityMonitor/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..355590f
--- /dev/null
@@ -0,0 +1,132 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define MOTION_FEATURE_API_HEALTHINFO  "http://tizen.org/privilege/healthinfo"
+#define MOTION_FEATURE_API_MEDICALINFO  "http://tizen.org/privilege/medicalinfo"
+#define MOTION_DEVICE_CAP_HEALTHINFO "healthinfo"
+#define MOTION_DEVICE_CAP_MEDICALINFO "medicalinfo"
+
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+static FunctionMapping createHumanActivityMonitorFunctions();
+static FunctionMapping HumanActivityMonitorFunctions = createHumanActivityMonitorFunctions();
+
+DEFINE_FUNCTION_GETTER(HumanActivityMonitor, HumanActivityMonitorFunctions);
+
+static FunctionMapping createHumanActivityMonitorFunctions()
+{
+    /**
+     * Device capabilities : healthinfo
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_MOTION_HEALTHINFO, MOTION_DEVICE_CAP_HEALTHINFO);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_MOTION_HEALTHINFO);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_MOTION_HEALTHINFO, DEVICE_CAP_MOTION_HEALTHINFO);
+
+    /**
+     * Device capabilities : medicalinfo
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_MOTION_MEDICALINFO, MOTION_DEVICE_CAP_MEDICALINFO);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_MOTION_MEDICALINFO);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_MOTION_MEDICALINFO, DEVICE_CAP_MOTION_MEDICALINFO);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_MOTION_HEALTHINFO, MOTION_FEATURE_API_HEALTHINFO);
+
+    ACE_CREATE_FEATURE_LIST(MOTION_FEATURES_MOTION_HEALTHINFO);
+    ACE_ADD_API_FEATURE(MOTION_FEATURES_MOTION_HEALTHINFO, FEATURE_MOTION_HEALTHINFO);
+
+    /**
+     * medical info Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_MOTION_MEDICALINFO, MOTION_FEATURE_API_MEDICALINFO);
+
+    ACE_CREATE_FEATURE_LIST(MOTION_FEATURES_MOTION_MEDICALINFO);
+    ACE_ADD_API_FEATURE(MOTION_FEATURES_MOTION_MEDICALINFO, FEATURE_MOTION_MEDICALINFO);
+
+    /**
+     * Functions
+     */
+    FunctionMapping motionMapping;
+
+
+    //start
+    AceFunction MotionStartFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_MOTION_START,
+            MOTION_API_START,
+            MOTION_FEATURES_MOTION_HEALTHINFO,
+            DEVICE_LIST_MOTION_HEALTHINFO);
+
+    motionMapping.insert(std::make_pair(
+                               MOTION_API_START,
+                               MotionStartFunc));
+
+    //medicalinfo
+    AceFunction MotionStartHRMFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_MOTION_MEDICALINFO,
+            MOTION_API_MEDICALINFO,
+            MOTION_FEATURES_MOTION_MEDICALINFO,
+            DEVICE_LIST_MOTION_HEALTHINFO);
+
+    motionMapping.insert(std::make_pair(
+                               MOTION_API_MEDICALINFO,
+                               MotionStartHRMFunc));
+
+    //stop
+    AceFunction MotionStopFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_MOTION_STOP,
+            MOTION_API_STOP,
+            MOTION_FEATURES_MOTION_HEALTHINFO,
+            DEVICE_LIST_MOTION_HEALTHINFO);
+
+    motionMapping.insert(std::make_pair(
+                               MOTION_API_STOP,
+                               MotionStopFunc));
+
+
+    //getMotionInfo
+    AceFunction MotionGetMotionInfoFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_MOTION_GET_MOTION_INFO,
+            MOTION_API_GET_CONTEXT_INFO,
+            MOTION_FEATURES_MOTION_HEALTHINFO,
+            DEVICE_LIST_MOTION_HEALTHINFO);
+
+    motionMapping.insert(std::make_pair(
+                               MOTION_API_GET_CONTEXT_INFO,
+                               MotionGetMotionInfoFunc));
+
+    return motionMapping;
+}
+
+} // Context
+} // DeviceAPI
diff --git a/src/HumanActivityMonitor/plugin_config.h b/src/HumanActivityMonitor/plugin_config.h
new file mode 100755 (executable)
index 0000000..c0313af
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _PEDOMETER_PLUGIN_CONFIG_H_
+#define _PEDOMETER_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+#define MOTION_API_GET_CONTEXT_INFO "getHumanActivityData"
+#define MOTION_API_START "start"
+#define MOTION_API_MEDICALINFO "medicalinfo"
+#define MOTION_API_STOP "stop"
+#define MOTION_API_SET_ACCUMULATIVE_PEDOMETER_LISTENER "setAccumulativePedometerListener"
+#define MOTION_API_UNSET_ACCUMULATIVE_PEDOMETER_LISTENER "unsetAccumulativePedometerListener"
+#define MOTION_API_START_HAND_GESTURE_RECOGNITION_LISTENER "startHandGestureRecognition"
+#define MOTION_API_STOP_HAND_GESTURE_RECOGNITION_LISTENER "stopHandGestureRecognition"
+
+
+
+// attributes
+#define PEDOMETER_INFO_STEP_STATUS "stepStatus"
+#define PEDOMETER_INFO_SPEED "speed"
+#define PEDOMETER_INFO_WALKING_FREQUENCY "walkingFrequency"
+#define PEDOMETER_INFO_STEP_COUNT_DIFFERENCES "stepCountDifferences"
+
+#define PEDOMETER_INFO_CUMULATIVE_DISTANCE "cumulativeDistance"
+#define PEDOMETER_INFO_CUMULATIVE_CALORIE "cumulativeCalorie"
+#define PEDOMETER_INFO_CUMULATIVE_TOTAL_STEP_COUNT "cumulativeTotalStepCount"
+#define PEDOMETER_INFO_CUMULATIVE_WALK_STEP_COUNT "cumulativeWalkStepCount"
+#define PEDOMETER_INFO_CUMULATIVE_RUN_STEP_COUNT "cumulativeRunStepCount"
+
+// functions
+#define PEDOMETER_MANAGER_API_GET_CONTEXT_INFO "getHumanActivityData"
+#define PEDOMETER_MANAGER_API_START "start"
+#define PEDOMETER_MANAGER_API_STOP "stop"
+
+DECLARE_FUNCTION_GETTER(HumanActivityMonitor);
+
+#define HUMANACTIVITYMONITOR_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getHumanActivityMonitorFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _PEDOMETER_PLUGIN_CONFIG_H_
diff --git a/src/HumanActivityMonitor/plugin_initializer.cpp b/src/HumanActivityMonitor/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..d6d4dd4
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <GlobalContextManager.h>
+#include <Logger.h>
+
+#include "JSMotionManager.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+#define WRT_JS_EXTENSION_OBJECT_WEBAPIS "webapis"
+#define WRT_JS_EXTENSION_OBJECT_TIZEN "tizen"
+
+namespace DeviceAPI {
+namespace HumanActivityMonitor {
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\HumanActivityMonitor] on_widget_start_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\HumanActivityMonitor] on_widget_stop_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\HumanActivityMonitor] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\HumanActivityMonitor] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+    MotionManager::getInstance()->removeCallback(static_cast<JSContextRef>(context));
+
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "humanactivitymonitor",
+        (js_class_template_getter)DeviceAPI::HumanActivityMonitor::JSMotionManager::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_END
+
+} // Context
+} // DeviceAPI
diff --git a/src/Mediakey/CMakeLists.txt b/src/Mediakey/CMakeLists.txt
new file mode 100644 (file)
index 0000000..2b65060
--- /dev/null
@@ -0,0 +1,52 @@
+
+SET(TARGET_NAME ${mediakey_target})
+SET(DESTINATION_NAME ${mediakey_dest})
+SET(TARGET_IMPL_NAME ${mediakey_impl})
+
+PKG_CHECK_MODULES(mediakey REQUIRED capi-system-media-key)
+
+INCLUDE_DIRECTORIES(
+        ${TOP}/Common
+        ${mediakey_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+        ${CMAKE_INSTALL_RPATH}
+        ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+        ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${timeutil_dest}
+        ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSMediaKeyManager.cpp
+    MediaKeyManager.cpp
+    MediaKeyEventCallback.cpp
+    MediaKeyUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+        ${LIBS_COMMON}
+        ${tizen_impl}
+        ${timeutil_impl}
+        ${mediakey_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+        ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/mediakey
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Mediakey/JSMediaKeyManager.cpp b/src/Mediakey/JSMediaKeyManager.cpp
new file mode 100644 (file)
index 0000000..150d886
--- /dev/null
@@ -0,0 +1,164 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSMediaKeyManager.h"
+#include "MediaKeyManager.h"
+#include "plugin_config.h"
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+JSClassDefinition JSMediaKeyManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "MediaKeyManager",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSMediaKeyManager::m_function[] = {
+    { MEDIA_KEY_MANAGER_API_SET_MEDIA_KEY_EVENT_LISTENER, setMediaKeyEventListener, kJSPropertyAttributeNone },
+    { MEDIA_KEY_MANAGER_API_UNSET_MEDIA_KEY_EVENT_LISTENER, unsetMediaKeyEventListener, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSMediaKeyManager::m_jsClassRef = JSClassCreate(JSMediaKeyManager::getClassInfo());
+
+const JSClassRef JSMediaKeyManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSMediaKeyManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSMediaKeyManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSMediaKeyManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+JSValueRef JSMediaKeyManager::setMediaKeyEventListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        //Private Object
+        LOGD("Entered");
+
+        MediaKeyManager *priv = MediaKeyManager::getInstance();
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        //callback
+        JSObjectRef callbackObj = validator.toCallbackObject(0, false, "onpressed","onreleased",NULL);
+
+        JSValueRef onpressed = JSUtil::getProperty(context, callbackObj, "onpressed");
+        JSValueRef onreleased = JSUtil::getProperty(context, callbackObj, "onreleased");
+
+        JSObjectRef pressedCallback = NULL;
+        if(!JSValueIsUndefined(context, onpressed)){
+            pressedCallback = JSUtil::JSValueToObject(context, onpressed);
+        }
+
+        JSObjectRef releasedCallback = NULL;
+        if(!JSValueIsUndefined(context, onreleased)){
+            releasedCallback = JSUtil::JSValueToObject(context, onreleased);
+        }
+
+        MediaKeyEventListenerPtr callback(new MediaKeyEventCallback(
+            GlobalContextManager::getInstance()->getGlobalContext(context),
+            pressedCallback,
+            releasedCallback));
+
+        priv -> setMediaKeyEventListener(callback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in MediaKeyManager.setMediaKeyEventListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSMediaKeyManager::unsetMediaKeyEventListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        LOGD("Entered");
+
+        MediaKeyManager *priv = MediaKeyManager::getInstance();
+
+        // perform
+        priv ->unsetMediaKeyEventListener();
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in MediaKeyManager.unsetMediaKeyEventListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // MediaKey
+} // DeviceAPI
diff --git a/src/Mediakey/JSMediaKeyManager.h b/src/Mediakey/JSMediaKeyManager.h
new file mode 100644 (file)
index 0000000..3ddad85
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_MEDIA_KEY_MANAGER_H__
+#define __TIZEN_JS_MEDIA_KEY_MANAGER_H__
+
+#include "MediaKeyManager.h"
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+class JSMediaKeyManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef setMediaKeyEventListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetMediaKeyEventListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+} // MediaKey
+} // DeviceAPI
+
+#endif // __TIZEN_JS_MEDIA_KEY_EVENT_CALLBACK_H__
diff --git a/src/Mediakey/MediaKeyEventCallback.cpp b/src/Mediakey/MediaKeyEventCallback.cpp
new file mode 100644 (file)
index 0000000..a484e05
--- /dev/null
@@ -0,0 +1,165 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <JSStringRefWrapper.h>
+#include <JSUtil.h>
+#include <GlobalContextManager.h>
+#include "MediaKeyManager.h"
+#include "MediaKeyEventCallback.h"
+
+#define PRESSED_CALLBACK "onpressed"
+#define RELEASED_CALLBACK "onreleased"
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+void MediaKeyEventCallback::setMediaKeyType(MediaKeyType type){
+    m_type = type;
+}
+
+MediaKeyEventCallback::MediaKeyEventCallback(JSContextRef context, JSObjectRef onpressed, JSObjectRef onreleased)
+:MultiCallbackUserData(context)
+{
+    LOGD("Entered");
+    setCallback(PRESSED_CALLBACK, onpressed);
+    setCallback(RELEASED_CALLBACK, onreleased);
+}
+
+MediaKeyEventCallback::~MediaKeyEventCallback()
+{
+}
+
+gboolean MediaKeyEventCallback::onpressed(void *data)
+{
+        LOGD("Enter");
+        MediaKeyEventListenerPtr *holder = static_cast<MediaKeyEventListenerPtr *>(data);
+        MediaKeyEventListenerPtr cb = *holder;
+
+        try {
+            JSContextRef context = cb->getContext();
+            if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+                LOGE("context was closed");
+                throw UnknownException("context was closed");
+            }
+
+        std::string typeStr;
+
+        switch(cb->m_type)
+        {
+        case MEDIA_KEY_TYPE_PLAY:
+                typeStr = "PLAY";
+                break;
+        case MEDIA_KEY_TYPE_STOP:
+                typeStr = "STOP";
+                break;
+        case MEDIA_KEY_TYPE_PAUSE:
+                typeStr = "PAUSE";
+                break;
+        case MEDIA_KEY_TYPE_PREVIOUS:
+                typeStr = "PREVIOUS";
+                break;
+        case MEDIA_KEY_TYPE_NEXT:
+                typeStr = "NEXT";
+                break;
+        case MEDIA_KEY_TYPE_FASTFORWARD:
+                typeStr = "FASTFORWARD";
+                break;
+        case MEDIA_KEY_TYPE_REWIND:
+                typeStr = "REWIND";
+                break;
+        case MEDIA_KEY_TYPE_PLAYPAUSE:
+                typeStr = "PLAYPAUSE";
+                break;
+        default:
+                LOGE("Wrong type value");
+                break;
+        }
+
+        cb->invokeCallback(PRESSED_CALLBACK, JSUtil::toJSValueRef(context, typeStr));
+
+        } catch (BasePlatformException &err) {
+            LOGE("%s : %s", (err.getName()).c_str(), (err.getMessage()).c_str());
+        } catch (...) {
+            LOGE("Something strange happened");
+        }
+
+        delete holder;
+        return false;
+}
+
+gboolean MediaKeyEventCallback::onreleased(void *data)
+{
+        LOGD("Enter");
+        MediaKeyEventListenerPtr *holder = static_cast<MediaKeyEventListenerPtr *>(data);
+        MediaKeyEventListenerPtr cb = *holder;
+
+        try {
+            JSContextRef context = cb->getContext();
+            if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+                LOGE("context was closed");
+                throw UnknownException("context was closed");
+            }
+
+        std::string typeStr;
+
+        switch(cb->m_type)
+        {
+        case MEDIA_KEY_TYPE_PLAY:
+                typeStr = "PLAY";
+                break;
+        case MEDIA_KEY_TYPE_STOP:
+                typeStr = "STOP";
+                break;
+        case MEDIA_KEY_TYPE_PAUSE:
+                typeStr = "PAUSE";
+                break;
+        case MEDIA_KEY_TYPE_PREVIOUS:
+                typeStr = "PREVIOUS";
+                break;
+        case MEDIA_KEY_TYPE_NEXT:
+                typeStr = "NEXT";
+                break;
+        case MEDIA_KEY_TYPE_FASTFORWARD:
+                typeStr = "FASTFORWARD";
+                break;
+        case MEDIA_KEY_TYPE_REWIND:
+                typeStr = "REWIND";
+                break;
+        case MEDIA_KEY_TYPE_PLAYPAUSE:
+                typeStr = "PLAYPAUSE";
+                break;
+        default:
+                LOGE("Wrong type value");
+                break;
+        }
+
+        cb->invokeCallback(RELEASED_CALLBACK, JSUtil::toJSValueRef(context, typeStr));
+
+        } catch (BasePlatformException &err) {
+            LOGE("%s : %s", (err.getName()).c_str(), (err.getMessage()).c_str());
+        } catch (...) {
+            LOGE("Something strange happened");
+        }
+
+        delete holder;
+        return false;
+}
+
+} // MediaKey
+} // DeviceAPI
diff --git a/src/Mediakey/MediaKeyEventCallback.h b/src/Mediakey/MediaKeyEventCallback.h
new file mode 100644 (file)
index 0000000..a8089b6
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MEDIA_KEY_EVENT_CALLBACK_H__
+#define __TIZEN_MEDIA_KEY_EVENT_CALLBACK_H__
+
+#include <MultiCallbackUserData.h>
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+#include <glib.h>
+
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+enum MediaKeyType
+{
+        MEDIA_KEY_TYPE_PLAY,
+        MEDIA_KEY_TYPE_STOP,
+        MEDIA_KEY_TYPE_PAUSE,
+        MEDIA_KEY_TYPE_PREVIOUS,
+        MEDIA_KEY_TYPE_NEXT,
+        MEDIA_KEY_TYPE_FASTFORWARD,
+        MEDIA_KEY_TYPE_REWIND,
+        MEDIA_KEY_TYPE_PLAYPAUSE
+};
+
+enum MediaKeyEventType
+{
+        MEDIA_KEY_EVENT_PRESSED,
+        MEDIA_KEY_EVENT_RELEASED
+};
+
+
+
+class MediaKeyEventCallback : MultiCallbackUserData
+{
+public:
+    MediaKeyEventCallback(JSContextRef globalCtx, JSObjectRef pressedCallback, JSObjectRef releasedCallback);
+    virtual ~MediaKeyEventCallback();
+
+    void setMediaKeyType(MediaKeyType type);
+    static gboolean onpressed(void *data);
+    static gboolean onreleased(void *data);
+
+private:
+    MediaKeyType m_type;
+};
+
+} // MediaKey
+} // DeviceAPI
+
+#endif // __TIZEN_MEDIA_KEY_EVENT_CALLBACK_H__
diff --git a/src/Mediakey/MediaKeyManager.cpp b/src/Mediakey/MediaKeyManager.cpp
new file mode 100644 (file)
index 0000000..5232784
--- /dev/null
@@ -0,0 +1,157 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MediaKeyManager.h"
+#include "MediaKeyUtil.h"
+
+#include <JSStringRefWrapper.h>
+#include <PlatformException.h>
+#include <Logger.h>
+#include <glib.h>
+
+#include <media_key.h>
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+void onMediaKeyEventCb(media_key_e key, media_key_event_e status, void* user_data)
+{
+    LOGD("Entered");
+
+    MediaKeyManager* mediaKeyManager = MediaKeyManager::getInstance();
+
+    MediaKeyType mediaKeyType = MediaKeyUtil::mediakeyTypeToString(key);
+    MediaKeyEventType mediaKeyEventType= MediaKeyUtil::mediakeyEventTypeToString(status);
+
+    mediaKeyManager->onMediaKey(mediaKeyType, mediaKeyEventType);
+}
+
+
+MediaKeyManager::MediaKeyManager() :
+    m_listener(MediaKeyEventListenerPtr(NULL)),
+    m_listeningPlatformEvent(false)
+{
+}
+
+MediaKeyManager* MediaKeyManager::getInstance()
+{
+    static MediaKeyManager instance;
+    return &instance;
+}
+
+
+MediaKeyManager::~MediaKeyManager()
+{
+    m_listener = NULL;
+
+    if(m_listeningPlatformEvent)
+    {
+        LOGD("::media_key_release");
+        int ret = media_key_release();
+        if (ret != MEDIA_KEY_ERROR_NONE)
+        {
+            LOGE("ret : %d", ret);
+            MediaKeyUtil::throwMediaKeyException(ret, "media_key_release()");
+        }
+        m_listeningPlatformEvent = false;
+    }
+}
+
+
+void MediaKeyManager::setMediaKeyEventListener(MediaKeyEventListenerPtr listener)
+{
+    LOGD("Enter MediaKeyManager setMediaKeyEventListener");
+
+    if(m_listener){
+        LOGD("delete m_listener");
+        m_listener = NULL;
+    }
+
+    if(listener){
+        m_listener = listener;
+    }
+
+    if(!m_listeningPlatformEvent)
+    {
+        LOGD("::media_key_reserve");
+        int ret = media_key_reserve(onMediaKeyEventCb, static_cast<void*>(this));
+        if (ret != MEDIA_KEY_ERROR_NONE)
+        {
+            LOGE("ret : %d", ret);
+            MediaKeyUtil::throwMediaKeyException(ret, "media_key_reserve()");
+        }
+        m_listeningPlatformEvent = true;
+    }
+}
+void MediaKeyManager::unsetMediaKeyEventListener()
+{
+    LOGD("Enter MediaKeyManager unsetMediaKeyEventListener");
+    m_listener = NULL;
+
+    if(m_listeningPlatformEvent)
+    {
+        LOGD("::media_key_release");
+        int ret = media_key_release();
+        if (ret != MEDIA_KEY_ERROR_NONE)
+        {
+            LOGE("ret : %d", ret);
+            MediaKeyUtil::throwMediaKeyException(ret, "media_key_release()");
+        }
+        m_listeningPlatformEvent = false;
+    }
+}
+
+void MediaKeyManager::onMediaKey(MediaKeyType type, MediaKeyEventType event)
+{
+        if(!m_listeningPlatformEvent)
+        {
+                LOGE("event is not registered");
+                return;
+        }
+
+        if(NULL == m_listener)
+        {
+                LOGE("event listener is not registered");
+                return;
+        }
+
+
+        MediaKeyEventListenerPtr cb = m_listener;
+        cb->setMediaKeyType(type);
+        MediaKeyEventListenerPtr* data = new MediaKeyEventListenerPtr(cb);
+
+        switch(event)
+        {
+        case MediaKeyEventType::MEDIA_KEY_EVENT_PRESSED:
+                LOGD("event : PRESSED");
+                if (!g_idle_add(MediaKeyEventCallback::onpressed, data)) {
+                    LOGE("g_idle addition failed");
+                    throw UnknownException("g_idle addition failed");
+                }
+                break;
+        case MEDIA_KEY_STATUS_RELEASED:
+                LOGD("event : RELEASED");
+                if (!g_idle_add(MediaKeyEventCallback::onreleased, data)) {
+                    LOGE("g_idle addition failed");
+                    throw UnknownException("g_idle addition failed");
+                }
+                break;
+        }
+}
+
+} // MediaKey
+} // DeviceAPI
diff --git a/src/Mediakey/MediaKeyManager.h b/src/Mediakey/MediaKeyManager.h
new file mode 100644 (file)
index 0000000..feb46ac
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MEDIA_KEY_MANAGER_H__
+#define __TIZEN_MEDIA_KEY_MANAGER_H__
+
+#include "MediaKeyEventCallback.h"
+
+#include <memory>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+typedef std::shared_ptr<MediaKeyEventCallback> MediaKeyEventListenerPtr;
+
+class MediaKeyManager
+{
+private:
+    MediaKeyManager();
+    MediaKeyEventListenerPtr m_listener;
+    bool m_listeningPlatformEvent;
+
+public:
+    ~MediaKeyManager();
+    static MediaKeyManager* getInstance();
+    void setMediaKeyEventListener(MediaKeyEventListenerPtr listener);
+    void unsetMediaKeyEventListener();
+    void onMediaKey(MediaKeyType type, MediaKeyEventType event);
+};
+
+} // MediaKey
+} // DeviceAPI
+
+#endif // __TIZEN_MEDIA_KEY_MANAGER_H__
diff --git a/src/Mediakey/MediaKeyUtil.cpp b/src/Mediakey/MediaKeyUtil.cpp
new file mode 100644 (file)
index 0000000..6f14ee4
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MediaKeyUtil.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include <sstream>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+std::string& MediaKeyUtil::getMediaKeyErrorMessage(const int errorCode){
+    switch(errorCode) {
+        case MEDIA_KEY_ERROR_INVALID_PARAMETER:
+            return errInvalidParameter;
+        case MEDIA_KEY_ERROR_OPERATION_FAILED:
+            return errOperationFailed;
+        default:
+            return errUnknown;
+    }
+}
+
+std::string MediaKeyUtil::getMediaKeyLogMessage(const int errorCode, const std::string &hint){
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getMediaKeyErrorMessage(errorCode) << ", " << errorCode;
+    return std::string(ss.str());
+}
+
+
+MediaKeyType MediaKeyUtil::mediakeyTypeToString(media_key_e key){
+
+    LOGD("Entered");
+
+    switch(key)
+    {
+        case MEDIA_KEY_PLAY:
+                LOGD("key : MEDIA_KEY_PLAY");
+                return MediaKeyType::MEDIA_KEY_TYPE_PLAY;
+                break;
+        case MEDIA_KEY_STOP:
+                LOGD("key : MEDIA_KEY_STOP");
+                return MediaKeyType::MEDIA_KEY_TYPE_STOP;
+                break;
+        case MEDIA_KEY_PAUSE:
+                LOGD("key : MEDIA_KEY_PAUSE");
+                return MediaKeyType::MEDIA_KEY_TYPE_PAUSE;
+                break;
+        case MEDIA_KEY_PREVIOUS:
+                LOGD("key : MEDIA_KEY_PREVIOUS");
+                return MediaKeyType::MEDIA_KEY_TYPE_PREVIOUS;
+                break;
+        case MEDIA_KEY_NEXT:
+                LOGD("key : MEDIA_KEY_NEXT");
+                return MediaKeyType::MEDIA_KEY_TYPE_NEXT;
+                break;
+        case MEDIA_KEY_FASTFORWARD:
+                LOGD("key : MEDIA_KEY_FASTFORWARD");
+                return MediaKeyType::MEDIA_KEY_TYPE_FASTFORWARD;
+                break;
+        case MEDIA_KEY_REWIND:
+                LOGD("key : MEDIA_KEY_REWIND");
+                return MediaKeyType::MEDIA_KEY_TYPE_REWIND;
+                break;
+        case MEDIA_KEY_PLAYPAUSE:
+                LOGD("key : MEDIA_KEY_PLAYPAUSE");
+                return MediaKeyType::MEDIA_KEY_TYPE_PLAYPAUSE;
+                break;
+        case MEDIA_KEY_UNKNOWN:
+                LOGW("media_key callback gave MEDIA_KEY_UNKNOWN");
+                throw TypeMismatchException("Invalid media_key");
+        default:
+                LOGW("media_key callback gave wrong key value");
+                throw TypeMismatchException("Invalid media_key");
+    }
+}
+
+MediaKeyEventType MediaKeyUtil::mediakeyEventTypeToString(media_key_event_e status){
+
+    LOGD("Entered");
+
+    switch(status)
+    {
+        case MEDIA_KEY_STATUS_PRESSED:
+                LOGD("status : MEDIA_KEY_STATUS_PRESSED");
+                return MediaKeyEventType::MEDIA_KEY_EVENT_PRESSED;
+                break;
+        case MEDIA_KEY_STATUS_RELEASED:
+                LOGD("status : MEDIA_KEY_STATUS_RELEASED");
+                return MediaKeyEventType::MEDIA_KEY_EVENT_RELEASED;
+                break;
+        case MEDIA_KEY_STATUS_UNKNOWN:
+                LOGW("media_key callback gave MEDIA_KEY_STATUS_UNKNOWN");
+                throw TypeMismatchException("Invalid media_key_status");
+        default:
+                LOGW("media_key callback gave wrong status value");
+                throw TypeMismatchException("Invalid media_key_status");
+    }
+}
+
+} // MediaKey
+} // DeviceAPI
diff --git a/src/Mediakey/MediaKeyUtil.h b/src/Mediakey/MediaKeyUtil.h
new file mode 100644 (file)
index 0000000..4353559
--- /dev/null
@@ -0,0 +1,52 @@
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MEDIAKEY_UTIL_H__
+#define __TIZEN_MEDIAKEY_UTIL_H__
+
+#include "MediaKeyEventCallback.h"
+
+#include <string>
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <media_key.h>
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+static std::string errInvalidParameter = "Invalid parameter";
+static std::string errOperationFailed = "Reserve/Release failed";
+static std::string errUnknown = "Unknown error";
+
+class MediaKeyUtil {
+public:
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwMediaKeyException(const int errorCode, const std::string &hint){
+        std::string log = MediaKeyUtil::getMediaKeyLogMessage(errorCode, hint);
+        LOGE("%s", log.c_str());
+        throw T(log.c_str());
+    }
+    static std::string& getMediaKeyErrorMessage(const int errorCode);
+    static std::string getMediaKeyLogMessage(const int errorCode, const std::string &hint);
+    static MediaKeyType mediakeyTypeToString(media_key_e key);
+    static MediaKeyEventType mediakeyEventTypeToString(media_key_event_e status);
+};
+
+} // MediaKey
+} // DeviceAPI
+
+#endif // __TIZEN_MEDIAKEY_UTIL_H__
diff --git a/src/Mediakey/config.xml b/src/Mediakey/config.xml
new file mode 100644 (file)
index 0000000..146207c
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-mediakey.so</library-name>
+    <feature-install-uri>mediakey.install.uri</feature-install-uri>
+
+        <api-feature>
+                <name>http://tizen.org/privilege/mediakey</name>
+        </api-feature>
+
+</plugin-properties>
diff --git a/src/Mediakey/plugin_config.cpp b/src/Mediakey/plugin_config.cpp
new file mode 100644 (file)
index 0000000..ac73c05
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+static FunctionMapping createMediaKeyFunctions();
+static FunctionMapping MediaKeyFunctions = createMediaKeyFunctions();
+
+DEFINE_FUNCTION_GETTER(MediaKey, MediaKeyFunctions);
+
+static FunctionMapping createMediaKeyFunctions()
+{
+    FunctionMapping mediaKeyMapping;
+    return mediaKeyMapping;
+}
+
+} // MediaKey
+} // DeviceAPI
diff --git a/src/Mediakey/plugin_config.h b/src/Mediakey/plugin_config.h
new file mode 100644 (file)
index 0000000..9272d89
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _MEDIA_KEY_PLUGIN_CONFIG_H_
+#define _MEDIA_KEY_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+// attributes
+
+// functions
+#define MEDIA_KEY_MANAGER_API_SET_MEDIA_KEY_EVENT_LISTENER "setMediaKeyEventListener"
+#define MEDIA_KEY_MANAGER_API_UNSET_MEDIA_KEY_EVENT_LISTENER "unsetMediaKeyEventListener"
+#define MEDIA_KEY_EVENT_CALLBACK_API_ONPRESSED "onpressed"
+#define MEDIA_KEY_EVENT_CALLBACK_API_ONRELEASED "onreleased"
+
+DECLARE_FUNCTION_GETTER(MediaKey);
+
+#define MEDIA_KEY_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getMediaKeyFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _MEDIA_KEY_PLUGIN_CONFIG_H_
diff --git a/src/Mediakey/plugin_initializer.cpp b/src/Mediakey/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..27688c8
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+
+#include "JSMediaKeyManager.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace MediaKey {
+
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\MediaKey] on_widget_start_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\MediaKey] on_widget_stop_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\MediaKey] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\MediaKey] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "mediakey",
+        (js_class_template_getter)JSMediaKeyManager::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_END
+
+} // MediaKey
+} // DeviceAPI
diff --git a/src/MessagePort/CMakeLists.txt b/src/MessagePort/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0597547
--- /dev/null
@@ -0,0 +1,59 @@
+SET(TARGET_NAME ${messageport_target})
+SET(DESTINATION_NAME ${messageport_dest})
+SET(TARGET_IMPL_NAME ${messageport_impl})
+
+IF(ENABLE_OPTIONAL_MESSAGE_PORT)
+PKG_CHECK_MODULES(platform_pkgs_messageport REQUIRED message-port)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_messageport_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    ILocalMessagePort.cpp
+    IMessagePortManager.cpp
+    IRemoteMessagePort.cpp
+    MessagePortFactory.cpp
+    LocalMessagePort.cpp
+    MessagePortManager.cpp
+    MessagePortManagerProxy.cpp
+    MessagePortUtility.cpp
+    RemoteMessagePort.cpp
+    JSLocalMessagePort.cpp
+    JSMessagePortManager.cpp
+    JSRemoteMessagePort.cpp
+    LocalMessagePortController.cpp
+    MessagePortJSUtil.cpp
+    MessagePortListenerManager.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${platform_pkgs_messageport_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_MESSAGE_PORT)
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/messageport
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/MessagePort/EventLocalMessagePortAddMessagePortListener.h b/src/MessagePort/EventLocalMessagePortAddMessagePortListener.h
new file mode 100644 (file)
index 0000000..3967375
--- /dev/null
@@ -0,0 +1,117 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventLocalMessagePortAddMessagePortListener.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_EVENT_LOCAL_MESSAGE_PORT_ADD_MESSAGE_PORT_LISTENER_H_
+#define _API_MESSAGE_PORT_EVENT_LOCAL_MESSAGE_PORT_ADD_MESSAGE_PORT_LISTENER_H_
+
+#include <string>
+
+#include <Commons/IEvent.h>
+#include "EventLocalMessagePortListener.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class EventLocalMessagePortAddMessagePortListener;
+typedef std::shared_ptr<EventLocalMessagePortAddMessagePortListener> EventLocalMessagePortAddMessagePortListenerPtr;
+
+class EventLocalMessagePortAddMessagePortListener :
+        public WrtDeviceApis::Commons::IEvent<EventLocalMessagePortAddMessagePortListener>
+{
+private:
+    bool m_result;
+
+    /* parameters */
+    EventLocalMessagePortListenerEmitterPtr m_emitter;
+
+    bool m_emitterIsSet;
+
+    /* result */
+    long m_id;
+
+    bool m_idIsSet;
+
+public:
+    EventLocalMessagePortAddMessagePortListener() :
+        m_result(false),
+        m_emitterIsSet(false),
+        m_id(0),
+        m_idIsSet(false)
+    {
+    }
+
+    virtual ~EventLocalMessagePortAddMessagePortListener()
+    {
+    }
+
+    virtual void clearOnCancel()
+    {
+    }
+
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setEmitter(EventLocalMessagePortListenerEmitterPtr &value)
+    {
+        m_emitter = value;
+        m_emitterIsSet = true;
+    }
+
+    EventLocalMessagePortListenerEmitterPtr getEmitter() const
+    {
+        return m_emitter;
+    }
+
+    bool getEmitterIsSet() const
+    {
+        return m_emitterIsSet;
+    }
+
+    long getId() const
+    {
+        return m_id;
+    }
+
+    void setId(const long value)
+    {
+        m_id = value;
+        m_idIsSet = true;
+    }
+
+    bool getIdIsSet() const
+    {
+        return m_idIsSet;
+    }
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_EVENT_LOCAL_MESSAGE_PORT_ADD_MESSAGE_PORT_LISTENER_H_
diff --git a/src/MessagePort/EventLocalMessagePortListener.h b/src/MessagePort/EventLocalMessagePortListener.h
new file mode 100644 (file)
index 0000000..9884d61
--- /dev/null
@@ -0,0 +1,99 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventLocalMessagePortListener.h
+ * @version     0.1
+ * @brief
+ * ##
+ */
+
+#ifndef _API_MESSAGE_PORT_EVENT_LOCAL_MESSAGE_PORT_LISTENER_H_
+#define _API_MESSAGE_PORT_EVENT_LOCAL_MESSAGE_PORT_LISTENER_H_
+
+#include <string>
+
+#include <Commons/IEvent.h>
+#include <Commons/ListenerEvent.h>
+#include <Commons/ListenerEventEmitter.h>
+#include "IRemoteMessagePort.h"
+#include "MessagePortDataItem.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class IRemoteMessagePort;
+typedef std::shared_ptr<IRemoteMessagePort> RemoteMessagePortPtr;
+
+class EventLocalMessagePortListener : public WrtDeviceApis::Commons::ListenerEvent<EventLocalMessagePortListener>
+{
+private:
+    /* result */
+    MessagePortDataItemMapPtr m_data;
+    RemoteMessagePortPtr m_remoteMessagePort;
+
+    bool m_dataIsSet;
+    bool m_remoteMessagePortIsSet;
+
+public:
+    EventLocalMessagePortListener() :
+        m_dataIsSet(false),
+        m_remoteMessagePortIsSet(false)
+    {
+    }
+
+    void setData(const MessagePortDataItemMapPtr &data)
+    {
+        m_data = data;
+        m_dataIsSet = true;
+    }
+
+    MessagePortDataItemMapPtr getData() const
+    {
+        return m_data;
+    }
+
+    bool getDataIsSet() const
+    {
+        return m_dataIsSet;
+    }
+
+    void setRemoteMessagePort(const RemoteMessagePortPtr &remoteMessagePort)
+    {
+        m_remoteMessagePort = remoteMessagePort;
+        m_remoteMessagePortIsSet = true;
+    }
+
+    RemoteMessagePortPtr getRemoteMessagePort() const
+    {
+        return m_remoteMessagePort;
+    }
+
+    bool getRemoteMessagePortIsSet() const
+    {
+        return m_remoteMessagePortIsSet;
+    }
+};
+typedef std::shared_ptr<EventLocalMessagePortListener> EventLocalMessagePortListenerPtr;
+
+typedef WrtDeviceApis::Commons::ListenerEventEmitter<EventLocalMessagePortListener> EventLocalMessagePortListenerEmitter;
+typedef std::shared_ptr<EventLocalMessagePortListenerEmitter> EventLocalMessagePortListenerEmitterPtr;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_EVENT_LOCAL_MESSAGE_PORT_LISTENER_H_
diff --git a/src/MessagePort/EventLocalMessagePortRemoveMessagePortListener.h b/src/MessagePort/EventLocalMessagePortRemoveMessagePortListener.h
new file mode 100644 (file)
index 0000000..305ef87
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventLocalMessagePortRemoveMessagePortListener.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_EVENT_LOCAL_MESSAGE_PORT_REMOVE_MESSAGE_PORT_LISTENER_H_
+#define _API_MESSAGE_PORT_EVENT_LOCAL_MESSAGE_PORT_REMOVE_MESSAGE_PORT_LISTENER_H_
+
+#include <string>
+
+#include <Commons/IEvent.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class EventLocalMessagePortRemoveMessagePortListener;
+typedef std::shared_ptr<EventLocalMessagePortRemoveMessagePortListener> EventLocalMessagePortRemoveMessagePortListenerPtr;
+
+class EventLocalMessagePortRemoveMessagePortListener :
+        public WrtDeviceApis::Commons::IEvent<EventLocalMessagePortRemoveMessagePortListener>
+{
+private:
+    bool m_result;
+
+    /* parameters */
+    long m_id;
+
+    bool m_idIsSet;
+
+    /* result */
+
+public:
+    EventLocalMessagePortRemoveMessagePortListener() :
+        m_result(false),
+        m_id(0),
+        m_idIsSet(false)
+    {
+    }
+
+    virtual ~EventLocalMessagePortRemoveMessagePortListener()
+    {
+    }
+
+    virtual void clearOnCancel()
+    {
+    }
+
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    long getId() const
+    {
+        return m_id;
+    }
+
+    void setId(const long value)
+    {
+        m_id = value;
+        m_idIsSet = true;
+    }
+
+    bool getIdIsSet() const
+    {
+        return m_idIsSet;
+    }
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_EVENT_LOCAL_MESSAGE_PORT_REMOVE_MESSAGE_PORT_LISTENER_H_
diff --git a/src/MessagePort/EventMessagePortManagerRequestLocalMessagePort.h b/src/MessagePort/EventMessagePortManagerRequestLocalMessagePort.h
new file mode 100644 (file)
index 0000000..73ce7dd
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventMessagePortManagerRequestLocalMessagePort.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_LOCAL_MESSAGE_PORT_H_
+#define _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_LOCAL_MESSAGE_PORT_H_
+
+#include <string>
+
+#include <Commons/IEvent.h>
+#include "ILocalMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class ILocalMessagePort;
+typedef std::shared_ptr<ILocalMessagePort> LocalMessagePortPtr;
+
+class EventMessagePortManagerRequestLocalMessagePort : public WrtDeviceApis::Commons::IEvent<EventMessagePortManagerRequestLocalMessagePort>
+{
+private:
+    bool m_result;
+
+    /* parameters */
+    std::string m_localMessagePortName;
+
+    bool m_localMessagePortNameIsSet;
+
+    /* result */
+    LocalMessagePortPtr m_localMessagePort;
+
+    bool m_localMessagePortIsSet;
+
+public:
+    EventMessagePortManagerRequestLocalMessagePort() :
+        m_result(false),
+        m_localMessagePortNameIsSet(false),
+        m_localMessagePortIsSet(false)
+    {
+    }
+
+    virtual ~EventMessagePortManagerRequestLocalMessagePort()
+    {
+    }
+
+    virtual void clearOnCancel()
+    {
+    }
+
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    std::string getLocalMessagePortName() const
+    {
+        return m_localMessagePortName;
+    }
+
+    void setLocalMessagePortName(const std::string &value)
+    {
+        m_localMessagePortName = value;
+        m_localMessagePortNameIsSet = true;
+    }
+
+    bool getLocalMessagePortNameIsSet() const
+    {
+        return m_localMessagePortNameIsSet;
+    }
+
+    LocalMessagePortPtr getLocalMessagePort() const
+    {
+        return m_localMessagePort;
+    }
+
+    void setLocalMessagePort(const LocalMessagePortPtr &value)
+    {
+        m_localMessagePort = value;
+        m_localMessagePortIsSet = true;
+    }
+
+    bool getLocalMessagePortIsSet() const
+    {
+        return m_localMessagePortIsSet;
+    }
+};
+
+typedef std::shared_ptr<EventMessagePortManagerRequestLocalMessagePort> EventMessagePortManagerRequestLocalMessagePortPtr;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_LOCAL_MESSAGE_PORT_H_
+
diff --git a/src/MessagePort/EventMessagePortManagerRequestRemoteMessagePort.h b/src/MessagePort/EventMessagePortManagerRequestRemoteMessagePort.h
new file mode 100644 (file)
index 0000000..1584413
--- /dev/null
@@ -0,0 +1,137 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventMessagePortManagerRequestRemoteMessagePort.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_REMOTE_MESSAGE_PORT_H_
+#define _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_REMOTE_MESSAGE_PORT_H_
+
+#include <string>
+
+#include <Commons/IEvent.h>
+#include "IRemoteMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class IRemoteMessagePort;
+typedef std::shared_ptr<IRemoteMessagePort> RemoteMessagePortPtr;
+
+class EventMessagePortManagerRequestRemoteMessagePort : public WrtDeviceApis::Commons::IEvent<EventMessagePortManagerRequestRemoteMessagePort>
+{
+private:
+    bool m_result;
+
+    /* parameters */
+    std::string m_appId;
+    std::string m_remoteMessagePortName;
+
+    bool m_appIdIsSet;
+    bool m_remoteMessagePortNameIsSet;
+
+    /* result */
+    RemoteMessagePortPtr m_remoteMessagePort;
+
+    bool m_remoteMessagePortIsSet;
+
+public:
+    EventMessagePortManagerRequestRemoteMessagePort() :
+        m_result(false),
+        m_appIdIsSet(false),
+        m_remoteMessagePortNameIsSet(false),
+        m_remoteMessagePortIsSet(false)
+    {
+    }
+
+    virtual ~EventMessagePortManagerRequestRemoteMessagePort()
+    {
+    }
+
+    virtual void clearOnCancel()
+    {
+    }
+
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    std::string getAppId() const
+    {
+        return m_appId;
+    }
+
+    void setAppId(const std::string &value)
+    {
+        m_appId = value;
+        m_appIdIsSet = true;
+    }
+
+    bool getAppIdIsSet() const
+    {
+        return m_appIdIsSet;
+    }
+
+    std::string getRemoteMessagePortName() const
+    {
+        return m_remoteMessagePortName;
+    }
+
+    void setRemoteMessagePortName(const std::string &value)
+    {
+        m_remoteMessagePortName = value;
+        m_remoteMessagePortNameIsSet = true;
+    }
+
+    bool getRemoteMessagePortNameIsSet() const
+    {
+        return m_remoteMessagePortNameIsSet;
+    }
+
+    RemoteMessagePortPtr getRemoteMessagePort() const
+    {
+        return m_remoteMessagePort;
+    }
+
+    void setRemoteMessagePort(const RemoteMessagePortPtr &value)
+    {
+        m_remoteMessagePort = value;
+        m_remoteMessagePortIsSet = true;
+    }
+
+    bool getRemoteMessagePortIsSet() const
+    {
+        return m_remoteMessagePortIsSet;
+    }
+};
+
+typedef std::shared_ptr<EventMessagePortManagerRequestRemoteMessagePort> EventMessagePortManagerRequestRemoteMessagePortPtr;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_REMOTE_MESSAGE_PORT_H_
+
diff --git a/src/MessagePort/EventMessagePortManagerRequestTrustedLocalMessagePort.h b/src/MessagePort/EventMessagePortManagerRequestTrustedLocalMessagePort.h
new file mode 100644 (file)
index 0000000..b5a6e8f
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventMessagePortManagerRequestTrustedLocalMessagePort.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_TRUSTED_LOCAL_MESSAGE_PORT_H_
+#define _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_TRUSTED_LOCAL_MESSAGE_PORT_H_
+
+#include <string>
+
+#include <Commons/IEvent.h>
+#include "ILocalMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class ILocalMessagePort;
+typedef std::shared_ptr<ILocalMessagePort> LocalMessagePortPtr;
+
+class EventMessagePortManagerRequestTrustedLocalMessagePort : public WrtDeviceApis::Commons::IEvent<EventMessagePortManagerRequestTrustedLocalMessagePort>
+{
+private:
+    bool m_result;
+
+    /* parameters */
+    std::string m_localMessagePortName;
+
+    bool m_localMessagePortNameIsSet;
+
+    /* result */
+    LocalMessagePortPtr m_localMessagePort;
+
+    bool m_localMessagePortIsSet;
+
+public:
+    EventMessagePortManagerRequestTrustedLocalMessagePort() :
+        m_result(false),
+        m_localMessagePortNameIsSet(false),
+        m_localMessagePortIsSet(false)
+    {
+    }
+
+    virtual ~EventMessagePortManagerRequestTrustedLocalMessagePort()
+    {
+    }
+
+    virtual void clearOnCancel()
+    {
+    }
+
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    std::string getLocalMessagePortName() const
+    {
+        return m_localMessagePortName;
+    }
+
+    void setLocalMessagePortName(const std::string &value)
+    {
+        m_localMessagePortName = value;
+        m_localMessagePortNameIsSet = true;
+    }
+
+    bool getLocalMessagePortNameIsSet() const
+    {
+        return m_localMessagePortNameIsSet;
+    }
+
+    LocalMessagePortPtr getLocalMessagePort() const
+    {
+        return m_localMessagePort;
+    }
+
+    void setLocalMessagePort(const LocalMessagePortPtr &value)
+    {
+        m_localMessagePort = value;
+        m_localMessagePortIsSet = true;
+    }
+
+    bool getLocalMessagePortIsSet() const
+    {
+        return m_localMessagePortIsSet;
+    }
+};
+
+typedef std::shared_ptr<EventMessagePortManagerRequestTrustedLocalMessagePort> EventMessagePortManagerRequestTrustedLocalMessagePortPtr;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_TRUSTED_LOCAL_MESSAGE_PORT_H_
+
diff --git a/src/MessagePort/EventMessagePortManagerRequestTrustedRemoteMessagePort.h b/src/MessagePort/EventMessagePortManagerRequestTrustedRemoteMessagePort.h
new file mode 100644 (file)
index 0000000..1592b9c
--- /dev/null
@@ -0,0 +1,137 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventMessagePortManagerRequestTrustedRemoteMessagePort.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_TRUSTED_REMOTE_MESSAGE_PORT_H_
+#define _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_TRUSTED_REMOTE_MESSAGE_PORT_H_
+
+#include <string>
+
+#include <Commons/IEvent.h>
+#include "IRemoteMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class IRemoteMessagePort;
+typedef std::shared_ptr<IRemoteMessagePort> RemoteMessagePortPtr;
+
+class EventMessagePortManagerRequestTrustedRemoteMessagePort : public WrtDeviceApis::Commons::IEvent<EventMessagePortManagerRequestTrustedRemoteMessagePort>
+{
+private:
+    bool m_result;
+
+    /* parameters */
+    std::string m_appId;
+    std::string m_remoteMessagePortName;
+
+    bool m_appIdIsSet;
+    bool m_remoteMessagePortNameIsSet;
+
+    /* result */
+    RemoteMessagePortPtr m_remoteMessagePort;
+
+    bool m_remoteMessagePortIsSet;
+
+public:
+    EventMessagePortManagerRequestTrustedRemoteMessagePort() :
+        m_result(false),
+        m_appIdIsSet(false),
+        m_remoteMessagePortNameIsSet(false),
+        m_remoteMessagePortIsSet(false)
+    {
+    }
+
+    virtual ~EventMessagePortManagerRequestTrustedRemoteMessagePort()
+    {
+    }
+
+    virtual void clearOnCancel()
+    {
+    }
+
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    std::string getAppId() const
+    {
+        return m_appId;
+    }
+
+    void setAppId(const std::string &value)
+    {
+        m_appId = value;
+        m_appIdIsSet = true;
+    }
+
+    bool getAppIdIsSet() const
+    {
+        return m_appIdIsSet;
+    }
+
+    std::string getRemoteMessagePortName() const
+    {
+        return m_remoteMessagePortName;
+    }
+
+    void setRemoteMessagePortName(const std::string &value)
+    {
+        m_remoteMessagePortName = value;
+        m_remoteMessagePortNameIsSet = true;
+    }
+
+    bool getRemoteMessagePortNameIsSet() const
+    {
+        return m_remoteMessagePortNameIsSet;
+    }
+
+    RemoteMessagePortPtr getRemoteMessagePort() const
+    {
+        return m_remoteMessagePort;
+    }
+
+    void setRemoteMessagePort(const RemoteMessagePortPtr &value)
+    {
+        m_remoteMessagePort = value;
+        m_remoteMessagePortIsSet = true;
+    }
+
+    bool getRemoteMessagePortIsSet() const
+    {
+        return m_remoteMessagePortIsSet;
+    }
+};
+
+typedef std::shared_ptr<EventMessagePortManagerRequestTrustedRemoteMessagePort> EventMessagePortManagerRequestTrustedRemoteMessagePortPtr;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_EVENT_MESSAGE_PORT_MANAGER_REQUEST_REMOTE_MESSAGE_PORT_H_
+
diff --git a/src/MessagePort/EventRemoteMessagePortSendMessage.h b/src/MessagePort/EventRemoteMessagePortSendMessage.h
new file mode 100644 (file)
index 0000000..2c5e922
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EventRemoteMessagePortSendMessage.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_EVENT_REMOTE_MESSAGE_PORT_SEND_MESSAGE_H_
+#define _API_MESSAGE_PORT_EVENT_REMOTE_MESSAGE_PORT_SEND_MESSAGE_H_
+
+#include <string>
+#include <map>
+
+#include <Commons/IEvent.h>
+#include "ILocalMessagePort.h"
+#include "MessagePortDataItem.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class ILocalMessagePort;
+typedef std::shared_ptr<ILocalMessagePort> LocalMessagePortPtr;
+
+class EventRemoteMessagePortSendMessage;
+typedef std::shared_ptr<EventRemoteMessagePortSendMessage> EventRemoteMessagePortSendMessagePtr;
+
+class EventRemoteMessagePortSendMessage :
+        public WrtDeviceApis::Commons::IEvent<EventRemoteMessagePortSendMessage>
+{
+private:
+    bool m_result;
+
+    /* parameters */
+    MessagePortDataItemMapPtr m_data;
+    LocalMessagePortPtr m_localMessagePort;
+
+    bool m_dataIsSet;
+    bool m_localMessagePortIsSet;
+
+    /* result */
+
+public:
+    EventRemoteMessagePortSendMessage() :
+        m_result(false),
+        m_dataIsSet(false),
+        m_localMessagePortIsSet(false)
+    {
+    }
+
+    virtual ~EventRemoteMessagePortSendMessage()
+    {
+    }
+
+    virtual void clearOnCancel()
+    {
+    }
+
+    void setResult(bool value)
+    {
+        m_result = value;
+    }
+
+    bool getResult() const
+    {
+        return m_result;
+    }
+
+    void setData(const MessagePortDataItemMapPtr &data)
+    {
+        m_data = data;
+        m_dataIsSet = true;
+    }
+
+    MessagePortDataItemMapPtr getData() const
+    {
+        return m_data;
+    }
+
+    bool getDataIsSet() const
+    {
+        return m_dataIsSet;
+    }
+
+    void setLocalMessagePort(const LocalMessagePortPtr &localMessagePort)
+    {
+        m_localMessagePort = localMessagePort;
+        m_localMessagePortIsSet = true;
+    }
+
+    LocalMessagePortPtr getLocalMessagePort() const
+    {
+        return m_localMessagePort;
+    }
+
+    bool getLocalMessagePortIsSet() const
+    {
+        return m_localMessagePortIsSet;
+    }
+
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_EVENT_REMOTE_MESSAGE_PORT_SEND_MESSAGE_H_
diff --git a/src/MessagePort/ILocalMessagePort.cpp b/src/MessagePort/ILocalMessagePort.cpp
new file mode 100644 (file)
index 0000000..d7ad41a
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ILocalMessagePort.cpp
+ * @version     0.1
+ * @brief
+ */
+
+#include "ILocalMessagePort.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace WrtDeviceApis::Commons;
+
+ILocalMessagePort::ILocalMessagePort() :
+        EventRequestReceiver< EventLocalMessagePortAddMessagePortListener >(ThreadEnum::NULL_THREAD),
+        EventRequestReceiver< EventLocalMessagePortRemoveMessagePortListener >(ThreadEnum::NULL_THREAD)
+{
+}
+
+ILocalMessagePort::~ILocalMessagePort()
+{
+}
+
+void ILocalMessagePort::addMessagePortListener(const EventLocalMessagePortAddMessagePortListenerPtr &event)
+{
+    //post event to PLATFORM implementation
+    EventRequestReceiver< EventLocalMessagePortAddMessagePortListener >::PostRequest(event);
+}
+
+void ILocalMessagePort::removeMessagePortListener(const EventLocalMessagePortRemoveMessagePortListenerPtr &event)
+{
+    //post event to PLATFORM implementation
+    EventRequestReceiver< EventLocalMessagePortRemoveMessagePortListener >::PostRequest(event);
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/ILocalMessagePort.h b/src/MessagePort/ILocalMessagePort.h
new file mode 100644 (file)
index 0000000..584aee2
--- /dev/null
@@ -0,0 +1,66 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        ILocalMessagePort.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_ILOCAL_MESSAGE_PORT_H_
+#define _API_MESSAGE_PORT_ILOCAL_MESSAGE_PORT_H_
+
+
+#include <Commons/EventReceiver.h>
+#include "EventLocalMessagePortAddMessagePortListener.h"
+#include "EventLocalMessagePortRemoveMessagePortListener.h"
+#include "IRemoteMessagePort.h"
+#include "MessagePortDataItem.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class ILocalMessagePort;
+typedef std::shared_ptr<ILocalMessagePort> LocalMessagePortPtr;
+
+class ILocalMessagePort :
+        public WrtDeviceApis::Commons::EventRequestReceiver< EventLocalMessagePortAddMessagePortListener >,
+        public WrtDeviceApis::Commons::EventRequestReceiver< EventLocalMessagePortRemoveMessagePortListener >
+{
+public:
+    ILocalMessagePort();
+    virtual ~ILocalMessagePort();
+
+    virtual void addMessagePortListener(const EventLocalMessagePortAddMessagePortListenerPtr &event);
+    virtual void removeMessagePortListener(const EventLocalMessagePortRemoveMessagePortListenerPtr &event);
+
+    virtual std::string getMessagePortName() const = 0;
+    virtual void        setMessagePortName(const std::string &value) = 0;
+    virtual bool        getIsTrusted() const = 0;
+    virtual void        setIsTrusted(const bool &value) = 0;
+
+    virtual void OnMessageReceived(MessagePortDataItemMapPtr &data, RemoteMessagePortPtr &remoteMessagePort) = 0;
+
+protected:
+    virtual void OnRequestReceived(const EventLocalMessagePortAddMessagePortListenerPtr &event) = 0;
+    virtual void OnRequestReceived(const EventLocalMessagePortRemoveMessagePortListenerPtr &event) = 0;
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_ILOCAL_MESSAGE_PORT_H_
diff --git a/src/MessagePort/IMessagePortManager.cpp b/src/MessagePort/IMessagePortManager.cpp
new file mode 100644 (file)
index 0000000..1198e95
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        IMessagePortManager.cpp
+ * @version     0.1
+ * @brief
+ * ##
+ */
+
+#include <Commons/ThreadPool.h>
+#include "IMessagePortManager.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace WrtDeviceApis::Commons;
+
+IMessagePortManager::IMessagePortManager() :
+        EventRequestReceiver< EventMessagePortManagerRequestLocalMessagePort >(ThreadEnum::NULL_THREAD),
+        EventRequestReceiver< EventMessagePortManagerRequestTrustedLocalMessagePort >(ThreadEnum::NULL_THREAD),
+        EventRequestReceiver< EventMessagePortManagerRequestRemoteMessagePort >(ThreadEnum::NULL_THREAD),
+        EventRequestReceiver< EventMessagePortManagerRequestTrustedRemoteMessagePort >(ThreadEnum::NULL_THREAD)
+{
+    //Nothing to do
+}
+
+IMessagePortManager::~IMessagePortManager()
+{
+    //Nothing to do
+}
+
+void IMessagePortManager::requestLocalMessagePort(const EventMessagePortManagerRequestLocalMessagePortPtr &event)
+{
+    //post event to PLATFORM implementation
+    EventRequestReceiver< EventMessagePortManagerRequestLocalMessagePort >::PostRequest(event);
+}
+
+void IMessagePortManager::requestTrustedLocalMessagePort(const EventMessagePortManagerRequestTrustedLocalMessagePortPtr &event)
+{
+    //post event to PLATFORM implementation
+    EventRequestReceiver< EventMessagePortManagerRequestTrustedLocalMessagePort >::PostRequest(event);
+}
+
+void IMessagePortManager::requestRemoteMessagePort(const EventMessagePortManagerRequestRemoteMessagePortPtr &event)
+{
+    //post event to PLATFORM implementation
+    EventRequestReceiver< EventMessagePortManagerRequestRemoteMessagePort >::PostRequest(event);
+}
+
+void IMessagePortManager::requestTrustedRemoteMessagePort(const EventMessagePortManagerRequestTrustedRemoteMessagePortPtr &event)
+{
+    //post event to PLATFORM implementation
+    EventRequestReceiver< EventMessagePortManagerRequestTrustedRemoteMessagePort >::PostRequest(event);
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/IMessagePortManager.h b/src/MessagePort/IMessagePortManager.h
new file mode 100644 (file)
index 0000000..720f18e
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        IMessagePortManager.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_IMESSAGE_PORT_MANAGER_H_
+#define _API_MESSAGE_PORT_IMESSAGE_PORT_MANAGER_H_
+
+
+#include <Commons/EventReceiver.h>
+#include "EventMessagePortManagerRequestLocalMessagePort.h"
+#include "EventMessagePortManagerRequestTrustedLocalMessagePort.h"
+#include "EventMessagePortManagerRequestRemoteMessagePort.h"
+#include "EventMessagePortManagerRequestTrustedRemoteMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class IMessagePortManager :
+    public WrtDeviceApis::Commons::EventRequestReceiver< EventMessagePortManagerRequestLocalMessagePort >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< EventMessagePortManagerRequestTrustedLocalMessagePort >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< EventMessagePortManagerRequestRemoteMessagePort >,
+    public WrtDeviceApis::Commons::EventRequestReceiver< EventMessagePortManagerRequestTrustedRemoteMessagePort >
+{
+public:
+    IMessagePortManager();
+    virtual ~IMessagePortManager();
+    virtual void requestLocalMessagePort(const EventMessagePortManagerRequestLocalMessagePortPtr &event);
+    virtual void requestTrustedLocalMessagePort(const EventMessagePortManagerRequestTrustedLocalMessagePortPtr &event);
+    virtual void requestRemoteMessagePort(const EventMessagePortManagerRequestRemoteMessagePortPtr &event);
+    virtual void requestTrustedRemoteMessagePort(const EventMessagePortManagerRequestTrustedRemoteMessagePortPtr &event);
+
+protected:
+    virtual void OnRequestReceived(const EventMessagePortManagerRequestLocalMessagePortPtr &event) = 0;
+    virtual void OnRequestReceived(const EventMessagePortManagerRequestTrustedLocalMessagePortPtr &event) = 0;
+    virtual void OnRequestReceived(const EventMessagePortManagerRequestRemoteMessagePortPtr &event) = 0;
+    virtual void OnRequestReceived(const EventMessagePortManagerRequestTrustedRemoteMessagePortPtr &event) = 0;
+};
+
+typedef std::shared_ptr<IMessagePortManager> MessagePortManagerPtr;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_IMESSAGE_PORT_MANAGER_H_
diff --git a/src/MessagePort/IRemoteMessagePort.cpp b/src/MessagePort/IRemoteMessagePort.cpp
new file mode 100644 (file)
index 0000000..2f5aa93
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        IRemoteMessagePort.cpp
+ * @version     0.1
+ * @brief
+ */
+
+#include "IRemoteMessagePort.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace WrtDeviceApis::Commons;
+
+IRemoteMessagePort::IRemoteMessagePort() :
+        EventRequestReceiver< EventRemoteMessagePortSendMessage >(ThreadEnum::NULL_THREAD)
+{
+}
+
+IRemoteMessagePort::~IRemoteMessagePort()
+{
+}
+
+void IRemoteMessagePort::sendMessage(const EventRemoteMessagePortSendMessagePtr &event)
+{
+    //post event to PLATFORM implementation
+    EventRequestReceiver< EventRemoteMessagePortSendMessage >::PostRequest(event);
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/IRemoteMessagePort.h b/src/MessagePort/IRemoteMessagePort.h
new file mode 100755 (executable)
index 0000000..f682426
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        IRemoteMessagePort.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _API_MESSAGE_PORT_IREMOTE_MESSAGE_PORT_H_
+#define _API_MESSAGE_PORT_IREMOTE_MESSAGE_PORT_H_
+
+#include <Commons/EventReceiver.h>
+#include "EventRemoteMessagePortSendMessage.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class IRemoteMessagePort;
+typedef std::shared_ptr<IRemoteMessagePort> RemoteMessagePortPtr;
+
+class IRemoteMessagePort :
+        public WrtDeviceApis::Commons::EventRequestReceiver< EventRemoteMessagePortSendMessage >
+{
+public:
+    IRemoteMessagePort();
+    virtual ~IRemoteMessagePort();
+
+    virtual void sendMessage(const EventRemoteMessagePortSendMessagePtr &event);
+
+    virtual std::string getMessagePortName() const = 0;
+    virtual void        setMessagePortName(const std::string &value) = 0;
+    virtual std::string getAppId() const = 0;
+    virtual void        setAppId(const std::string &value) = 0;
+    virtual bool        getIsTrusted() const = 0;
+    virtual void        setIsTrusted(const bool &value) = 0;
+
+protected:
+    virtual void    OnRequestReceived(const EventRemoteMessagePortSendMessagePtr &event) = 0;
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_IREMOTE_MESSAGE_PORT_H_
diff --git a/src/MessagePort/JSLocalMessagePort.cpp b/src/MessagePort/JSLocalMessagePort.cpp
new file mode 100755 (executable)
index 0000000..8c75c7f
--- /dev/null
@@ -0,0 +1,381 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSLocalMessagePort.cpp
+ * @version     0.1
+ * @brief       Implementation of the JSLocalMessagePort class
+ */
+
+#include "JSLocalMessagePort.h"
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <ArgumentValidator.h>
+#include <JSWebAPIErrorFactory.h>
+#include <TimeTracer.h>
+#include "EventLocalMessagePortAddMessagePortListener.h"
+#include "EventLocalMessagePortRemoveMessagePortListener.h"
+#include "MessagePortListenerManager.h"
+#include "MessagePortJSUtil.h"
+#include <Logger.h>
+
+#define TIZEN_LOCAL_MESSAGE_PORT                                "LocalMessagePort"
+
+#define TIZEN_LOCAL_MESSAGE_PORT_MESSAGE_PORT_NAME              "messagePortName"
+#define TIZEN_LOCAL_MESSAGE_PORT_IS_TRUSTED                     "isTrusted"
+
+#define TIZEN_LOCAL_MESSAGE_PORT_ADD_MESSAGE_PORT_LISTENER      "addMessagePortListener"
+#define TIZEN_LOCAL_MESSAGE_PORT_REMOVE_MESSAGE_PORT_LISTENER   "removeMessagePortListener"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+JSClassRef JSLocalMessagePort::m_jsClassRef = NULL;
+
+JSClassDefinition JSLocalMessagePort::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_LOCAL_MESSAGE_PORT,
+    0,
+    m_property,
+    m_function,
+    Initialize,
+    Finalize,
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL, //ConvertToType,
+};
+
+JSStaticValue JSLocalMessagePort::m_property[] = {
+    { TIZEN_LOCAL_MESSAGE_PORT_MESSAGE_PORT_NAME, getMessagePortName, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_LOCAL_MESSAGE_PORT_IS_TRUSTED, getIsTrusted, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSLocalMessagePort::m_function[] = {
+    { TIZEN_LOCAL_MESSAGE_PORT_ADD_MESSAGE_PORT_LISTENER, addMessagePortListener, kJSPropertyAttributeNone },
+    { TIZEN_LOCAL_MESSAGE_PORT_REMOVE_MESSAGE_PORT_LISTENER, removeMessagePortListener, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSLocalMessagePort::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+const JSClassRef JSLocalMessagePort::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSLocalMessagePort::Initialize(JSContextRef context,
+        JSObjectRef object)
+{
+}
+
+void JSLocalMessagePort::Finalize(JSObjectRef object)
+{
+    LocalMessagePortController *priv =
+        static_cast<LocalMessagePortController*>(JSObjectGetPrivate(object));
+
+    delete priv;
+}
+
+bool JSLocalMessagePort::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+LocalMessagePortPtr JSLocalMessagePort::getLocalMessagePort(JSContextRef context, JSValueRef value)
+{
+    if (!isObjectOfClass(context, value)) {
+        LOGE("value is not a LocalMessagePort object");
+        throw TypeMismatchException("value is not a LocalMessagePort object");
+    }
+    JSObjectRef object = JSValueToObject(context, value, NULL);
+    if (!object) {
+        LOGE("value is not a object");
+        throw TypeMismatchException("value is not a object");
+    }
+    LocalMessagePortController *priv =
+            static_cast<LocalMessagePortController*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("cannot get priv object from LocalMessagePort object");
+        throw TypeMismatchException(
+                "cannot get priv object from LocalMessagePort object");
+    }
+    return priv->getObject();
+}
+
+LocalMessagePortPtr JSLocalMessagePort::getPrivData(JSObjectRef object)
+{
+    LocalMessagePortController *priv =
+        static_cast<LocalMessagePortController*>(JSObjectGetPrivate(object));
+
+    if (priv)
+        return priv->getObject();
+
+    Throw(NullPointerException);
+}
+
+JSValueRef JSLocalMessagePort::getMessagePortName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try
+    {
+        LocalMessagePortPtr localMessagePort = getPrivData(object);
+        return JSUtil::toJSValueRef(context, localMessagePort->getMessagePortName());
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGW("trying to get incorrect value");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSLocalMessagePort::getIsTrusted(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try
+    {
+        LocalMessagePortPtr localMessagePort = getPrivData(object);
+        return JSUtil::toJSValueRef(context, localMessagePort->getIsTrusted());
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGW("trying to get incorrect value");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSLocalMessagePort::addMessagePortListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    LocalMessagePortPtr localMessagePort;
+    JSContextRef gContext;
+    LocalMessagePortController *controller;
+
+    try
+    {
+        controller = static_cast<LocalMessagePortController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            LOGE("Wrong object");
+            throw TypeMismatchException("Wrong object");
+        }
+        localMessagePort = controller->getObject();
+        gContext = controller->getContext();
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("No private object");
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    JSValueRef listener = NULL;
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    try
+    {
+        listener = validator.toFunction(0, false);
+    }
+    catch(BasePlatformException &e)
+    {
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    JSCallbackManagerPtr callbackManager = JSCallbackManager::createObject(gContext);
+
+    callbackManager->setOnSuccess(listener);
+
+    EventLocalMessagePortListenerEmitterPtr emitter(new EventLocalMessagePortListenerEmitter());
+
+    emitter->setEventPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+    emitter->setListener(controller);
+
+    EventLocalMessagePortAddMessagePortListenerPtr dplEvent(new EventLocalMessagePortAddMessagePortListener());
+
+    dplEvent->setEmitter(emitter);
+    dplEvent->setForSynchronousCall();
+
+    Try
+    {
+        localMessagePort->addMessagePortListener(dplEvent);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Plugin's internal error"));
+    }
+
+    if (!dplEvent->getResult() || !dplEvent->getIdIsSet())
+    {
+        switch (dplEvent->getExceptionCode())
+        {
+        case ExceptionCodes::InvalidArgumentException:
+            return JSWebAPIErrorFactory::postException(context, exception,
+                    UnknownException("Plugin's internal error."));
+        case ExceptionCodes::PlatformException:
+            return JSWebAPIErrorFactory::postException(context, exception,
+                    UnknownException("The method cannot proceed due to a severe system error."));
+        default:
+            return JSWebAPIErrorFactory::postException(context, exception,
+                    UnknownException("Internal error"));
+        }
+    }
+
+    long watchId = dplEvent->getId();
+
+    MessagePortsChangeListenerCancellerPtr canceller = MessagePortsChangeListenerCancellerPtr(new MessagePortsChangeListenerCanceller(gContext, thisObject, watchId));
+    DeviceAPI::Common::IListenerItemPtr listenerItem = std::static_pointer_cast<DeviceAPI::Common::IListenerItem>(canceller);
+    MessagePortListenerManagerSingleton::Instance().registerListener(listenerItem, gContext);
+
+    JSValueRef result;
+    try
+    {
+        result = JSUtil::toJSValueRef(context, watchId);
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("Error on conversion : %s", e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Internal error"));
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return result;
+}
+
+JSValueRef JSLocalMessagePort::removeMessagePortListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    LocalMessagePortPtr localMessagePort;
+    JSContextRef gContext;
+    LocalMessagePortController *controller;
+
+    try
+    {
+        controller = static_cast<LocalMessagePortController*>(JSObjectGetPrivate(thisObject));
+        if (!controller) {
+            LOGE("Wrong object");
+            throw TypeMismatchException("Wrong object");
+        }
+        localMessagePort = controller->getObject();
+        gContext = controller->getContext();
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("No private object");
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    long watchId = 0;
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    try
+    {
+        watchId = validator.toLong(0, false);
+    }
+    catch(BasePlatformException &e)
+    {
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    EventLocalMessagePortRemoveMessagePortListenerPtr dplEvent(new EventLocalMessagePortRemoveMessagePortListener());
+
+    dplEvent->setId(watchId);
+    dplEvent->setForSynchronousCall();
+
+    Try
+    {
+        localMessagePort->removeMessagePortListener(dplEvent);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Internal error"));
+    }
+
+    MessagePortsChangeListenerCancellerPtr canceller =
+            MessagePortsChangeListenerCancellerPtr(new MessagePortsChangeListenerCanceller(gContext, thisObject, watchId));
+    DeviceAPI::Common::IListenerItemPtr listenerItem = std::static_pointer_cast<DeviceAPI::Common::IListenerItem>(canceller);
+    MessagePortListenerManagerSingleton::Instance().unregisterListener(listenerItem);
+
+    if (!dplEvent->getResult())
+    {
+        stringstream oss;
+        switch (dplEvent->getExceptionCode())
+        {
+        case ExceptionCodes::InvalidArgumentException:
+            return JSWebAPIErrorFactory::postException(context, exception,
+                    InvalidValuesException(oss.str().c_str()));
+        case ExceptionCodes::NotFoundException:
+            oss << "No watchId (" << watchId << ") has been registered.";
+            return JSWebAPIErrorFactory::postException(context, exception,
+                    NotFoundException(oss.str().c_str()));
+        case ExceptionCodes::PlatformException:
+            return JSWebAPIErrorFactory::postException(context, exception,
+                    UnknownException("The method cannot proceed due to a severe system error."));
+        default:
+            return JSWebAPIErrorFactory::postException(context, exception,
+                    UnknownException("Internal error."));
+        }
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/JSLocalMessagePort.h b/src/MessagePort/JSLocalMessagePort.h
new file mode 100755 (executable)
index 0000000..a09ddee
--- /dev/null
@@ -0,0 +1,95 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSLocalMessagePort.cpp
+ * @version     0.1
+ * @brief       Declaration of the JSLocalMessagePort class
+ */
+
+#ifndef _TIZEN_MESSAGE_PORT_JS_LOCAL_MESSAGE_PORT_H_
+#define _TIZEN_MESSAGE_PORT_JS_LOCAL_MESSAGE_PORT_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "ILocalMessagePort.h"
+#include "LocalMessagePortController.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class JSLocalMessagePort
+{
+public:
+
+    static const JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+    static LocalMessagePortPtr getLocalMessagePort(JSContextRef context, JSValueRef value);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void Initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void Finalize(JSObjectRef object);
+
+    static JSClassDefinition m_classInfo;
+
+    static JSStaticFunction m_function[];
+
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    static LocalMessagePortPtr getPrivData(JSObjectRef object);
+
+    static JSValueRef getMessagePortName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsTrusted(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef addMessagePortListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeMessagePortListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _TIZEN_MESSAGE_PORT_JS_LOCAL_MESSAGE_PORT_H_
diff --git a/src/MessagePort/JSMessagePortManager.cpp b/src/MessagePort/JSMessagePortManager.cpp
new file mode 100755 (executable)
index 0000000..c0d2ae7
--- /dev/null
@@ -0,0 +1,569 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSMessagePortManager.cpp
+ * @version     0.1
+ * @brief       Implementation of the JSMessagePortManager class
+ */
+
+#include "JSMessagePortManager.h"
+
+#include <CommonsJavaScript/Validator.h>
+#include <ArgumentValidator.h>
+#include <JSWebAPIErrorFactory.h>
+#include <TimeTracer.h>
+#include "IMessagePortManager.h"
+#include "MessagePortFactory.h"
+#include "JSLocalMessagePort.h"
+#include "JSRemoteMessagePort.h"
+#include "MessagePortJSUtil.h"
+#include <Logger.h>
+
+#define CLASS_NAME "MessagePortManager"
+
+#define CHANNEL_FUNC_REQUEST_LOCAL_MESSAGE_PORT             "requestLocalMessagePort"
+#define CHANNEL_FUNC_REQUEST_TRUSTED_LOCAL_MESSAGE_PORT     "requestTrustedLocalMessagePort"
+#define CHANNEL_FUNC_REQUEST_REMOTE_MESSAGE_PORT            "requestRemoteMessagePort"
+#define CHANNEL_FUNC_REQUEST_TRUSTED_REMOTE_MESSAGE_PORT    "requestTrustedRemoteMessagePort"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+JSClassDefinition JSMessagePortManager::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    CLASS_NAME,
+    NULL,
+    m_property,
+    m_functions,
+    Initialize,
+    Finalize,
+    NULL, //hasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL, //ConvertToType,
+};
+
+JSStaticValue JSMessagePortManager::m_property[] = {
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSMessagePortManager::m_functions[] =
+{
+    { CHANNEL_FUNC_REQUEST_LOCAL_MESSAGE_PORT, requestLocalMessagePort, kJSPropertyAttributeNone },
+    { CHANNEL_FUNC_REQUEST_TRUSTED_LOCAL_MESSAGE_PORT, requestTrustedLocalMessagePort, kJSPropertyAttributeNone },
+    { CHANNEL_FUNC_REQUEST_REMOTE_MESSAGE_PORT, requestRemoteMessagePort, kJSPropertyAttributeNone },
+    { CHANNEL_FUNC_REQUEST_TRUSTED_REMOTE_MESSAGE_PORT, requestTrustedRemoteMessagePort, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSMessagePortManager::m_classRef = JSClassCreate(&m_classInfo);
+
+JSClassRef JSMessagePortManager::getClassRef() {
+    if (!m_classRef)
+        m_classRef = JSClassCreate(&m_classInfo);
+
+    return m_classRef;
+}
+
+void JSMessagePortManager::Initialize(JSContextRef context, JSObjectRef object)
+{
+    JSMessagePortManagerPriv *prevPriv =
+            static_cast<JSMessagePortManagerPriv*>(JSObjectGetPrivate(object));
+    if (prevPriv != NULL)
+        delete prevPriv;
+
+    MessagePortManagerPtr messagePortManager =
+            MessagePortFactory::getInstance().createMessagePortManager();
+    JSMessagePortManagerPriv *priv =
+            new JSMessagePortManagerPriv(context, messagePortManager);
+
+    if (!JSObjectSetPrivate(object, priv))
+        delete priv;
+}
+
+void JSMessagePortManager::Finalize(JSObjectRef object)
+{
+    JSMessagePortManagerPriv *priv =
+            static_cast<JSMessagePortManagerPriv*>(JSObjectGetPrivate(object));
+
+    if (priv != NULL)
+        delete (priv);
+}
+
+JSValueRef JSMessagePortManager::requestLocalMessagePort(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    MessagePortManagerPtr messagePortManager;
+    JSContextRef gContext;
+    JSMessagePortManagerPriv *priv;
+
+    try
+    {
+        priv = static_cast<JSMessagePortManagerPriv*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Wrong object");
+            throw TypeMismatchException("Wrong object");
+        }
+        messagePortManager = priv->getObject();
+        gContext = priv->getContext();
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("No private object");
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    string localMessagePortName;
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    try
+    {
+        localMessagePortName = validator.toString(0, false);
+    }
+    catch(BasePlatformException &e)
+    {
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    if (localMessagePortName.empty())
+    {
+        return JSWebAPIErrorFactory::postException(context, exception,
+                InvalidValuesException("Local message port name is empty"));
+    }
+
+    EventMessagePortManagerRequestLocalMessagePortPtr dplEvent(
+            new EventMessagePortManagerRequestLocalMessagePort());
+
+    dplEvent->setLocalMessagePortName(localMessagePortName);
+    dplEvent->setForSynchronousCall();
+
+    Try
+    {
+        messagePortManager->requestLocalMessagePort(dplEvent);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Plugin's internal error"));
+    }
+
+    if (!dplEvent->getResult() || !dplEvent->getLocalMessagePortIsSet())
+    {
+        stringstream oss;
+        switch (dplEvent->getExceptionCode())
+        {
+            case ExceptionCodes::InvalidArgumentException:
+                oss << "Invalid local message port name ('" << localMessagePortName << "')";
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        InvalidValuesException(oss.str().c_str()));
+                break;
+            case ExceptionCodes::PlatformException:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("The method cannot proceed due to a severe system error."));
+                break;
+            default:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("Internal error"));
+                break;
+        }
+    }
+
+    LocalMessagePortPtr localMessagePort = dplEvent->getLocalMessagePort();
+
+    JSValueRef result;
+    try
+    {
+        result = MessagePortJSUtil::toJSValueRef(gContext, localMessagePort);
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("Error on conversion : %s", e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Internal error"));
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return result;
+}
+
+JSValueRef JSMessagePortManager::requestTrustedLocalMessagePort(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    MessagePortManagerPtr messagePortManager;
+    JSContextRef gContext;
+    JSMessagePortManagerPriv *priv;
+
+    try
+    {
+        priv = static_cast<JSMessagePortManagerPriv*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Wrong object");
+            throw TypeMismatchException("Wrong object");
+        }
+        messagePortManager = priv->getObject();
+        gContext = priv->getContext();
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("No private object");
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    string localMessagePortName;
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    try
+    {
+        localMessagePortName = validator.toString(0, false);
+    }
+    catch(BasePlatformException &e)
+    {
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    if (localMessagePortName.empty())
+    {
+        return JSWebAPIErrorFactory::postException(context, exception,
+                InvalidValuesException("Local message port name is empty"));
+    }
+
+    EventMessagePortManagerRequestTrustedLocalMessagePortPtr dplEvent(
+            new EventMessagePortManagerRequestTrustedLocalMessagePort());
+
+    dplEvent->setLocalMessagePortName(localMessagePortName);
+    dplEvent->setForSynchronousCall();
+
+    Try
+    {
+        messagePortManager->requestTrustedLocalMessagePort(dplEvent);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Plugin's internal error"));
+    }
+
+    if (!dplEvent->getResult() || !dplEvent->getLocalMessagePortIsSet())
+    {
+        stringstream oss;
+        switch (dplEvent->getExceptionCode())
+        {
+            case ExceptionCodes::InvalidArgumentException:
+                oss << "Invalid local message port name ('" << localMessagePortName << "')";
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        InvalidValuesException(oss.str().c_str()));
+                break;
+            case ExceptionCodes::PlatformException:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("The method cannot proceed due to a severe system error."));
+                break;
+            default:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("Internal error"));
+                break;
+        }
+    }
+
+    LocalMessagePortPtr localMessagePort = dplEvent->getLocalMessagePort();
+
+    JSValueRef result;
+    try
+    {
+        result = MessagePortJSUtil::toJSValueRef(gContext, localMessagePort);
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("Error on conversion : %s", e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Internal error"));
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return result;
+}
+
+JSValueRef JSMessagePortManager::requestRemoteMessagePort(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    MessagePortManagerPtr messagePortManager;
+    JSContextRef gContext;
+    JSMessagePortManagerPriv *priv;
+
+    try
+    {
+        priv = static_cast<JSMessagePortManagerPriv*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Wrong object");
+            throw TypeMismatchException("Wrong object");
+        }
+
+        messagePortManager = priv->getObject();
+        gContext = priv->getContext();
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("No private object");
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    string appId;
+    string remoteMessagePortName;
+
+    ArgumentValidator argValidator(context, argumentCount, arguments);
+
+    try
+    {
+        appId = argValidator.toString(0, false);
+        remoteMessagePortName = argValidator.toString(1, false);
+    }
+    catch(BasePlatformException &e)
+    {
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+
+    if (appId.empty())
+    {
+        return JSWebAPIErrorFactory::postException(context, exception,
+                InvalidValuesException("Application id is empty"));
+    }
+
+    if (remoteMessagePortName.empty())
+    {
+        return JSWebAPIErrorFactory::postException(context, exception,
+                InvalidValuesException("Remote message port name is empty"));
+    }
+
+    EventMessagePortManagerRequestRemoteMessagePortPtr dplEvent(
+            new EventMessagePortManagerRequestRemoteMessagePort());
+
+    dplEvent->setAppId(appId);
+    dplEvent->setRemoteMessagePortName(remoteMessagePortName);
+    dplEvent->setForSynchronousCall();
+
+    Try
+    {
+        messagePortManager->requestRemoteMessagePort(dplEvent);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Plugin's internal error"));
+    }
+
+    if (!dplEvent->getResult() || !dplEvent->getRemoteMessagePortIsSet())
+    {
+        stringstream oss;
+        switch (dplEvent->getExceptionCode())
+        {
+            case ExceptionCodes::InvalidArgumentException:
+                oss << "Invalid values for appId '" << appId << "' or port name '" << remoteMessagePortName << "'";
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        InvalidValuesException(oss.str().c_str()));
+                break;
+            case ExceptionCodes::NotFoundException:
+                oss << "No port name '" << remoteMessagePortName << "' on app '" << appId << "'";
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        NotFoundException(oss.str().c_str()));
+                break;
+            case ExceptionCodes::PlatformException:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("The method cannot proceed due to a severe system error."));
+                break;
+            default:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("Internal error"));
+                break;
+        }
+    }
+
+    RemoteMessagePortPtr remoteMessagePort = dplEvent->getRemoteMessagePort();
+
+    JSValueRef result;
+    try
+    {
+        result = MessagePortJSUtil::toJSValueRef(gContext, remoteMessagePort);
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("Error on conversion : %s", e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Internal error"));
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return result;
+}
+
+JSValueRef JSMessagePortManager::requestTrustedRemoteMessagePort(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    MessagePortManagerPtr messagePortManager;
+    JSContextRef gContext;
+    JSMessagePortManagerPriv *priv;
+
+    try
+    {
+        priv = static_cast<JSMessagePortManagerPriv*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Wrong object");
+            throw TypeMismatchException("Wrong object");
+        }
+
+        messagePortManager = priv->getObject();
+        gContext = priv->getContext();
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("No private object");
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    string appId;
+    string remoteMessagePortName;
+
+    ArgumentValidator argValidator(context, argumentCount, arguments);
+
+    try
+    {
+        appId = argValidator.toString(0, false);
+        remoteMessagePortName = argValidator.toString(1, false);
+    }
+    catch(BasePlatformException &e)
+    {
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+
+    if (appId.empty())
+    {
+        return JSWebAPIErrorFactory::postException(context, exception,
+                InvalidValuesException("Application id is empty"));
+    }
+
+    if (remoteMessagePortName.empty())
+    {
+        return JSWebAPIErrorFactory::postException(context, exception,
+                InvalidValuesException("Remote message port name is empty"));
+    }
+
+    EventMessagePortManagerRequestTrustedRemoteMessagePortPtr dplEvent(
+            new EventMessagePortManagerRequestTrustedRemoteMessagePort());
+
+    dplEvent->setAppId(appId);
+    dplEvent->setRemoteMessagePortName(remoteMessagePortName);
+    dplEvent->setForSynchronousCall();
+
+    Try
+    {
+        messagePortManager->requestTrustedRemoteMessagePort(dplEvent);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Plugin's internal error"));
+    }
+
+    if (!dplEvent->getResult() || !dplEvent->getRemoteMessagePortIsSet())
+    {
+        stringstream oss;
+        switch (dplEvent->getExceptionCode())
+        {
+            case ExceptionCodes::InvalidArgumentException:
+                oss << "Invalid values for appId '" << appId << "' or port name '" << remoteMessagePortName << "'";
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        InvalidValuesException(oss.str().c_str()));
+            case ExceptionCodes::NotFoundException:
+                oss << "No port name '" << remoteMessagePortName << "' on app '" << appId << "'";
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        NotFoundException(oss.str().c_str()));
+            case ExceptionCodes::PlatformWrongStateException:
+                oss << "Have no permission to access app '" << appId << "'";
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        InvalidAccessException(oss.str().c_str()));
+            case ExceptionCodes::PlatformException:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("The method cannot proceed due to a severe system error."));
+            default:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("Internal error"));
+        }
+    }
+
+    RemoteMessagePortPtr remoteMessagePort = dplEvent->getRemoteMessagePort();
+
+    JSValueRef result;
+    try
+    {
+        result = MessagePortJSUtil::toJSValueRef(gContext, remoteMessagePort);
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("Error on conversion : %s", e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Internal error"));
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return result;
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/JSMessagePortManager.h b/src/MessagePort/JSMessagePortManager.h
new file mode 100755 (executable)
index 0000000..3fbb623
--- /dev/null
@@ -0,0 +1,107 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSMessagePortManager.h
+ * @version     0.1
+ * @brief       Declaration of the JSMessagePortManager class
+ */
+
+#ifndef _TIZEN_MESSAGE_PORT_JS_MESSAGE_PORT_MANAGER_H_
+#define _TIZEN_MESSAGE_PORT_JS_MESSAGE_PORT_MANAGER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include <CommonsJavaScript/PrivateObject.h>
+#include <Commons/IEvent.h>
+#include "IMessagePortManager.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<MessagePortManagerPtr,
+        WrtDeviceApis::CommonsJavaScript::NoOwnership> JSMessagePortManagerPriv;
+
+class JSMessagePortManager {
+public:
+    /*
+     * This initializes this JS class in the JS Engine.
+     */
+    static JSClassRef getClassRef();
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void Initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void Finalize(JSObjectRef object);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_functions[];
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_classRef;
+
+    static JSValueRef requestLocalMessagePort(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef requestTrustedLocalMessagePort(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef requestRemoteMessagePort(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef requestTrustedRemoteMessagePort(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _TIZEN_MESSAGE_PORT_JS_MESSAGE_PORT_MANAGER_H_
diff --git a/src/MessagePort/JSRemoteMessagePort.cpp b/src/MessagePort/JSRemoteMessagePort.cpp
new file mode 100755 (executable)
index 0000000..df261f6
--- /dev/null
@@ -0,0 +1,306 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSRemoteMessagePort.cpp
+ * @version     0.1
+ * @brief       Implementation of the JSRemoteMessagePort class
+ */
+
+#include "JSRemoteMessagePort.h"
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <JSWebAPIErrorFactory.h>
+#include <TimeTracer.h>
+#include "EventRemoteMessagePortSendMessage.h"
+#include "JSLocalMessagePort.h"
+#include "MessagePortJSUtil.h"
+#include <Logger.h>
+
+#define TIZEN_REMOTE_MESSAGE_PORT                   "RemoteMessagePort"
+
+#define TIZEN_REMOTE_MESSAGE_PORT_MESSAGE_PORT_NAME "messagePortName"
+#define TIZEN_REMOTE_MESSAGE_PORT_APP_ID            "appId"
+#define TIZEN_REMOTE_MESSAGE_PORT_IS_TRUSTED        "isTrusted"
+
+#define TIZEN_REMOTE_MESSAGE_PORT_SEND_MESSAGE      "sendMessage"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+JSClassRef JSRemoteMessagePort::m_jsClassRef = NULL;
+
+JSClassDefinition JSRemoteMessagePort::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    TIZEN_REMOTE_MESSAGE_PORT,
+    0,
+    m_property,
+    m_function,
+    Initialize,
+    Finalize,
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL, //ConvertToType,
+};
+
+JSStaticValue JSRemoteMessagePort::m_property[] = {
+    { TIZEN_REMOTE_MESSAGE_PORT_MESSAGE_PORT_NAME, getMessagePortName, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_REMOTE_MESSAGE_PORT_APP_ID, getAppId, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_REMOTE_MESSAGE_PORT_IS_TRUSTED, getIsTrusted, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSRemoteMessagePort::m_function[] = {
+    { TIZEN_REMOTE_MESSAGE_PORT_SEND_MESSAGE, sendMessage, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSRemoteMessagePort::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+const JSClassRef JSRemoteMessagePort::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSRemoteMessagePort::Initialize(JSContextRef context,
+        JSObjectRef object)
+{
+}
+
+void JSRemoteMessagePort::Finalize(JSObjectRef object)
+{
+    JSRemoteMessagePortPriv *priv =
+        static_cast<JSRemoteMessagePortPriv*>(JSObjectGetPrivate(object));
+
+    delete priv;
+}
+
+bool JSRemoteMessagePort::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+RemoteMessagePortPtr JSRemoteMessagePort::getRemoteMessagePort(JSContextRef context, JSValueRef value)
+{
+    if (!isObjectOfClass(context, value)) {
+        LOGE("value is not a RemoteMessagePort object");
+        throw TypeMismatchException("value is not a RemoteMessagePort object");
+    }
+    JSObjectRef object = JSValueToObject(context, value, NULL);
+    if (!object) {
+        LOGE("value is not a object");
+        throw TypeMismatchException("value is not a object");
+    }
+    JSRemoteMessagePortPriv *priv = static_cast<JSRemoteMessagePortPriv*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("cannot get priv object from RemoteMessagePort object");
+        throw TypeMismatchException("cannot get priv object from RemoteMessagePort object");
+    }
+
+    return priv->getObject();
+}
+
+RemoteMessagePortPtr JSRemoteMessagePort::getPrivData(JSObjectRef object)
+{
+    JSRemoteMessagePortPriv *priv =
+        static_cast<JSRemoteMessagePortPriv*>(JSObjectGetPrivate(object));
+
+    if (priv)
+        return priv->getObject();
+
+    LOGE("cannot get priv object from RemoteMessagePort object");
+    throw TypeMismatchException("cannot get priv object from RemoteMessagePort object");
+}
+
+JSValueRef JSRemoteMessagePort::getMessagePortName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try
+    {
+        RemoteMessagePortPtr localMessagePort = getPrivData(object);
+        return JSUtil::toJSValueRef(context, localMessagePort->getMessagePortName());
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGW("trying to get incorrect value");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSRemoteMessagePort::getAppId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try
+    {
+        RemoteMessagePortPtr localMessagePort = getPrivData(object);
+        return JSUtil::toJSValueRef(context, localMessagePort->getAppId());
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGW("trying to get incorrect value");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSRemoteMessagePort::getIsTrusted(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try
+    {
+        RemoteMessagePortPtr localMessagePort = getPrivData(object);
+        return JSUtil::toJSValueRef(context, localMessagePort->getIsTrusted());
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGW("trying to get incorrect value");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSRemoteMessagePort::sendMessage(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("entered");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    RemoteMessagePortPtr remoteMessagePort(static_cast<IRemoteMessagePort*>(NULL));
+
+    try
+    {
+        JSRemoteMessagePortPriv *priv =
+            static_cast<JSRemoteMessagePortPriv*>(JSObjectGetPrivate(thisObject));
+
+        if (!priv) {
+            LOGE("Wrong object");
+            throw TypeMismatchException("Wrong object");
+        }
+        remoteMessagePort = priv->getObject();
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("No private object");
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    MessagePortDataItemMapPtr data(static_cast<MessagePortDataItemMap*>(NULL));
+    LocalMessagePortPtr localMessagePort(static_cast<ILocalMessagePort*>(NULL));
+
+    try
+    {
+        if (argumentCount < 1) {
+            LOGE("1st argument must be array of MessagePortDataItem");
+            throw TypeMismatchException("1st argument must be array of MessagePortDataItem");
+        }
+        data = MessagePortJSUtil::JSValueToMessagePortDataItemMap(context, arguments[0]);
+    }
+    catch(BasePlatformException &e)
+    {
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    try
+    {
+        if (argumentCount >= 2 &&
+                !JSValueIsNull(context, arguments[1]))
+            localMessagePort = MessagePortJSUtil::JSValueToLocalMessagePort(context, arguments[1]);
+    }
+    catch(BasePlatformException &e)
+    {
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+
+    EventRemoteMessagePortSendMessagePtr dplEvent(new EventRemoteMessagePortSendMessage());
+
+    dplEvent->setData(data);
+    if (localMessagePort.get() != NULL)
+        dplEvent->setLocalMessagePort(localMessagePort);
+    dplEvent->setForSynchronousCall();
+
+    Try
+    {
+        remoteMessagePort->sendMessage(dplEvent);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+                UnknownException("Plugin's internal error."));
+    }
+
+    if (!dplEvent->getResult())
+    {
+        switch (dplEvent->getExceptionCode())
+        {
+            case ExceptionCodes::ConversionException:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        TypeMismatchException("Wrong LocalMessagePort object."));
+            case ExceptionCodes::InvalidArgumentException:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        InvalidValuesException("The data argument is wrong."));
+            case ExceptionCodes::NotFoundException:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("The target application's port is not found."));
+            case ExceptionCodes::PlatformException:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("The method cannot proceed due to a severe system error."));
+            case ExceptionCodes::OutOfRangeException:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        QuotaExceededException("The size of message has exceeded the maximum limit."));
+            default:
+                return JSWebAPIErrorFactory::postException(context, exception,
+                        UnknownException("Internal error"));
+        }
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/JSRemoteMessagePort.h b/src/MessagePort/JSRemoteMessagePort.h
new file mode 100755 (executable)
index 0000000..9dd81d3
--- /dev/null
@@ -0,0 +1,96 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSRemoteMessagePort.cpp
+ * @version     0.1
+ * @brief       Declaration of the JSRemoteMessagePort class
+ */
+
+#ifndef _TIZEN_MESSAGE_PORT_JS_REMOTE_MESSAGE_PORT_H_
+#define _TIZEN_MESSAGE_PORT_JS_REMOTE_MESSAGE_PORT_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "IRemoteMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject
+        <RemoteMessagePortPtr, WrtDeviceApis::CommonsJavaScript::NoOwnership> JSRemoteMessagePortPriv;
+
+class JSRemoteMessagePort
+{
+public:
+
+    static const JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+    static RemoteMessagePortPtr getRemoteMessagePort(JSContextRef context, JSValueRef value);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void Initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void Finalize(JSObjectRef object);
+
+    static JSClassDefinition m_classInfo;
+
+    static JSStaticFunction m_function[];
+
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    static RemoteMessagePortPtr getPrivData(JSObjectRef object);
+
+    static JSValueRef getMessagePortName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getAppId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsTrusted(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef sendMessage(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _TIZEN_MESSAGE_PORT_JS_REMOTE_MESSAGE_PORT_H_
diff --git a/src/MessagePort/LocalMessagePort.cpp b/src/MessagePort/LocalMessagePort.cpp
new file mode 100755 (executable)
index 0000000..38f369d
--- /dev/null
@@ -0,0 +1,181 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        LocalMessagePort.cpp
+ * @version     0.1
+ * @brief
+ */
+
+#include "LocalMessagePort.h"
+
+#include <string>
+#include <clocale>
+#include <locale>
+#include <vector>
+
+#include "MessagePortManagerProxy.h"
+#include "MessagePortUtility.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+
+long LocalMessagePort::watchIdAcc = 100;
+
+LocalMessagePort::LocalMessagePort(int id, string &name, bool isTrusted) :
+        ILocalMessagePort(),
+        m_id(id),
+        m_name(name),
+        m_isTrusted(isTrusted)
+{
+}
+
+LocalMessagePort::~LocalMessagePort()
+{
+}
+
+string LocalMessagePort::getMessagePortName() const
+{
+    return m_name;
+}
+
+void LocalMessagePort::setMessagePortName(const string &value)
+{
+}
+
+bool LocalMessagePort::getIsTrusted() const
+{
+    return m_isTrusted;
+}
+
+void LocalMessagePort::setIsTrusted(const bool &value)
+{
+}
+
+void LocalMessagePort::OnRequestReceived(const EventLocalMessagePortAddMessagePortListenerPtr &event)
+{
+    LOGD("entered");
+
+    Try
+    {
+        if (!event->getEmitterIsSet()) {
+            LOGE("Failed to get emitter from event.");
+            ThrowMsg(InvalidArgumentException, "Failed to get emitter from event.");
+        }
+        EventLocalMessagePortListenerEmitterPtr emitter = event->getEmitter();
+
+        m_emitters.attach(emitter);
+
+        long watchId = watchIdAcc++;
+
+        m_emitterIdMap[watchId] = emitter->getId();
+
+        event->setId(watchId);
+        event->setResult(true);
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGE("Error [InvalidArgumentException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
+        event->setResult(false);
+    }
+    Catch(PlatformException)
+    {
+        LOGE("Error [PlatformException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+        event->setResult(false);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error [UnknownException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::UnknownException);
+        event->setResult(false);
+    }
+}
+
+void LocalMessagePort::OnRequestReceived(const EventLocalMessagePortRemoveMessagePortListenerPtr &event)
+{
+    LOGD("entered");
+
+    Try
+    {
+        if (!event->getIdIsSet()) {
+            LOGE("Failed to get watchId from event.");
+            ThrowMsg(InvalidArgumentException, "Failed to get watchId from event.");
+        }
+        long watchId = event->getId();
+
+        MessageReceivedEmitterIdMap::iterator iter = m_emitterIdMap.find(watchId);
+        if (iter == m_emitterIdMap.end()) {
+            LOGE("No watchId (%u) have been registered.", watchId);
+            ThrowMsg(NotFoundException, "No watchId (" << watchId << ") have been registered.");
+        }
+        MessageReceivedEmitter::EmitterIdType emitterId = iter->second;
+        m_emitters.detach(emitterId);
+
+        event->setResult(true);
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGE("Error [InvalidArgumentException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
+        event->setResult(false);
+    }
+    Catch(NotFoundException)
+    {
+        LOGE("Error [NotFoundException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+        event->setResult(false);
+    }
+    Catch(PlatformException)
+    {
+        LOGE("Error [PlatformException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+        event->setResult(false);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error [UnknownException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::UnknownException);
+        event->setResult(false);
+    }
+}
+
+int LocalMessagePort::getPlatformLocalMessagePortId() const
+{
+    return m_id;
+}
+
+void LocalMessagePort::OnMessageReceived(MessagePortDataItemMapPtr &data, RemoteMessagePortPtr &remoteMessagePort)
+{
+    EventLocalMessagePortListenerPtr listener(new EventLocalMessagePortListener());
+
+    listener->setData(data);
+    if (remoteMessagePort.get() != NULL)
+        listener->setRemoteMessagePort(remoteMessagePort);
+
+    LOGD(" onreceived to [%u] callbacks", m_emitters.size());
+
+    m_emitters.emit(listener);
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/LocalMessagePort.h b/src/MessagePort/LocalMessagePort.h
new file mode 100755 (executable)
index 0000000..c63aa44
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        LocalMessagePort.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _PLATFORM_MESSAGE_PORT_LOCAL_MESSAGE_PORT_H_
+#define _PLATFORM_MESSAGE_PORT_LOCAL_MESSAGE_PORT_H_
+
+#include <map>
+#include <string>
+#include <Commons/Emitters.h>
+#include "ILocalMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class LocalMessagePort : public ILocalMessagePort
+{
+public:
+    LocalMessagePort(int id, std::string &name, bool isTrusted);
+    virtual ~LocalMessagePort();
+
+    virtual void addMessagePortListener(const EventLocalMessagePortAddMessagePortListenerPtr &event)
+    {
+        OnRequestReceived(event);
+    }
+
+    virtual void removeMessagePortListener(const EventLocalMessagePortRemoveMessagePortListenerPtr &event)
+    {
+        OnRequestReceived(event);
+    }
+
+    virtual std::string getMessagePortName() const;
+    virtual void        setMessagePortName(const std::string &value);
+    virtual bool        getIsTrusted() const;
+    virtual void        setIsTrusted(const bool &value);
+
+    int getPlatformLocalMessagePortId() const;
+
+protected:
+    virtual void OnRequestReceived(const EventLocalMessagePortAddMessagePortListenerPtr &event);
+    virtual void OnRequestReceived(const EventLocalMessagePortRemoveMessagePortListenerPtr &event);
+
+private:
+    int             m_id;
+    std::string     m_name;
+    bool            m_isTrusted;
+
+public:
+    virtual void OnMessageReceived(MessagePortDataItemMapPtr &data,
+            RemoteMessagePortPtr &remoteMessagePort);
+
+private:
+    typedef WrtDeviceApis::Commons::Emitters<EventLocalMessagePortListenerEmitter> MessageReceivedEmitter;
+    MessageReceivedEmitter m_emitters;
+
+    static long watchIdAcc;
+    typedef std::map<long, MessageReceivedEmitter::EmitterIdType> MessageReceivedEmitterIdMap;
+    MessageReceivedEmitterIdMap m_emitterIdMap;
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _PLATFORM_MESSAGE_PORT_LOCAL_MESSAGE_PORT_H_
diff --git a/src/MessagePort/LocalMessagePortController.cpp b/src/MessagePort/LocalMessagePortController.cpp
new file mode 100755 (executable)
index 0000000..81b9356
--- /dev/null
@@ -0,0 +1,110 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortManagerController.cpp
+ * @version     0.1
+ * @brief
+ */
+
+#include "LocalMessagePortController.h"
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include "MessagePortDataItem.h"
+#include "MessagePortJSUtil.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+LocalMessagePortController::LocalMessagePortController(JSContextRef context, LocalMessagePortPtr localMessagePort) :
+        EventLocalMessagePortListenerListener(ThreadEnum::NULL_THREAD),
+        LocalMessagePortPrivObject(context, localMessagePort)
+{
+    LOGD("LocalMessagePortController constructed : %p",this);
+    if (!localMessagePort) {
+        LOGW("controller has no localMessagePort object");
+    }
+}
+
+LocalMessagePortController::~LocalMessagePortController()
+{
+    LOGD("LocalMessagePortController destructed : %p", this);
+}
+
+void LocalMessagePortAsyncAnswerHandler::localMessagePortListener(const EventLocalMessagePortListenerPtr &event)
+{
+    LOGD("entered");
+    JSValueRef result[2];
+
+    JSCallbackManagerPtr cbm = std::static_pointer_cast<JSCallbackManager>(event->getPrivateData());
+    if (!cbm)
+    {
+        LOGE("no callback manager");
+        return;
+    }
+
+    JSContextRef gContext = cbm->getContext();
+
+    if (!event->getDataIsSet())
+    {
+        LOGE("No data items");
+        return;
+    }
+
+    try
+    {
+        result[0] = MessagePortJSUtil::toJSValueRef(gContext, event->getData());
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("Fail to convert MessagePortDataItemMap");
+        return;
+    }
+
+    try
+    {
+        if (event->getRemoteMessagePortIsSet())
+            result[1] = MessagePortJSUtil::toJSValueRef(gContext, event->getRemoteMessagePort());
+        else
+            result[1] = JSValueMakeNull(gContext);
+    }
+    catch(BasePlatformException &e)
+    {
+        LOGE("Fail to convert RemoteMessagePort");
+        return;
+    }
+
+    cbm->callOnSuccess(result, 2);
+}
+
+void LocalMessagePortController::onAnswerReceived(const EventLocalMessagePortListenerPtr &event)
+{
+    if (event.get() == NULL)
+    {
+        LOGE("wrong event");
+        return;
+    }
+
+    LocalMessagePortAsyncAnswerHandler::localMessagePortListener(event);
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/LocalMessagePortController.h b/src/MessagePort/LocalMessagePortController.h
new file mode 100755 (executable)
index 0000000..a9db193
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        LocalMessagePortController.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _TIZEN_MESSAGE_PORT_LOCAL_MESSAGE_PORT_CONTROLLER_H_
+#define _TIZEN_MESSAGE_PORT_LOCAL_MESSAGE_PORT_CONTROLLER_H_
+
+#include <Commons/EventReceiver.h>
+#include <Commons/EventListener.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "ILocalMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObject<LocalMessagePortPtr,
+        WrtDeviceApis::CommonsJavaScript::NoOwnership> LocalMessagePortPrivObject;
+
+typedef WrtDeviceApis::Commons::EventListener<EventLocalMessagePortListener> EventLocalMessagePortListenerListener;
+
+class LocalMessagePortController :
+    public EventLocalMessagePortListenerListener,
+    public LocalMessagePortPrivObject
+{
+public:
+    LocalMessagePortController(JSContextRef context,
+            LocalMessagePortPtr localMessagePort);
+    virtual ~LocalMessagePortController();
+protected:
+    void onAnswerReceived(const EventLocalMessagePortListenerPtr &event);
+};
+
+typedef std::shared_ptr<LocalMessagePortController> LocalMessagePortControllerPtr;
+
+//common part
+class LocalMessagePortAsyncAnswerHandler
+{
+public:
+    static void localMessagePortListener(const EventLocalMessagePortListenerPtr &event);
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _TIZEN_MESSAGE_PORT_LOCAL_MESSAGE_PORT_CONTROLLER_H_
diff --git a/src/MessagePort/MessagePortDataItem.h b/src/MessagePort/MessagePortDataItem.h
new file mode 100755 (executable)
index 0000000..b1b78ea
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortDataItem.h
+ * @version     0.1
+ * @brief
+ * ##
+ */
+
+#ifndef _API_MESSAGE_PORT_MESSAGE_PORT_DATA_ITEM_H_
+#define _API_MESSAGE_PORT_MESSAGE_PORT_DATA_ITEM_H_
+
+#include <string>
+#include <map>
+#include <memory>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+typedef std::string MessagePortDataItemKey;
+typedef std::string MessagePortDataItemValue;
+
+typedef std::map<MessagePortDataItemKey, MessagePortDataItemValue> MessagePortDataItemMap;
+typedef std::shared_ptr<MessagePortDataItemMap> MessagePortDataItemMapPtr;
+
+typedef std::pair<MessagePortDataItemKey, MessagePortDataItemKey> MessagePortDataItemPair;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_MESSAGE_PORT_DATA_ITEM_H_
diff --git a/src/MessagePort/MessagePortFactory.cpp b/src/MessagePort/MessagePortFactory.cpp
new file mode 100755 (executable)
index 0000000..954dc28
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortFactory.cpp
+ * @version     0.1
+ * @brief
+ * ##
+ */
+
+#include "MessagePortFactory.h"
+
+#include "MessagePortImpl.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+
+MessagePortFactory& MessagePortFactory::getInstance() // static
+{
+    static MessagePortFactory theInstance;
+    return theInstance;
+}
+
+MessagePortManagerPtr MessagePortFactory::createMessagePortManager()
+{
+    static MessagePortManagerPtr result(new MessagePortManager());
+    return result;
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/MessagePortFactory.h b/src/MessagePort/MessagePortFactory.h
new file mode 100755 (executable)
index 0000000..d32a195
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortFactory.h
+ * @version     0.1
+ * @brief
+ * ##
+ */
+
+#ifndef _API_MESSAGE_PORT_MESSAGE_PORT_FACTORY_H_
+#define _API_MESSAGE_PORT_MESSAGE_PORT_FACTORY_H_
+
+#include <string>
+
+#include "IMessagePortManager.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class MessagePortFactory : private DPL::Noncopyable
+{
+private:
+    MessagePortFactory()
+    {
+    };
+
+public:
+    static MessagePortFactory&  getInstance();
+    MessagePortManagerPtr       createMessagePortManager();
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _API_MESSAGE_PORT_MESSAGE_PORT_FACTORY_H_
diff --git a/src/MessagePort/MessagePortImpl.h b/src/MessagePort/MessagePortImpl.h
new file mode 100755 (executable)
index 0000000..2cccb61
--- /dev/null
@@ -0,0 +1,29 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortImpl.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_IMPL_H_
+#define _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_IMPL_H_
+
+#include "MessagePortManager.h"
+
+#endif // _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_IMPL_H_
diff --git a/src/MessagePort/MessagePortJSUtil.cpp b/src/MessagePort/MessagePortJSUtil.cpp
new file mode 100755 (executable)
index 0000000..abc59e2
--- /dev/null
@@ -0,0 +1,202 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MessagePortJSUtil.h"
+
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+
+#include <set>
+#include <string>
+#include <sstream>
+#include "JSLocalMessagePort.h"
+#include "JSRemoteMessagePort.h"
+#include <Logger.h>
+
+#define MESSAGE_PORT_ATTRIBUTE_KEY "key"
+#define MESSAGE_PORT_ATTRIBUTE_VALUE "value"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+using namespace DeviceAPI::Common;
+
+JSValueRef MessagePortJSUtil::toJSValueRef(JSContextRef context, const MessagePortDataItemMapPtr &arg)
+{
+    JSObjectRef resultObject = JSCreateArrayObject(context, 0, NULL);
+    if (!resultObject) {
+        LOGE("Can not create array object");
+        throw TypeMismatchException("Can not create array object");
+    }
+
+    int i = 0;
+    MessagePortDataItemMap::iterator iter;
+    for (iter = arg->begin(); iter != arg->end(); iter++, i++)
+    {
+        const WrtDeviceApis::CommonsJavaScript::ScopedJSStringRef keyStr(
+                JSStringCreateWithUTF8CString(MESSAGE_PORT_ATTRIBUTE_KEY));
+        const WrtDeviceApis::CommonsJavaScript::ScopedJSStringRef valueStr(
+                JSStringCreateWithUTF8CString(MESSAGE_PORT_ATTRIBUTE_VALUE));
+
+        JSValueRef key = JSUtil::toJSValueRef(context, iter->first);
+        JSValueRef value = JSUtil::toJSValueRef(context, iter->second);
+
+        JSObjectRef jsobject = JSObjectMake(context, NULL, NULL);
+        JSObjectSetProperty(context, jsobject, keyStr.get(), key, kJSPropertyAttributeNone, NULL);
+        JSObjectSetProperty(context, jsobject, valueStr.get(), value, kJSPropertyAttributeNone, NULL);
+
+        JSValueRef jsvalue = jsobject;
+
+        if (!JSSetArrayElement(context, resultObject, i, jsvalue)) {
+            LOGE("Can not fill contact array");
+            throw TypeMismatchException("Can not fill contact array");
+        }
+    }
+
+    return static_cast<JSValueRef>(resultObject);
+}
+
+JSValueRef MessagePortJSUtil::toJSValueRef(JSContextRef context, const LocalMessagePortPtr &arg)
+{
+    LocalMessagePortController *priv = new LocalMessagePortController(context, arg);
+    JSObjectRef object = JSObjectMake(context, JSLocalMessagePort::getClassRef(), priv);
+    if (!object) {
+        LOGE("Could not create JS object.");
+        throw TypeMismatchException("Could not create JS object.");
+    }
+    return object;
+}
+
+JSValueRef MessagePortJSUtil::toJSValueRef(JSContextRef context, const RemoteMessagePortPtr &arg)
+{
+    JSRemoteMessagePortPriv* priv = new JSRemoteMessagePortPriv(context, arg);
+    JSObjectRef object = JSObjectMake(context, JSRemoteMessagePort::getClassRef(), priv);
+    if (!object) {
+        LOGE("Could not create JS object.");
+        throw TypeMismatchException("Could not create JS object.");
+    }
+    return object;
+}
+
+MessagePortDataItemMapPtr MessagePortJSUtil::JSValueToMessagePortDataItemMap(JSContextRef context, JSValueRef jsValue)
+{
+    if (!JSIsArrayValue(context, jsValue)) {
+        LOGE("MessagePortArray is not array.");
+        throw TypeMismatchException("MessagePortArray is not array.");
+    }
+    MessagePortDataItemMapPtr result = MessagePortDataItemMapPtr(new MessagePortDataItemMap());
+
+    const WrtDeviceApis::CommonsJavaScript::ScopedJSStringRef keyStr(
+            JSStringCreateWithUTF8CString(MESSAGE_PORT_ATTRIBUTE_KEY));
+    const WrtDeviceApis::CommonsJavaScript::ScopedJSStringRef valueStr(
+            JSStringCreateWithUTF8CString(MESSAGE_PORT_ATTRIBUTE_VALUE));
+
+    set<string> keyDupChecker;
+    JSObjectRef jsObject = JSValueToObject(context, jsValue);
+    unsigned int length = JSGetArrayLength(context, jsObject);
+    for (std::size_t i = 0; i < length; i++)
+    {
+        JSValueRef element = JSGetArrayElement(context, jsObject, i);
+
+        if (!JSValueIsObject(context, element))
+        {
+            stringstream ss;
+            ss << "data[" << i << "] is not object type";
+            LOGE("%s", ss.str().c_str());
+            throw TypeMismatchException(ss.str().c_str());
+        }
+
+        JSObjectRef jsObject = JSValueToObject(context, element);
+
+        std::string key;
+        std::string value;
+
+        JSValueRef keyData = JSObjectGetProperty(context, jsObject, keyStr.get(), NULL);
+        try
+        {
+            key = JSUtil::JSValueToString(context, keyData);
+        }
+        catch(BasePlatformException &e)
+        {
+            stringstream ss;
+            ss << "data[" << i << "].key is not string type";
+            LOGE("%s", ss.str().c_str());
+            throw TypeMismatchException(ss.str().c_str());
+        }
+
+        if (key.empty())
+        {
+            stringstream ss;
+            ss << "data[" << i << "].key is empty";
+            LOGE("%s", ss.str().c_str());
+            throw InvalidValuesException(ss.str().c_str());
+        }
+
+        if (keyDupChecker.find(key) != keyDupChecker.end())
+        {
+            stringstream ss;
+            ss << "data[" << i << "].key \"" << key << "\" is duplicated";
+            LOGE("%s", ss.str().c_str());
+            throw InvalidValuesException(ss.str().c_str());
+        }
+
+        keyDupChecker.insert(key);
+
+        JSValueRef valueData = JSObjectGetProperty(context, jsObject, valueStr.get(), NULL);
+        try
+        {
+            value = JSUtil::JSValueToString(context, valueData);
+        }
+        catch(BasePlatformException &e)
+        {
+            stringstream ss;
+            ss << "data[" << i << "].value is not string type";
+            LOGE("%s", ss.str().c_str());
+            throw TypeMismatchException(ss.str().c_str());
+        }
+
+        MessagePortDataItemPair pair(key, value);
+        result->insert(pair);
+    }
+
+    return result;
+}
+
+LocalMessagePortPtr MessagePortJSUtil::JSValueToLocalMessagePort(JSContextRef context, JSValueRef jsValue)
+{
+    if (!JSLocalMessagePort::isObjectOfClass(context, jsValue))
+    {
+        LOGE("Not a LocalMessagePort object");
+        throw TypeMismatchException("value is not a LocalMessagePort object");
+    }
+
+    return JSLocalMessagePort::getLocalMessagePort(context, jsValue);
+}
+
+RemoteMessagePortPtr MessagePortJSUtil::JSValueToRemoteMessagePort(JSContextRef context, JSValueRef jsValue)
+{
+    if (!JSRemoteMessagePort::isObjectOfClass(context, jsValue))
+    {
+        LOGE("Not a RemoteMessagePort object");
+        throw TypeMismatchException("value is not a RemoteMessagePort object");
+    }
+
+    return JSRemoteMessagePort::getRemoteMessagePort(context, jsValue);
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/MessagePortJSUtil.h b/src/MessagePort/MessagePortJSUtil.h
new file mode 100755 (executable)
index 0000000..c8a2e75
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _MESSAGE_PORT_JSUTIL_H_
+#define _MESSAGE_PORT_JSUTIL_H_
+
+#include <JSUtil.h>
+#include "MessagePortDataItem.h"
+#include "ILocalMessagePort.h"
+#include "IRemoteMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class MessagePortJSUtil : public DeviceAPI::Common::JSUtil
+{
+public:
+    static JSValueRef toJSValueRef(JSContextRef context, const MessagePortDataItemMapPtr &arg);
+    static JSValueRef toJSValueRef(JSContextRef context, const LocalMessagePortPtr &arg);
+    static JSValueRef toJSValueRef(JSContextRef context, const RemoteMessagePortPtr &arg);
+
+    static MessagePortDataItemMapPtr JSValueToMessagePortDataItemMap(JSContextRef context, JSValueRef value);
+    static LocalMessagePortPtr JSValueToLocalMessagePort(JSContextRef context, JSValueRef value);
+    static RemoteMessagePortPtr JSValueToRemoteMessagePort(JSContextRef context, JSValueRef value);
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif //_MESSAGE_PORT_JSUTIL_H_
diff --git a/src/MessagePort/MessagePortListenerManager.cpp b/src/MessagePort/MessagePortListenerManager.cpp
new file mode 100755 (executable)
index 0000000..6986379
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortListenerManager.cpp
+ * @version     0.1
+ * @brief
+ */
+
+#include "MessagePortListenerManager.h"
+#include <dpl/singleton_impl.h>
+
+
+
+IMPLEMENT_SINGLETON(DeviceAPI::MessagePort::MessagePortListenerManager)
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/MessagePortListenerManager.h b/src/MessagePort/MessagePortListenerManager.h
new file mode 100755 (executable)
index 0000000..1ba31ea
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortListenerManager.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _TIZEN_CONTACT_LISTENER_MANAGER_H_
+#define _TIZEN_CONTACT_LISTENER_MANAGER_H_
+
+#include <map>
+#include <JavaScriptCore/JavaScript.h>
+
+#include <dpl/singleton.h>
+#include <IListenerManager.h>
+#include "LocalMessagePortController.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+
+class MessagePortListenerManager : public DeviceAPI::Common::IListenerController
+{
+public:
+    MessagePortListenerManager()
+    {
+    }
+
+    virtual ~MessagePortListenerManager()
+    {
+    }
+};
+typedef DPL::Singleton<MessagePortListenerManager> MessagePortListenerManagerSingleton;
+
+class MessagePortsChangeListenerCanceller : public DeviceAPI::Common::IListenerItem
+{
+public:
+    MessagePortsChangeListenerCanceller(JSContextRef context, JSObjectRef object, long watchId) :
+        DeviceAPI::Common::IListenerItem(context, object, watchId)
+    {
+    }
+
+    virtual ~MessagePortsChangeListenerCanceller()
+    {
+    }
+
+    virtual void cancelListener()
+    {
+        LocalMessagePortPtr localMessagePort;
+        LocalMessagePortController *controller;
+
+        controller = static_cast<LocalMessagePortController*>(JSObjectGetPrivate(m_object));
+        if (!controller) {
+            LOGW("Object has no controller");
+            return;
+        }
+        localMessagePort = controller->getObject();
+
+        EventLocalMessagePortRemoveMessagePortListenerPtr dplEvent(new EventLocalMessagePortRemoveMessagePortListener());
+
+        dplEvent->setId(m_watchId);
+        dplEvent->setForSynchronousCall();
+
+        Try
+        {
+            LOGD("Remove change listener");
+            localMessagePort->removeMessagePortListener(dplEvent);
+        }
+        Catch(WrtDeviceApis::Commons::Exception)
+        {
+            LOGE("Error on platform : %s", _rethrown_exception.GetMessage().c_str());
+        }
+    }
+};
+typedef std::shared_ptr<MessagePortsChangeListenerCanceller> MessagePortsChangeListenerCancellerPtr;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _TIZEN_CONTACT_LISTENER_MANAGER_H_
diff --git a/src/MessagePort/MessagePortManager.cpp b/src/MessagePort/MessagePortManager.cpp
new file mode 100755 (executable)
index 0000000..3b3f78b
--- /dev/null
@@ -0,0 +1,227 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortManager.cpp
+ * @version     0.1
+ * @brief
+ * ##
+ */
+
+#include "MessagePortManager.h"
+#include "MessagePortManagerProxy.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+
+MessagePortManager::MessagePortManager() :
+        IMessagePortManager()
+{
+    //Nothing to do
+}
+
+MessagePortManager::~MessagePortManager()
+{
+    //Nothing to do
+}
+
+void MessagePortManager::OnRequestReceived(const EventMessagePortManagerRequestLocalMessagePortPtr &event)
+{
+    LOGD("entered");
+
+    Try
+    {
+        if (!event->getLocalMessagePortNameIsSet()) {
+            LOGE("Failed to get LocalMessagePortName from event.");
+            ThrowMsg(InvalidArgumentException, "Failed to get LocalMessagePortName from event.");
+        }
+        string messagePortName = event->getLocalMessagePortName();
+
+        LocalMessagePortPtr localMessagePort =
+                MessagePortManagerProxySingleton::Instance().requestLocalMessagePort(messagePortName);
+
+        event->setLocalMessagePort(localMessagePort);
+        event->setResult(true);
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGE("Error [InvalidArgumentException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
+        event->setResult(false);
+    }
+    Catch(PlatformException)
+    {
+        LOGE("Error [PlatformException] : %s",  _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+        event->setResult(false);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error [UnknownException] : %s",  _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::UnknownException);
+        event->setResult(false);
+    }
+}
+
+void MessagePortManager::OnRequestReceived(const EventMessagePortManagerRequestTrustedLocalMessagePortPtr &event)
+{
+    LOGD("entered");
+
+    Try
+    {
+        if (!event->getLocalMessagePortNameIsSet()) {
+            LOGE("Failed to get LocalMessagePortName from event.");
+            ThrowMsg(InvalidArgumentException, "Failed to get LocalMessagePortName from event.");
+        }
+        string messagePortName = event->getLocalMessagePortName();
+
+        LocalMessagePortPtr localMessagePort =
+                MessagePortManagerProxySingleton::Instance().requestTrustedLocalMessagePort(messagePortName);
+
+        event->setLocalMessagePort(localMessagePort);
+        event->setResult(true);
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGE("Error [InvalidArgumentException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
+        event->setResult(false);
+    }
+    Catch(PlatformException)
+    {
+        LOGE("Error [PlatformException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+        event->setResult(false);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error [UnknownException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::UnknownException);
+        event->setResult(false);
+    }
+}
+
+void MessagePortManager::OnRequestReceived(const EventMessagePortManagerRequestRemoteMessagePortPtr &event)
+{
+    LOGD("entered");
+
+    Try
+    {
+        if (!event->getAppIdIsSet()) {
+            LOGE("Failed to get appId from event.");
+            ThrowMsg(InvalidArgumentException, "Failed to get appId from event.");
+        }
+        if (!event->getRemoteMessagePortNameIsSet()) {
+            LOGE("Failed to get remoteMessagePortName from event.");
+            ThrowMsg(InvalidArgumentException, "Failed to get remoteMessagePortName from event.");
+        }
+        string appId = event->getAppId();
+        string messagePortName = event->getRemoteMessagePortName();
+
+        RemoteMessagePortPtr remoteMessagePort =
+                MessagePortManagerProxySingleton::Instance().requestRemoteMessagePort(appId, messagePortName);
+
+        event->setRemoteMessagePort(remoteMessagePort);
+        event->setResult(true);
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGE("Error [InvalidArgumentException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
+        event->setResult(false);
+    }
+    Catch(NotFoundException)
+    {
+        LOGE("Error [NotFoundException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+        event->setResult(false);
+    }
+    Catch(PlatformException)
+    {
+        LOGE("Error [PlatformException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+        event->setResult(false);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error [UnknownException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::UnknownException);
+        event->setResult(false);
+    }
+}
+
+void MessagePortManager::OnRequestReceived(const EventMessagePortManagerRequestTrustedRemoteMessagePortPtr &event)
+{
+    LOGD("entered");
+
+    Try
+    {
+        if (!event->getAppIdIsSet()) {
+            LOGE("Failed to get appId from event.");
+            ThrowMsg(InvalidArgumentException, "Failed to get appId from event.");
+        }
+        if (!event->getRemoteMessagePortNameIsSet()) {
+            LOGE("Failed to get remoteMessagePortName from event.");
+            ThrowMsg(InvalidArgumentException, "Failed to get remoteMessagePortName from event.");
+        }
+        string appId = event->getAppId();
+        string messagePortName = event->getRemoteMessagePortName();
+
+        RemoteMessagePortPtr remoteMessagePort =
+                MessagePortManagerProxySingleton::Instance().requestTrustedRemoteMessagePort(appId, messagePortName);
+
+        event->setRemoteMessagePort(remoteMessagePort);
+        event->setResult(true);
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGE("Error [InvalidArgumentException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
+        event->setResult(false);
+    }
+    Catch(NotFoundException)
+    {
+        LOGE("Error [NotFoundException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+        event->setResult(false);
+    }
+    Catch(PlatformWrongStateException)
+    {
+        LOGE("Error [PlatformWrongStateException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformWrongStateException);
+        event->setResult(false);
+    }
+    Catch(PlatformException)
+    {
+        LOGE("Error [PlatformException] : %s",  _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+        event->setResult(false);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error [UnknownException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::UnknownException);
+        event->setResult(false);
+    }
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/MessagePortManager.h b/src/MessagePort/MessagePortManager.h
new file mode 100755 (executable)
index 0000000..08be3b5
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortManager.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_MANAGER_H_
+#define _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_MANAGER_H_
+
+#include <map>
+
+#include "IMessagePortManager.h"
+#include "ILocalMessagePort.h"
+#include "IRemoteMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class MessagePortManager : public IMessagePortManager
+{
+public:
+    MessagePortManager();
+    virtual ~MessagePortManager();
+    virtual void requestLocalMessagePort(const EventMessagePortManagerRequestLocalMessagePortPtr &event)
+    {
+        OnRequestReceived(event);
+    }
+
+    virtual void requestTrustedLocalMessagePort(const EventMessagePortManagerRequestTrustedLocalMessagePortPtr &event)
+    {
+        OnRequestReceived(event);
+    }
+
+    virtual void requestRemoteMessagePort(const EventMessagePortManagerRequestRemoteMessagePortPtr &event)
+    {
+        OnRequestReceived(event);
+    }
+
+    virtual void requestTrustedRemoteMessagePort(const EventMessagePortManagerRequestTrustedRemoteMessagePortPtr &event)
+    {
+        OnRequestReceived(event);
+    }
+
+protected:
+    virtual void OnRequestReceived(const EventMessagePortManagerRequestLocalMessagePortPtr &event);
+    virtual void OnRequestReceived(const EventMessagePortManagerRequestTrustedLocalMessagePortPtr &event);
+    virtual void OnRequestReceived(const EventMessagePortManagerRequestRemoteMessagePortPtr &event);
+    virtual void OnRequestReceived(const EventMessagePortManagerRequestTrustedRemoteMessagePortPtr &event);
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_MANAGER_H_
diff --git a/src/MessagePort/MessagePortManagerProxy.cpp b/src/MessagePort/MessagePortManagerProxy.cpp
new file mode 100755 (executable)
index 0000000..917a41f
--- /dev/null
@@ -0,0 +1,375 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortManagerProxy.cpp
+ * @version     0.1
+ * @brief
+ * ##
+ */
+
+#include "MessagePortManagerProxy.h"
+
+#include <unistd.h>
+#include <app_manager.h>
+#include <dpl/singleton_impl.h>
+
+#include "LocalMessagePort.h"
+#include "RemoteMessagePort.h"
+#include "MessagePortUtility.h"
+#include <Logger.h>
+
+IMPLEMENT_SINGLETON(DeviceAPI::MessagePort::MessagePortManagerProxy)
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+
+MessagePortManagerProxy::MessagePortManagerProxy()
+{
+}
+
+MessagePortManagerProxy::~MessagePortManagerProxy()
+{
+    //Nothing to do
+}
+
+LocalMessagePortPtr MessagePortManagerProxy::requestLocalMessagePort(string &messagePortName)
+{
+    LOGD("request local (name : %s )", messagePortName.c_str());
+
+    return getLocalMessagePort(messagePortName, false);
+}
+
+LocalMessagePortPtr MessagePortManagerProxy::requestTrustedLocalMessagePort(string &messagePortName)
+{
+    LOGD("request trusted local (name : %s )", messagePortName.c_str());
+
+    return getLocalMessagePort(messagePortName, true);
+}
+
+RemoteMessagePortPtr MessagePortManagerProxy::requestRemoteMessagePort(string &appId, string &messagePortName)
+{
+    LOGD("request remote (appId : %s / name : %s )", appId.c_str(), messagePortName.c_str());
+
+    return getRemoteMessagePort(appId, messagePortName, false);
+}
+
+RemoteMessagePortPtr MessagePortManagerProxy::requestTrustedRemoteMessagePort(string &appId, string &messagePortName)
+{
+    LOGD("request trusted remote (appId : %s / name : %s )", appId.c_str(), messagePortName.c_str());
+
+    return getRemoteMessagePort(appId, messagePortName, true);
+}
+
+void MessagePortManagerProxy::sendMessage(string appId, string name, bool isTrusted,
+        MessagePortDataItemMapPtr &data, int localPortId)
+{
+    bundle *b = MessagePortUtilitySingleton::Instance().getBundle(data);
+
+    LOGD("==> %s:%s[%c] (%d)", appId.c_str(), name.c_str(), (isTrusted?'T':' '), localPortId );
+
+    int err = 0;
+
+    std::string core_function_name = "";
+    if (!isTrusted)
+    {
+        if (localPortId == UNDEFINED_LOCAL_PORT_ID) {
+            err = messageport_send_message(appId.c_str(), name.c_str(), b);
+            core_function_name = "messageport_send_message()";
+        } else {
+            err = messageport_send_bidirectional_message(localPortId,
+                    appId.c_str(), name.c_str(), b);
+            core_function_name = "messageport_send_bidirectional_message()";
+        }
+    }
+    else
+    {
+        if (localPortId == UNDEFINED_LOCAL_PORT_ID) {
+            err = messageport_send_trusted_message(appId.c_str(), name.c_str(), b);
+            core_function_name = "messageport_send_trusted_message()";
+        } else {
+            err = messageport_send_bidirectional_trusted_message(localPortId,
+                    appId.c_str(), name.c_str(), b);
+            core_function_name = "messageport_send_bidirectional_trusted_message()";
+        }
+    }
+
+    if (err < 0)
+    {
+        LOGE("ret: %d", err);
+
+        switch(err)
+        {
+        case MESSAGEPORT_ERROR_INVALID_PARAMETER:
+            MessagePortUtility::throwMessagePortException<PlatformException>(err,
+                    core_function_name, "The message argument is not a map of String key and String value pair.");
+            break;
+        case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
+            MessagePortUtility::throwMessagePortException<PlatformException>(err,
+                    core_function_name, "The method cannot proceed due to a severe system error. (memory)");
+            break;
+        case MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND:
+            MessagePortUtility::throwMessagePortException<NotFoundException>(err,
+                    core_function_name, "The target application's port is not found.");
+            break;
+        case MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH:
+            MessagePortUtility::throwMessagePortException<PlatformWrongStateException>(err,
+                    core_function_name, "The target application is not signed with the same certificate.");
+            break;
+        case MESSAGEPORT_ERROR_IO_ERROR:
+            MessagePortUtility::throwMessagePortException<PlatformException>(err,
+                    core_function_name, "The method cannot proceed due to a severe system error. (I/O)");
+            break;
+        case MESSAGEPORT_ERROR_MAX_EXCEEDED:
+            MessagePortUtility::throwMessagePortException<OutOfRangeException>(err,
+                    core_function_name, "The size of message has exceeded the maximum limit.");
+            break;
+        default:
+            MessagePortUtility::throwMessagePortException<PlatformException>(err,
+                    core_function_name, "The method cannot proceed due to a severe system error.");
+            break;
+        }
+    }
+}
+
+LocalMessagePortPtr MessagePortManagerProxy::getLocalMessagePort(string &name, bool isTrusted)
+{
+    LocalMessagePortPtr localMessagePort = getCachedLocalMessagePort(name, isTrusted);
+
+    if (localMessagePort.get() == NULL)
+    {
+        int id = 0;
+        std::string core_function_name = "";
+        if (isTrusted) {
+            core_function_name = "messageport_register_trusted_local_port()";
+            id = messageport_register_trusted_local_port(name.c_str(), message_port_message_cb);
+        } else {
+            core_function_name = "messageport_register_local_port()";
+            id = messageport_register_local_port(name.c_str(), message_port_message_cb);
+        }
+
+        LOGD("registered local port (id: %d", id);
+
+        if (id < 0)
+        {
+            LOGD("Failed to register local port (err: %d", id);
+
+            int errorCode = id;
+
+            LOGE("ret: %d", errorCode);
+            switch(errorCode)
+            {
+            case MESSAGEPORT_ERROR_INVALID_PARAMETER:
+                MessagePortUtility::throwMessagePortException<InvalidArgumentException>(errorCode,
+                        core_function_name, "The remote application ID or the remote message port name is empty.");
+                break;
+            case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
+                MessagePortUtility::throwMessagePortException<PlatformException>(errorCode,
+                        core_function_name, "The method cannot proceed due to a severe system error. (Memory)");
+                break;
+            case MESSAGEPORT_ERROR_IO_ERROR:
+                MessagePortUtility::throwMessagePortException<PlatformException>(errorCode,
+                        core_function_name, "The method cannot proceed due to a severe system error. (I/O)");
+                break;
+            default:
+                MessagePortUtility::throwMessagePortException<PlatformException>(errorCode,
+                        core_function_name, "The method cannot proceed due to a severe system error. (Unknown code)");
+                break;
+            }
+        }
+
+        localMessagePort = LocalMessagePortPtr(new LocalMessagePort(id, name, isTrusted));
+
+        cacheLocalMessagePort(id, name, isTrusted, localMessagePort);
+    }
+
+    return localMessagePort;
+}
+
+RemoteMessagePortPtr MessagePortManagerProxy::getRemoteMessagePort(string &appId, string &name, bool isTrusted)
+{
+    bool exists = false;
+    int errorCode = 0;
+    std::string core_function_name = "";
+    if (isTrusted) {
+        core_function_name = "messageport_check_trusted_remote_port()";
+        errorCode = messageport_check_trusted_remote_port(appId.c_str(),
+                name.c_str(), &exists);
+    } else {
+        core_function_name = "messageport_check_remote_port()";
+        errorCode = messageport_check_remote_port(appId.c_str(), name.c_str(),
+                &exists);
+    }
+
+
+    if (!exists || errorCode < 0)
+    {
+        LOGE("ret: %d", errorCode);
+
+        switch(errorCode)
+        {
+        case MESSAGEPORT_ERROR_INVALID_PARAMETER:
+            MessagePortUtility::throwMessagePortException<InvalidArgumentException>(errorCode,
+                    core_function_name, "The remote application ID or the remote message port name is empty.");
+            break;
+        case MESSAGEPORT_ERROR_MESSAGEPORT_NOT_FOUND:
+            MessagePortUtility::throwMessagePortException<NotFoundException>(errorCode,
+                               core_function_name, "The target application's port is not found.");
+            break;
+        case MESSAGEPORT_ERROR_CERTIFICATE_NOT_MATCH:
+            MessagePortUtility::throwMessagePortException<PlatformWrongStateException>(errorCode,
+                               core_function_name, "The target application is not signed with the same certificate.");
+            break;
+        case MESSAGEPORT_ERROR_OUT_OF_MEMORY:
+            MessagePortUtility::throwMessagePortException<PlatformException>(errorCode,
+                               core_function_name, "The method cannot proceed due to a severe system error. (Memory)");
+            break;
+        case MESSAGEPORT_ERROR_IO_ERROR:
+            MessagePortUtility::throwMessagePortException<PlatformException>(errorCode,
+                               core_function_name, "The method cannot proceed due to a severe system error. (I/O)");
+            break;
+        default:
+            MessagePortUtility::throwMessagePortException<NotFoundException>(errorCode,
+                               core_function_name, "The target application's port is not found. (Unknown code)");
+            break;
+        }
+    }
+
+    RemoteMessagePortPtr remoteMessagePort = getCachedRemoteMessagePort(appId, name, isTrusted);
+
+    if (remoteMessagePort.get() == NULL)
+    {
+        remoteMessagePort = RemoteMessagePortPtr(new RemoteMessagePort(appId, name, isTrusted));
+
+        cacheRemoteMessagePort(appId, name, isTrusted, remoteMessagePort);
+    }
+
+    return remoteMessagePort;
+}
+
+void MessagePortManagerProxy::cacheLocalMessagePort(int id, std::string &name, bool isTrusted, LocalMessagePortPtr &localMessagePort)
+{
+    LocalMessagePortKey key = { name, isTrusted };
+
+    LocalMessagePortPair keyPair(key, localMessagePort);
+    m_localMessagePortMap.insert(keyPair);
+    LocalMessagePortIdPair idPair(id, localMessagePort);
+    m_localMessagePortIdMap.insert(idPair);
+}
+
+LocalMessagePortPtr MessagePortManagerProxy::getCachedLocalMessagePort(string &name, bool isTrusted)
+{
+    LocalMessagePortPtr localMessagePort(static_cast<ILocalMessagePort*>(NULL));
+
+    LocalMessagePortKey key = { name, isTrusted };
+    LocalMessagePortMap::iterator iter = m_localMessagePortMap.find(key);
+    if (iter != m_localMessagePortMap.end())
+    {
+        localMessagePort = iter->second;
+        LOGD("Found cached LocalMessagePort");
+    }
+
+    return localMessagePort;
+}
+
+LocalMessagePortPtr MessagePortManagerProxy::getCachedLocalMessagePort(int id)
+{
+    LocalMessagePortPtr localMessagePort(static_cast<ILocalMessagePort*>(NULL));
+
+    LocalMessagePortIdMap::iterator iter = m_localMessagePortIdMap.find(id);
+    if (iter != m_localMessagePortIdMap.end())
+    {
+        localMessagePort = iter->second;
+        LOGD("Found cached LocalMessagePort");
+    }
+
+    return localMessagePort;
+}
+
+void MessagePortManagerProxy::cacheRemoteMessagePort(std::string &appId, std::string &name, bool isTrusted, RemoteMessagePortPtr &remoteMessagePort)
+{
+    RemoteMessagePortKey key = { appId, name, isTrusted };
+
+    RemoteMessagePortPair keyPair(key, remoteMessagePort);
+    m_remoteMessagePortMap.insert(keyPair);
+}
+
+RemoteMessagePortPtr MessagePortManagerProxy::getCachedRemoteMessagePort(string &appId, string &name, bool isTrusted)
+{
+    RemoteMessagePortPtr remoteMessagePort(static_cast<IRemoteMessagePort*>(NULL));
+
+    RemoteMessagePortKey key = { appId, name, isTrusted };
+    RemoteMessagePortMap::iterator iter = m_remoteMessagePortMap.find(key);
+    if (iter != m_remoteMessagePortMap.end())
+    {
+        remoteMessagePort = iter->second;
+        LOGD("Found cached RemoteMessagePort");
+    }
+
+    return remoteMessagePort;
+}
+
+void MessagePortManagerProxy::messagePortMessageCb(int id, const char* remote_app_id,
+        const char* remote_port, bool trusted_message, bundle* data)
+{
+    LOGD("<== %s:%s[%c] (%d)", (remote_app_id?remote_app_id:"NULL"),
+            (remote_port?remote_port:"NULL"),
+            (trusted_message?'T':' '), id);
+
+    LocalMessagePortPtr localMessagePort = getCachedLocalMessagePort(id);
+    if (localMessagePort.get() == NULL)
+    {
+        LOGW("There is no local message port id : %d", id);
+        return;
+    }
+
+    RemoteMessagePortPtr remoteMessagePort(static_cast<IRemoteMessagePort*>(NULL));
+
+    if (remote_app_id != NULL && remote_port != NULL)
+    {
+        string remoteAppId(remote_app_id);
+        string remotePortName(remote_port);
+        Try
+        {
+            remoteMessagePort = getRemoteMessagePort(remoteAppId, remotePortName, trusted_message);
+        }
+        Catch(Exception)
+        {
+            LOGE("Error on getRemoteMessagePort : %s", _rethrown_exception.GetMessage().c_str());
+        }
+    }
+
+    MessagePortDataItemMapPtr dataItemMap = MessagePortUtilitySingleton::Instance().getDataItemMap(data);
+
+    localMessagePort->OnMessageReceived(dataItemMap, remoteMessagePort);
+
+    MessagePortUtilitySingleton::Instance().releaseBundle(data);
+}
+
+// private static
+void MessagePortManagerProxy::message_port_message_cb(int id, const char* remote_app_id,
+        const char* remote_port, bool trusted_message, bundle* data)
+{
+    MessagePortManagerProxySingleton::Instance().messagePortMessageCb(id, remote_app_id,
+            remote_port, trusted_message, data);
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/MessagePortManagerProxy.h b/src/MessagePort/MessagePortManagerProxy.h
new file mode 100755 (executable)
index 0000000..897e709
--- /dev/null
@@ -0,0 +1,110 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagePortManagerProxy.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_MANAGER_WRAPPER_H_
+#define _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_MANAGER_WRAPPER_H_
+
+#include <string>
+#include <map>
+
+#include <dpl/singleton.h>
+#include "ILocalMessagePort.h"
+#include "IRemoteMessagePort.h"
+
+#include <message-port.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+#define UNDEFINED_LOCAL_PORT_ID (-1)
+
+class MessagePortManagerProxy
+{
+public:
+    MessagePortManagerProxy();
+    virtual ~MessagePortManagerProxy();
+
+    LocalMessagePortPtr requestLocalMessagePort(std::string &messagePortName);
+    LocalMessagePortPtr requestTrustedLocalMessagePort(std::string &messagePortName);
+    RemoteMessagePortPtr requestRemoteMessagePort(std::string &appId, std::string &messagePortName);
+    RemoteMessagePortPtr requestTrustedRemoteMessagePort(std::string &appId, std::string &messagePortName);
+
+    void sendMessage(std::string appId, std::string name, bool isTrusted,
+            MessagePortDataItemMapPtr &data, int localPortId = UNDEFINED_LOCAL_PORT_ID);
+
+protected:
+    LocalMessagePortPtr getLocalMessagePort(std::string &name, bool isTrusted);
+    RemoteMessagePortPtr getRemoteMessagePort(std::string &appId, std::string &name, bool isTrusted);
+
+private:
+    void cacheLocalMessagePort(int id, std::string &name, bool isTrusted, LocalMessagePortPtr &localMessagePort);
+    LocalMessagePortPtr getCachedLocalMessagePort(std::string &name, bool isTrusted);
+    LocalMessagePortPtr getCachedLocalMessagePort(int id);
+
+    void cacheRemoteMessagePort(std::string &appId, std::string &name, bool isTrusted, RemoteMessagePortPtr &remoteMessagePort);
+    RemoteMessagePortPtr getCachedRemoteMessagePort(std::string &appId, std::string &name, bool isTrusted);
+
+    struct LocalMessagePortKey {
+        std::string name;
+        bool isTrusted;
+        bool operator<(const LocalMessagePortKey &t) const {
+            return (name < t.name || (name == t.name && isTrusted < t.isTrusted));
+        }
+    };
+    struct RemoteMessagePortKey {
+        std::string appId;
+        std::string name;
+        bool isTrusted;
+        bool operator<(const RemoteMessagePortKey &t) const {
+            if (appId < t.appId) return true;
+            if (appId == t.appId) {
+                if (name < t.name) return true;
+                if (name == t.name && isTrusted < t.isTrusted)
+                    return true;
+            }
+            return false;
+        }
+    };
+    typedef std::map<LocalMessagePortKey, LocalMessagePortPtr> LocalMessagePortMap;
+    typedef std::pair<LocalMessagePortKey, LocalMessagePortPtr> LocalMessagePortPair;
+    typedef std::map<int, LocalMessagePortPtr> LocalMessagePortIdMap;
+    typedef std::pair<int, LocalMessagePortPtr> LocalMessagePortIdPair;
+    typedef std::map<RemoteMessagePortKey, RemoteMessagePortPtr> RemoteMessagePortMap;
+    typedef std::pair<RemoteMessagePortKey, RemoteMessagePortPtr> RemoteMessagePortPair;
+
+    LocalMessagePortMap m_localMessagePortMap;
+    LocalMessagePortIdMap m_localMessagePortIdMap;
+    RemoteMessagePortMap m_remoteMessagePortMap;
+
+public:
+    void messagePortMessageCb(int id, const char* remote_app_id, const char* remote_port,
+            bool trusted_message, bundle* data);
+    static void message_port_message_cb(int id, const char* remote_app_id,
+            const char* remote_port, bool trusted_message, bundle* data);
+};
+typedef DPL::Singleton<MessagePortManagerProxy> MessagePortManagerProxySingleton;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_MANAGER_WRAPPER_H_
diff --git a/src/MessagePort/MessagePortUtility.cpp b/src/MessagePort/MessagePortUtility.cpp
new file mode 100755 (executable)
index 0000000..2452646
--- /dev/null
@@ -0,0 +1,142 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/*
+ * @file        MessagePortUtility.cpp
+ * @version     0.1
+ * @brief
+ */
+
+#include "MessagePortUtility.h"
+
+#include <cstdlib>
+#include <clocale>
+#include <sstream>
+#include <dpl/singleton_impl.h>
+#include <Commons/Regex.h>
+#include <Logger.h>
+
+IMPLEMENT_SINGLETON(DeviceAPI::MessagePort::MessagePortUtility)
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+
+MessagePortUtility::MessagePortUtility()
+{
+    setlocale(LC_ALL, "");
+}
+
+MessagePortUtility::~MessagePortUtility()
+{
+}
+
+string MessagePortUtility::wstrToStr(const wstring &wstr)
+{
+    char *buf = new char[ wstr.size() * 4 ];
+    wcstombs(buf, &wstr[0], wstr.size()*4);
+    string result(buf);
+
+    delete[] buf;
+
+    return result;
+}
+
+wstring MessagePortUtility::strToWstr(const string &str)
+{
+    setlocale(LC_ALL, "");
+    wchar_t *buf = new wchar_t[ str.size() ];
+    size_t numChars = mbstowcs( buf, str.c_str(), str.size() );
+    wstring result( buf, numChars );
+    delete[] buf;
+
+    return result;
+}
+
+MessagePortDataItemMapPtr MessagePortUtility::getDataItemMap(bundle *b)
+{
+    MessagePortDataItemMapPtr dataMap(new MessagePortDataItemMap());
+
+    if (b == NULL)
+        return dataMap;
+
+    bundle_foreach(b, getDataItemMapHelper, static_cast<void *>(dataMap.get()));
+
+    return dataMap;
+}
+
+bundle *MessagePortUtility::getBundle(MessagePortDataItemMapPtr &data)
+{
+    bundle *b = bundle_create();
+
+    for (MessagePortDataItemMap::iterator iter = data->begin(); iter != data->end(); iter++)
+    {
+        string key = iter->first;
+        string value = iter->second;
+
+        bundle_add_str(b, key.c_str(), value.c_str());
+    }
+
+    return b;
+}
+
+void MessagePortUtility::releaseBundle(bundle *b)
+{
+    if (b != NULL)
+    {
+        bundle_free(b);
+    }
+}
+
+void MessagePortUtility::getDataItemMapHelper(const char *key, const int type, const bundle_keyval_t *kv, void *user_data)
+{
+    if (type != BUNDLE_TYPE_STR)
+    {
+        LOGW("bundle has wrong data type. (type : %d)", type);
+        return;
+    }
+
+    MessagePortDataItemMap *dataMap = static_cast<MessagePortDataItemMap *>(user_data);
+
+    void *basic_val = NULL;
+    size_t basic_size = 0;
+
+    bundle_keyval_t *kv_tmp = const_cast<bundle_keyval_t *>(kv);
+
+    bundle_keyval_get_basic_val(kv_tmp, &basic_val, &basic_size);
+
+    string valueStr(static_cast<char *>(basic_val));
+
+    MessagePortDataItemPair keyPair(key, valueStr);
+
+    dataMap->insert(keyPair);
+}
+
+std::string MessagePortUtility::getMessagePortLogMessage(const int errorCode,
+        const std::string &hint,
+        const std::string &messageToThrow)
+{
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << messageToThrow << ", " << errorCode;
+    return ss.str();
+}
+
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/MessagePortUtility.h b/src/MessagePort/MessagePortUtility.h
new file mode 100755 (executable)
index 0000000..f0433cc
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/*
+ * @file        MessagePortUtility.h
+ * @version     0.1
+ * @brief       
+ */
+
+#ifndef _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_UTILITY_H_
+#define _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_UTILITY_H_
+
+#include <string>
+#include <dpl/singleton.h>
+#include <bundle.h>
+#include <Logger.h>
+#include "MessagePortDataItem.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class MessagePortUtility
+{
+public:
+    MessagePortUtility();
+    virtual ~MessagePortUtility();
+
+    std::string wstrToStr(const std::wstring &wstr);
+    std::wstring strToWstr(const std::string &str);
+
+    MessagePortDataItemMapPtr getDataItemMap(bundle *b);
+    bundle * getBundle(MessagePortDataItemMapPtr &data);
+    void releaseBundle(bundle *b);
+
+    static std::string getMessagePortLogMessage(const int errorCode,
+               const std::string &hint,
+               const std::string &messageToThrow);
+
+    template <class T>
+    static void throwMessagePortException(
+              const int errorCode,
+              const std::string &hint,
+              const std::string &messageToThrow = "")
+    {
+
+        std::string log = MessagePortUtility::getMessagePortLogMessage(errorCode, hint, messageToThrow);
+        LOGE("%s", log.c_str());
+        ThrowMsg(T, log.c_str());
+    }
+
+private:
+    static void getDataItemMapHelper(const char *key, const int type, const bundle_keyval_t *kv, void *user_data);
+};
+typedef DPL::Singleton<MessagePortUtility> MessagePortUtilitySingleton;
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _PLATFORM_MESSAGE_PORT_MESSAGE_PORT_UTILITY_H_
diff --git a/src/MessagePort/RemoteMessagePort.cpp b/src/MessagePort/RemoteMessagePort.cpp
new file mode 100755 (executable)
index 0000000..c8843d6
--- /dev/null
@@ -0,0 +1,143 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        RemoteMessagePort.cpp
+ * @version     0.1
+ * @brief
+ */
+
+#include "RemoteMessagePort.h"
+#include "LocalMessagePort.h"
+#include "MessagePortManagerProxy.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+
+RemoteMessagePort::RemoteMessagePort(string appId, string name, bool isTrusted) :
+        IRemoteMessagePort(),
+        m_appId(appId),
+        m_name(name),
+        m_isTrusted(isTrusted)
+{
+}
+
+RemoteMessagePort::~RemoteMessagePort()
+{
+}
+
+std::string RemoteMessagePort::getMessagePortName() const
+{
+    return m_name;
+}
+
+void RemoteMessagePort::setMessagePortName(const std::string &value)
+{
+}
+
+std::string RemoteMessagePort::getAppId() const
+{
+    return m_appId;
+}
+
+void RemoteMessagePort::setAppId(const std::string &value)
+{
+}
+
+bool RemoteMessagePort::getIsTrusted() const
+{
+    return m_isTrusted;
+}
+
+void RemoteMessagePort::setIsTrusted(const bool &value)
+{
+}
+
+void RemoteMessagePort::OnRequestReceived(const EventRemoteMessagePortSendMessagePtr &event)
+{
+    LOGD("entered");
+
+    Try
+    {
+        if (!event->getDataIsSet()) {
+            LOGE("Failed to get data from event.");
+            ThrowMsg(InvalidArgumentException, "Failed to get data from event.");
+        }
+        MessagePortDataItemMapPtr data = event->getData();
+
+        if (event->getLocalMessagePortIsSet())
+        {
+            LocalMessagePort *localMessagePortImpl =
+                    dynamic_cast<LocalMessagePort *>(event->getLocalMessagePort().get());
+            if (localMessagePortImpl == NULL) {
+                LOGE("Failed to get platform LocalMessagePort from event.");
+                ThrowMsg(ConversionException, "Failed to get platform LocalMessagePort from event.");
+            }
+            int localPortId = localMessagePortImpl->getPlatformLocalMessagePortId();
+            MessagePortManagerProxySingleton::Instance().sendMessage(m_appId, m_name, m_isTrusted, data, localPortId);
+        }
+        else
+        {
+            MessagePortManagerProxySingleton::Instance().sendMessage(m_appId, m_name, m_isTrusted, data);
+        }
+
+        event->setResult(true);
+    }
+    Catch(InvalidArgumentException)
+    {
+        LOGE("Error [InvalidArguments] : %s",  _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
+        event->setResult(false);
+    }
+    Catch(ConversionException)
+    {
+        LOGE("Error [ConversionException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::ConversionException);
+        event->setResult(false);
+    }
+    Catch(NotFoundException)
+    {
+        LOGE("Error [NotFound] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::NotFoundException);
+        event->setResult(false);
+    }
+    Catch(OutOfRangeException)
+    {
+        LOGE("Error [OutOfRange] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::OutOfRangeException);
+        event->setResult(false);
+    }
+    Catch(PlatformException)
+    {
+        LOGE("Error [PlatformException] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+        event->setResult(false);
+    }
+    Catch(Exception)
+    {
+        LOGE("Error [Unknown] : %s", _rethrown_exception.GetMessage().c_str());
+        event->setExceptionCode(ExceptionCodes::UnknownException);
+        event->setResult(false);
+    }
+}
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/MessagePort/RemoteMessagePort.h b/src/MessagePort/RemoteMessagePort.h
new file mode 100644 (file)
index 0000000..239d761
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        RemoteMessagePort.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _PLATFORM_MESSAGE_PORT_REMOTE_MESSAGE_PORT_H_
+#define _PLATFORM_MESSAGE_PORT_REMOTE_MESSAGE_PORT_H_
+
+#include <string>
+#include "IRemoteMessagePort.h"
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+class RemoteMessagePort : public IRemoteMessagePort
+{
+public:
+    RemoteMessagePort(std::string appId, std::string name, bool isTrusted);
+    virtual ~RemoteMessagePort();
+
+    virtual void sendMessage(const EventRemoteMessagePortSendMessagePtr &event)
+    {
+        OnRequestReceived(event);
+    }
+
+    virtual std::string getMessagePortName() const;
+    virtual void        setMessagePortName(const std::string &value);
+    virtual std::string getAppId() const;
+    virtual void        setAppId(const std::string &value);
+    virtual bool        getIsTrusted() const;
+    virtual void        setIsTrusted(const bool &value);
+
+protected:
+    virtual void    OnRequestReceived(const EventRemoteMessagePortSendMessagePtr &event);
+
+private:
+    std::string m_appId;
+    std::string m_name;
+    bool m_isTrusted;
+};
+
+} // MessagePort
+} // DeviceAPI
+
+#endif // _PLATFORM_MESSAGE_PORT_REMOTE_MESSAGE_PORT_H_
diff --git a/src/MessagePort/config.xml b/src/MessagePort/config.xml
new file mode 100644 (file)
index 0000000..99ea66d
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-messageport.so</library-name>
+    <feature-install-uri>messageport.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/messageport</name>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/MessagePort/plugin_initializer.cpp b/src/MessagePort/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..4cc2e62
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        plugin_initializer.cpp
+ * @version     0.1
+ * @brief
+ */
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <TimeTracer.h>
+#include "JSMessagePortManager.h"
+#include "MessagePortListenerManager.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace MessagePort {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\MessagePort] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    Try
+    {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\MessagePort] on_widget_stop_callback (%d)", widgetId);
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"MessagePort");
+    TIME_TRACER_RELEASE();
+    Try
+    {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\MessagePort] on_frame_load_callback (%p)", context);
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\MessagePort] on_frame_unload_callback (%p)", context);
+
+    DeviceAPI::MessagePort::MessagePortListenerManagerSingleton::Instance().unregisterContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "messageport",
+        (js_class_template_getter)DeviceAPI::MessagePort::JSMessagePortManager::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_END
+
+} // MessagePort
+} // DeviceAPI
diff --git a/src/Messaging/BaseFilterVisitor.cpp b/src/Messaging/BaseFilterVisitor.cpp
new file mode 100644 (file)
index 0000000..47ab777
--- /dev/null
@@ -0,0 +1,236 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        BaseFilterVisitor.cpp
+ */
+
+#include "BaseFilterVisitor.h"
+#include <Logger.h>
+#include <cstring>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+inline std::string convertToLowerCase(const std::string& input_string)
+{
+    std::string outputString=input_string;
+    outputString.reserve(input_string.length());
+    std::transform(outputString.begin(), outputString.end(), outputString.begin(),
+            ::tolower);
+    return outputString;
+}
+
+BaseFilterVisitor::BaseFilterVisitor()
+{
+}
+
+BaseFilterVisitor::~BaseFilterVisitor()
+{
+}
+
+void BaseFilterVisitor::visitPreComposite(Tizen::FilterType& type, int depth)
+{
+    LOGD("Entered");
+    m_operand_list.push_back(FCO_START);
+}
+
+void BaseFilterVisitor::visitInComposite(Tizen::FilterType& type, int depth)
+{
+    LOGD("Entered");
+    if(Tizen::UNION_FILTER == type) {
+        m_operand_list.push_back(FCO_OR);
+        LOGD("operand OR");
+    }else if(Tizen::INTERSECTION_FILTER == type) {
+        LOGD("operand AND");
+        m_operand_list.push_back(FCO_AND);
+    } else {
+        LOGE("Invalid filter type:%d", type);
+    }
+}
+
+void BaseFilterVisitor::visitPostComposite(Tizen::FilterType& type, int depth)
+{
+    LOGD("Entered");
+    LOGD("Start: numResults:%d numOperands:%d", m_result_list.size(),
+            m_operand_list.size());
+
+    while(m_operand_list.back() != FCO_START) {
+
+        const bool left =  m_result_list.back();
+        m_result_list.pop_back();
+        const bool right =  m_result_list.back();
+        m_result_list.pop_back();
+        const FilterCompositeOperand& operand = m_operand_list.back();
+        m_operand_list.pop_back();
+
+        bool result = false;
+        if(FCO_AND == operand) {
+            result = left && right;
+        } else if(FCO_OR == operand) {
+            result = left || right;
+        }
+        m_result_list.push_back(result);
+    }
+
+    m_operand_list.pop_back(); //remove FCO_START
+    LOGD("End: numResults:%d numOperands:%d", m_result_list.size(),
+            m_operand_list.size());
+}
+
+void BaseFilterVisitor::testStringMatch(const std::string& key,
+        const std::string& value,
+        Tizen::MatchFlag flag)
+{
+    m_result_list.push_back(matchString(key, value, flag));
+}
+
+void BaseFilterVisitor::testAnyStringMatch(const std::string& key,
+        const std::vector<std::string>& values,
+        Tizen::MatchFlag flag)
+{
+    m_result_list.push_back(matchStringVector(key, values, flag));
+}
+
+void BaseFilterVisitor::testTimeStampIsInRange(const time_t& timeStamp,
+            Tizen::AnyPtr& initialValue, Tizen::AnyPtr& endValue)
+{
+    m_result_list.push_back(matchTimeStampRange(timeStamp, initialValue, endValue));
+}
+
+bool BaseFilterVisitor::matchString(const std::string& key,
+        const std::string& value,
+        Tizen::MatchFlag flag)
+{
+    bool res = false;
+
+    switch(flag)
+    {
+        case Tizen::MATCH_ENDSWITH: {
+            if (key.empty()) return false;
+            if (key.size() > value.size()) return false;
+            std::string lvalue = convertToLowerCase(value);
+            std::string lkey = convertToLowerCase(key);
+            res = lvalue.substr(lvalue.size() - lkey.size(), lkey.size()) == lkey;
+        } break;
+
+        case Tizen::MATCH_EXACTLY: {
+            res = key == value;
+        } break;
+
+        case Tizen::MATCH_STARTSWITH: {
+            if (key.empty()) return false;
+            if (key.size() > value.size()) return false;
+            std::string lvalue = convertToLowerCase(value);
+            std::string lkey = convertToLowerCase(key);
+            res = lvalue.substr(0, lkey.size()) == lkey;
+        } break;
+
+        case Tizen::MATCH_CONTAINS: {
+            if (key.empty()) return false;
+            if (key.size() > value.size()) return false;
+            std::string lvalue = convertToLowerCase(value);
+            std::string lkey = convertToLowerCase(key);
+            res = lvalue.find(lkey) != std::string::npos;
+        } break;
+
+        default: {
+            LOGE("Unknown match flag");
+            res =  false;
+        } break;
+    }
+
+    LOGD("key:%s value:%s matchFlag:%d RESULT:%d", key.c_str(), value.c_str(), flag, res);
+    return res;
+}
+
+bool BaseFilterVisitor::matchStringVector(const std::string& key,
+        const std::vector<std::string>& values,
+        Tizen::MatchFlag flag)
+{
+    for(auto it = values.begin(); it != values.end(); ++it) {
+        if(matchString(key,*it,flag)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool BaseFilterVisitor:: matchTimeStampRange(const time_t& timeStamp,
+        Tizen::AnyPtr& initialValue, Tizen::AnyPtr& endValue)
+{
+    time_t from_time;
+    time_t to_time;
+
+    if (initialValue && !initialValue->isNullOrUndefined() &&
+            initialValue->isType(DeviceAPI::Tizen::PrimitiveType_Time)) {
+        struct tm ftime = *initialValue->getDateTm();
+        from_time = mktime(&ftime);
+    } else {
+        LOGE("initialValue is not Time!");
+        throw Common::InvalidValuesException("initialValue is not Time!");
+    }
+
+    if (endValue && !endValue->isNullOrUndefined() &&
+            endValue->isType(DeviceAPI::Tizen::PrimitiveType_Time) ) {
+        struct tm ttime = *endValue->getDateTm();
+        to_time = mktime(&ttime);
+    } else {
+        LOGE("endValue is not Time!");
+        throw Common::InvalidValuesException("endValue is not Time!");
+    }
+
+    bool isInRange = isBetweenTimeRange(timeStamp, from_time, to_time);
+
+    LOGD("%d is%s in time range <%d, %d>", timeStamp, (isInRange ? "" : " NOT"),
+            from_time, to_time);
+
+    return isInRange;
+}
+
+bool BaseFilterVisitor::isMatched()
+{
+    if(m_result_list.empty()) {
+        LOGW("m_result_list is empty!");
+        return false;
+    }
+    return m_result_list.back();
+}
+
+std::string BaseFilterVisitor::formatResultListChangeLog(const size_t old_res_count)
+{
+    const size_t new_res_count = m_result_list.size();
+    const int delta = new_res_count - old_res_count;
+    std::ostringstream oss;
+
+    if(delta > 0) {
+        oss << "m_result_list added: "<< delta << " {" << std::endl;
+        std::vector<bool>::reverse_iterator rit = m_result_list.rbegin();
+        for(size_t i = 0; i < delta; ++i, ++rit) {
+            const bool result = *rit;
+            oss << "    [LAST -" << (delta - (i+1)) <<"] added: "<< result;
+        }
+        oss << "}" << std::endl;
+    } else if(delta < 0) {
+        oss <<"m_result_list removed: "<< delta;
+    }
+
+    return oss.str();
+}
+
+} //namespace Messaging
+} //namespace DeviceAPI
diff --git a/src/Messaging/CMakeLists.txt b/src/Messaging/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..e9c8ec3
--- /dev/null
@@ -0,0 +1,106 @@
+SET(TARGET_NAME ${messaging_target})
+SET(DESTINATION_NAME ${messaging_dest})
+SET(TARGET_IMPL_NAME ${messaging_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_messaging REQUIRED msg-service email-service
+                  dbus-1 capi-system-info dbus-glib-1 tapi)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+SET(INCLUDE_DIRS
+    ${filesystem_include}
+    ${messaging_include}
+    ${tizen_include}
+    ${platform_pkgs_messaging_INCLUDE_DIRS}
+)
+
+INCLUDE_DIRECTORIES(${INCLUDE_COMMON} ${INCLUDE_DIRS})
+MESSAGE(STATUS "${TARGET_NAME} module includes: INCLUDE_COMMON ${INCLUDE_DIRS}")
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${filesystem_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    ChangeListenerContainer.cpp
+    JSMessagingManager.cpp
+    MessagingManager.cpp
+    JSMessage.cpp
+    JSMessageAttachment.cpp
+    JSMessageBody.cpp
+    JSMessageConversation.cpp
+    JSMessageFolder.cpp
+    JSMessageService.cpp
+    MessageService.cpp
+    MessageServiceShortMsg.cpp
+    MessageServiceEmail.cpp
+    ShortMsgManager.cpp
+    EmailManager.cpp
+    MessageCallbackUserData.cpp
+    MessagesCallbackUserData.cpp
+    ConversationCallbackData.cpp
+    FoldersCallbackData.cpp
+    JSMessageStorage.cpp
+    MessageStorage.cpp
+    MessageStorageEmail.cpp
+    MessageStorageShortMsg.cpp
+    MessagingUtil.cpp
+    JSMessageAttachment.cpp
+    MessageAttachment.cpp
+    Message.cpp
+    MessageEmail.cpp
+    MessageMMS.cpp
+    MessageSMS.cpp
+    MessageConversation.cpp
+    MessageBody.cpp
+    MessageFolder.cpp
+    JSMessageFolder.cpp
+    MessagesChangeCallback.cpp
+    ConversationsChangeCallback.cpp
+    FoldersChangeCallback.cpp
+    FindMsgCallbackUserData.cpp
+    DBus/Connection.cpp
+    DBus/Proxy.cpp
+    DBus/SyncProxy.cpp
+    DBus/LoadBodyProxy.cpp
+    DBus/LoadAttachmentProxy.cpp
+    DBus/EmailSignalProxy.cpp
+    DBus/MessageProxy.cpp
+    DBus/SendProxy.cpp
+    MessagingDatabaseManager.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+SET(LINK_LIBS
+    ${LIBS_WIDGETDB}
+    ${filesystem_config}
+    ${filesystem_impl}
+    ${tizen_impl}
+    ${platform_pkgs_messaging_LIBRARIES}
+)
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME} ${LIBS_COMMON} ${LINK_LIBS})
+MESSAGE(STATUS "${TARGET_NAME} module links: LIBS_COMMON ${LINK_LIBS}")
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+    "-Wl,--no-as-needed" ${filesystem_config}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/messaging
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Messaging/ChangeListenerContainer.cpp b/src/Messaging/ChangeListenerContainer.cpp
new file mode 100644 (file)
index 0000000..ef32e51
--- /dev/null
@@ -0,0 +1,456 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ChangeListenerContainer.h"
+
+#include <Logger.h>
+#include "EmailManager.h"
+#include "ShortMsgManager.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+ChangeListenerContainer& ChangeListenerContainer::getInstance()
+{
+    EmailManager::getInstance(); //make sure that callbacks are registered in email-service
+    ShortMsgManager::getInstance(); //make sure that callbacks are registered in msg-service
+    static ChangeListenerContainer clc;
+    return clc;
+}
+
+ChangeListenerContainer::ChangeListenerContainer():
+        m_current_id(0)
+{
+    LOGD("Entered");
+    // call getNextId() function to properly initialize static mutex inside
+    getNextId();
+}
+
+// --- Listeners registration functions ---
+long ChangeListenerContainer::addMessageChangeListener(
+        std::shared_ptr<MessagesChangeCallback> callback)
+{
+    LOGD("Entered");
+    // Check type of service for which listener should be registered
+    // and lock appropriate mutex
+    MessageType mtype = callback->getServiceType();
+    if (MessageType(SMS) == mtype || MessageType(MMS) == mtype)
+    {
+        std::lock_guard<std::mutex> lock(m_short_lock);
+        int new_id = getNextId();
+        m_short_message_callbacks.insert(std::make_pair(new_id, callback));
+        LOGD("Added callback for ShortMessage, watchId: %d", new_id);
+        return new_id;
+    }
+    else if (MessageType(EMAIL) == mtype) {
+        std::lock_guard<std::mutex> lock(m_email_lock);
+        int new_id = getNextId();
+        m_email_message_callbacks.insert(std::make_pair(new_id, callback));
+        LOGD("Added callback for Email, watchId: %d", new_id);
+        return new_id;
+    }
+    LOGE("Listener with invalid MessageService type - failed to register");
+    return -1;
+}
+
+long ChangeListenerContainer::addConversationChangeListener(
+        std::shared_ptr<ConversationsChangeCallback> callback)
+{
+    LOGD("Entered");
+    // Check type of service for which listener should be registered
+    // and lock appropriate mutex
+    MessageType mtype = callback->getServiceType();
+    if (MessageType(SMS) == mtype || MessageType(MMS) == mtype)
+    {
+        std::lock_guard<std::mutex> lock(m_short_lock);
+        int new_id = getNextId();
+        m_short_conversation_callbacks.insert(std::make_pair(new_id, callback));
+        LOGD("Added callback for ShortMessage, watchId: %d", new_id);
+        return new_id;
+    }
+    else if (MessageType(EMAIL) == mtype) {
+        std::lock_guard<std::mutex> lock(m_email_lock);
+        int new_id = getNextId();
+        m_email_conversation_callbacks.insert(std::make_pair(new_id, callback));
+        LOGD("Added callback for Email, watchId: %d", new_id);
+        return new_id;
+    }
+    LOGE("Listener with invalid MessageService type - failed to register");
+    return -1;
+}
+
+long ChangeListenerContainer::addFolderChangeListener(
+        std::shared_ptr<FoldersChangeCallback> callback)
+{
+    LOGD("Entered");
+    // Check type of service for which listener should be registered
+    // and lock appropriate mutex
+    MessageType mtype = callback->getServiceType();
+    if (MessageType(SMS) == mtype || MessageType(MMS) == mtype)
+    {
+        std::lock_guard<std::mutex> lock(m_short_lock);
+        int new_id = getNextId();
+        m_short_folder_callbacks.insert(std::make_pair(new_id, callback));
+        LOGD("Added callback for ShortMessage, watchId: %d", new_id);
+        return new_id;
+    }
+    else if (MessageType(EMAIL) == mtype) {
+        std::lock_guard<std::mutex> lock(m_email_lock);
+        int new_id = getNextId();
+        m_email_folder_callbacks.insert(std::make_pair(new_id, callback));
+        LOGD("Added callback for Email, watchId: %d", new_id);
+        return new_id;
+    }
+    LOGE("Listener with invalid MessageService type - failed to register");
+    return -1;
+}
+
+// --- listeners removal ---
+void ChangeListenerContainer::removeChangeListener(JSContextRef context, long id)
+{
+    LOGD("Entered");
+    // Lock both types of collections - id does not indicate service type
+    // TODO: consider additional map<listener_id, service_type> or
+    //       map<lister_id, map<>&> to provide faster and less complicated removal
+    std::lock_guard<std::mutex> shortlock(m_short_lock);
+    std::lock_guard<std::mutex> maillock(m_email_lock);
+    LOGD("Locks done");
+    if(id<0 || id > m_current_id) {
+        LOGE("Invalid id %d given.", id);
+        return;
+    }
+    if (removeCallbackIfExists<MessagesChangeCallback>(
+            context, m_short_message_callbacks,id)) {
+        LOGD("ShortMessage message listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<ConversationsChangeCallback>(
+            context, m_short_conversation_callbacks, id)) {
+        LOGD("ShortMessage conversation listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<FoldersChangeCallback>(
+            context, m_short_folder_callbacks, id)) {
+        LOGD("ShortMessage folder listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<MessagesChangeCallback>(
+            context, m_email_message_callbacks, id)) {
+        LOGD("Email message listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<ConversationsChangeCallback>(
+            context, m_email_conversation_callbacks, id)) {
+        LOGD("Email conversation listener with id: %d removed", id);
+    }
+    else if (removeCallbackIfExists<FoldersChangeCallback>(
+            context, m_email_folder_callbacks,id)) {
+        LOGD("Email folder listener with id: %d removed", id);
+    }
+    else {
+        LOGW("WatchId %d not found", id);
+    }
+}
+
+// --- Callback invoking functions ---
+// -- for message --
+void ChangeListenerContainer::callMessageAdded(EventMessages* event)
+{
+    LOGD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LOGD("Calling messageadded for ShortMessage");
+        MCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            callbacksCopy = m_short_message_callbacks;
+        }
+        callAdded<MessagesChangeCallback, EventMessages>(
+                callbacksCopy, event);
+    }
+    else if(MessageType(EMAIL) == event->service_type) {
+        LOGD("Calling messageadded for Email");
+        MCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            callbacksCopy = m_email_message_callbacks;
+        }
+        callAdded<MessagesChangeCallback, EventMessages>(
+                callbacksCopy, event);
+    }
+    else {
+        LOGW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callMessageUpdated(EventMessages* event)
+{
+    LOGD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LOGD("Calling messageupdated for ShortMessage");
+        MCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            callbacksCopy = m_short_message_callbacks;
+        }
+        callUpdated<MessagesChangeCallback, EventMessages>(
+                callbacksCopy, event);
+    }
+    else if(MessageType(EMAIL) == event->service_type) {
+        LOGD("Calling messageupdated for Email");
+        MCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            callbacksCopy = m_email_message_callbacks;
+        }
+        callUpdated<MessagesChangeCallback, EventMessages>(
+                callbacksCopy, event);
+    }
+    else {
+        LOGW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callMessageRemoved(EventMessages* event)
+{
+    LOGD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LOGD("Calling messageremoved for ShortMessage");
+        MCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            callbacksCopy = m_short_message_callbacks;
+        }
+        callRemoved<MessagesChangeCallback, EventMessages>(
+                callbacksCopy, event);
+    }
+    else if(MessageType(EMAIL) == event->service_type) {
+        LOGD("Calling messageremoved for Email");
+        MCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            callbacksCopy = m_email_message_callbacks;
+        }
+        callRemoved<MessagesChangeCallback, EventMessages>(
+                callbacksCopy, event);
+    }
+    else {
+        LOGW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+// -- for conversation --
+void ChangeListenerContainer::callConversationAdded(EventConversations* event)
+{
+    LOGD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LOGD("Calling converationadded for ShortMessage");
+        CCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            callbacksCopy = m_short_conversation_callbacks;
+        }
+        callAdded<ConversationsChangeCallback, EventConversations>(
+                callbacksCopy, event);
+    }
+    else if(MessageType(EMAIL) == event->service_type) {
+        LOGD("Calling conversationadded for Email");
+        CCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            callbacksCopy = m_email_conversation_callbacks;
+        }
+        callAdded<ConversationsChangeCallback, EventConversations>(
+                callbacksCopy, event);
+    }
+    else {
+        LOGW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callConversationUpdated(EventConversations* event)
+{
+    LOGD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LOGD("Calling conversationupdated for ShortConversation");
+        CCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            callbacksCopy = m_short_conversation_callbacks;
+        }
+        callUpdated<ConversationsChangeCallback, EventConversations>(
+                callbacksCopy, event);
+    }
+    else if(MessageType(EMAIL) == event->service_type) {
+        LOGD("Calling conversationupdated for Email");
+        CCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            callbacksCopy = m_email_conversation_callbacks;
+        }
+        callUpdated<ConversationsChangeCallback, EventConversations>(
+                callbacksCopy, event);
+    }
+    else {
+        LOGW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callConversationRemoved(EventConversations* event)
+{
+    LOGD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LOGD("Calling conversationremoved for ShortConversation");
+        CCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            LOGD("m_short_conversation_callbacks.size() = %d",
+                    m_short_conversation_callbacks.size());
+
+            callbacksCopy = m_short_conversation_callbacks;
+        }
+        callRemoved<ConversationsChangeCallback, EventConversations>(
+                callbacksCopy, event);
+    }
+    else if(MessageType(EMAIL) == event->service_type) {
+        LOGD("Calling conversationremoved for Email");
+        CCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            LOGD("m_email_conversation_callbacks.size() = %d",
+                m_email_conversation_callbacks.size());
+
+            callbacksCopy = m_email_conversation_callbacks;
+        }
+        callRemoved<ConversationsChangeCallback, EventConversations>(
+                callbacksCopy, event);
+    }
+    else {
+        LOGW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+// -- for folder --
+void ChangeListenerContainer::callFolderAdded(EventFolders* event)
+{
+    LOGD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LOGD("Calling folderadded for ShortMessage");
+        FCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            callbacksCopy = m_short_folder_callbacks;
+        }
+        callAdded<FoldersChangeCallback, EventFolders>(
+                m_short_folder_callbacks, event);
+    }
+    else if(MessageType(EMAIL) == event->service_type) {
+        LOGD("Calling folderadded for Email");
+        FCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            callbacksCopy = m_email_folder_callbacks;
+        }
+        callAdded<FoldersChangeCallback, EventFolders>(
+                callbacksCopy, event);
+    }
+    else {
+        LOGW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+
+void ChangeListenerContainer::callFolderUpdated(EventFolders* event)
+{
+    LOGD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LOGD("Calling folderupdated for ShortFolder");
+        FCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            callbacksCopy = m_short_folder_callbacks;
+        }
+        callUpdated<FoldersChangeCallback, EventFolders>(
+                callbacksCopy, event);
+    }
+    else if(MessageType(EMAIL) == event->service_type) {
+        LOGD("Calling folderupdated for Email");
+        FCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            callbacksCopy = m_email_folder_callbacks;
+        }
+        callUpdated<FoldersChangeCallback, EventFolders>(
+                callbacksCopy, event);
+    }
+    else {
+        LOGW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+void ChangeListenerContainer::callFolderRemoved(EventFolders* event)
+{
+    LOGD("Entered");
+
+    if(MessageType(SMS) == event->service_type ||
+            MessageType(MMS) == event->service_type) {
+        LOGD("Calling folderremoved for ShortFolder");
+        FCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> shortlock(m_short_lock);
+            callbacksCopy = m_short_folder_callbacks;
+        }
+        callRemoved<FoldersChangeCallback, EventFolders>(
+                callbacksCopy, event);
+    }
+    else if(MessageType(EMAIL) == event->service_type) {
+        LOGD("Calling folderremoved for Email");
+        FCLmap callbacksCopy;
+        {
+            std::lock_guard<std::mutex> maillock(m_email_lock);
+            callbacksCopy = m_email_folder_callbacks;
+        }
+        callRemoved<FoldersChangeCallback, EventFolders>(
+                callbacksCopy, event);
+    }
+    else {
+        LOGW("Invalid event type (%d) - no callback called.", event->service_type);
+    }
+}
+
+int ChangeListenerContainer::getNextId() {
+    // mutex is created only on first call (first call added to constructor
+    // to initialize mutex correctly
+    static std::mutex id_mutex;
+    std::lock_guard<std::mutex> idlock(id_mutex);
+
+    return m_current_id++;
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/ChangeListenerContainer.h b/src/Messaging/ChangeListenerContainer.h
new file mode 100755 (executable)
index 0000000..3fd7831
--- /dev/null
@@ -0,0 +1,251 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CHANGE_LISTENER_CONTAINER_H__
+#define __TIZEN_CHANGE_LISTENER_CONTAINER_H__
+
+#include <memory>
+#include <mutex>
+#include <vector>
+#include <map>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+#include "Message.h"
+#include "MessageConversation.h"
+#include "MessageFolder.h"
+#include "MessagingUtil.h"
+#include "MessagesChangeCallback.h"
+#include "ConversationsChangeCallback.h"
+#include "FoldersChangeCallback.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+//! Data related to MessageChange event passed to add/update/remove callbacks
+struct EventMessages {
+    int service_id;
+    MessageType service_type;
+    MessagePtrVector items;
+    ConversationPtrVector removed_conversations;
+    // TODO: Filtering support
+};
+
+//! Data related to ConversationChange event passed to add/update/remove callbacks
+struct EventConversations {
+    int service_id;
+    MessageType service_type;
+    ConversationPtrVector items;
+    // TODO: Filtering support
+};
+
+//! Data related to FolderChange event passed to add/update/remove callbacks
+struct EventFolders {
+    int service_id;
+    MessageType service_type;
+    FolderPtrVector items;
+    // TODO: Filtering support
+};
+
+template <class T > struct CallbackDataHolder {
+    std::shared_ptr<T> ptr;
+    int operation_type;
+};
+
+//! Map that stores MessageChangeListeners
+typedef std::map<long, std::shared_ptr<MessagesChangeCallback>> MCLmap;
+//! Map that stores ConversationsChangeListeners
+typedef std::map<long, std::shared_ptr<ConversationsChangeCallback>> CCLmap;
+//! Map that stores FoldersChangeListeners
+typedef std::map<long, std::shared_ptr<FoldersChangeCallback>> FCLmap;
+
+
+/**
+ * Singleton class for managing (storing and calling) ChangeListeners for
+ * short message (SMS/MMS) service and email service.
+ *
+ * Two mutexes used to lock separately addition and searching of Short and
+ * Email message related listeners. Listeneres removal functions locks access
+ * to both types of listeners (havind listener id only it is not possible
+ * to determine message (service) type.
+ */
+class ChangeListenerContainer {
+    public:
+        static ChangeListenerContainer& getInstance();
+
+
+        // Interface for listener's manipulation (registration and removal).
+        long addMessageChangeListener(std::shared_ptr<MessagesChangeCallback> callback);
+        long addConversationChangeListener(std::shared_ptr<ConversationsChangeCallback> callback);
+        long addFolderChangeListener(std::shared_ptr<FoldersChangeCallback> callback);
+        void removeChangeListener(JSContextRef context, long id);
+
+        // Methods used to invoke registered listeners
+        void callMessageAdded(EventMessages* event);
+        void callMessageUpdated(EventMessages* event);
+        void callMessageRemoved(EventMessages* event);
+        void callConversationAdded(EventConversations* event);
+        void callConversationUpdated(EventConversations* event);
+        void callConversationRemoved(EventConversations* event);
+        void callFolderAdded(EventFolders* event);
+        void callFolderUpdated(EventFolders* event);
+        void callFolderRemoved(EventFolders* event);
+
+    private:
+        //! Highest used id (in most cases id of last registered listener)
+        long m_current_id;
+        //! Mutex for preventing race conditions on SMS/MMS callbacks collection
+        std::mutex m_short_lock;
+        //! Mutex for preventing race conditions on email callbacks collection
+        std::mutex m_email_lock;
+
+        //! Functions for listener id incrementation with thread safe mutex locking
+        int getNextId();
+
+        /* Callbacks for emails and short messages should be stored in separate
+         * collections to simplyfy adding ang searching on call */
+
+        // Callbacks for short messages service
+        MCLmap m_short_message_callbacks;
+        CCLmap m_short_conversation_callbacks;
+        FCLmap m_short_folder_callbacks;
+
+        // Callbacks for email service
+        MCLmap m_email_message_callbacks;
+        CCLmap m_email_conversation_callbacks;
+        FCLmap m_email_folder_callbacks;
+
+        ChangeListenerContainer();
+
+        template<class T> static bool removeCallbackIfExists(
+                JSContextRef context, std::map<long,std::shared_ptr<T>>& collection, long id ) {
+            LOGD("Entered");
+
+            JSContextRef g_ctx = Common::GlobalContextManager::getInstance()->
+                    getGlobalContext(context);
+            auto itr = collection.find(id);
+            if ( itr != collection.end()) {
+                if(itr->second->getContext() == g_ctx){
+                    itr->second->setActive(false);
+                    collection.erase(id);
+                    return true;
+                } else {
+                    LOGE("Removing callback which does not belong to the current context is not allowed.");
+                    throw Common::NotFoundException(
+                            "Removing callback which does not belong to the current context is not allowed.");
+                }
+            }
+            return false;
+        }
+
+        /* Templates below written for code reusage (each template is used
+         * 2 times in each callXxxx[Added | Removed | Updated] function. */
+
+        /**
+         * Template function for calling "added" callback for all listeners
+         * from given collection with given event.
+         * */
+        template<class T, class U> void callAdded(
+                std::map<long,std::shared_ptr<T>>& collection,
+                U* event) {
+            typename std::map<long,std::shared_ptr<T>>::iterator itstart = collection.begin();
+            typename std::map<long,std::shared_ptr<T>>::iterator itend = collection.end();
+            try {
+                for (; itstart != itend; ++itstart) {
+                    auto callback = (*itstart).second;
+                    if (callback->getServiceType() == event->service_type
+                            && callback->getServiceId() == event->service_id) {
+                        LOGD("Found callback for given service id (%d) and type (%d)",
+                                event->service_id, event->service_type);
+                        //@todo filter msgs
+                        callback->added(event->items);
+                    }
+                }
+            }catch (const Common::BasePlatformException &err) {
+                LOGE("callAdded failed, %s: %s", err.getName().c_str(),
+                        err.getMessage().c_str());
+            }
+            catch (...) {
+                LOGE("callAdded failed");
+            }
+        }
+
+        /**
+         * Template function for calling "updated" callback for all listeners
+         * from given collection with given event.
+         * */
+        template<class T, class U> void callUpdated(
+                std::map<long,std::shared_ptr<T>>& collection,
+                U* event) {
+            typename std::map<long,std::shared_ptr<T>>::iterator itstart = collection.begin();
+            typename std::map<long,std::shared_ptr<T>>::iterator itend = collection.end();
+            try {
+                for (; itstart != itend; ++itstart) {
+                    auto callback = (*itstart).second;
+                    if (callback->getServiceType() == event->service_type
+                            && callback->getServiceId() == event->service_id) {
+                        LOGD("Found callback for given service id (%d) and type (%d)",
+                                event->service_id, event->service_type);
+                        //@todo filter msgs
+                        callback->updated(event->items);
+                    }
+                }
+            }catch (const Common::BasePlatformException &err) {
+                LOGE("callUpdated failed, %s: %s", err.getName().c_str(),
+                        err.getMessage().c_str());
+            }
+            catch (...) {
+                LOGE("callUpdated failed");
+            }
+        }
+
+        /**
+         * Template function for calling "removed" callback for all listeners
+         * from given collection with given event.
+         * */
+
+        template<class T, class U> void callRemoved(
+                std::map<long,std::shared_ptr<T>>& collection,
+                U* event) {
+            typename std::map<long,std::shared_ptr<T>>::iterator itstart = collection.begin();
+            typename std::map<long,std::shared_ptr<T>>::iterator itend = collection.end();
+            try {
+                for (; itstart != itend; ++itstart) {
+                    auto callback = (*itstart).second;
+                    if (callback->getServiceType() == event->service_type
+                            && callback->getServiceId() == event->service_id) {
+                        LOGD("Found callback for given service id (%d) and type (%d)",
+                                event->service_id, event->service_type);
+                        //@todo filter msgs
+                        callback->removed(event->items);
+                    }
+                }
+            }catch (const Common::BasePlatformException &err) {
+                LOGE("callRemoved failed, %s: %s", err.getName().c_str(),
+                        err.getMessage().c_str());
+            }
+            catch (...) {
+                LOGE("callRemoved failed");
+            }
+        }
+};
+
+
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_CHANGE_LISTENER_CONTAINER_H__
diff --git a/src/Messaging/ConversationCallbackData.cpp b/src/Messaging/ConversationCallbackData.cpp
new file mode 100644 (file)
index 0000000..51d309e
--- /dev/null
@@ -0,0 +1,151 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ConversationCallbackData.h"
+#include "JSMessageConversation.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+ConversationCallbackData::ConversationCallbackData(JSContextRef globalCtx):
+        CallbackUserData(globalCtx),
+        m_filter(),
+        m_sort(),
+        m_limit(0),
+        m_offset(0),
+        m_is_error(false),
+        m_account_id(0),
+        m_service_type(UNDEFINED)
+{
+}
+
+ConversationCallbackData::~ConversationCallbackData()
+{
+}
+
+void ConversationCallbackData::setFilter(Tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+void ConversationCallbackData::setSortMode(Tizen::SortModePtr sortMode)
+{
+    m_sort = sortMode;
+}
+
+void ConversationCallbackData::setLimit(long limit)
+{
+    m_limit = limit;
+}
+
+void ConversationCallbackData::setOffset(long offset)
+{
+    m_offset = offset;
+}
+
+void ConversationCallbackData::addConversation(std::shared_ptr<MessageConversation> msg)
+{
+    m_conversations.push_back(msg);
+}
+
+void ConversationCallbackData::addConversations(JSContextRef context,
+        const std::vector<JSValueRef>& jsobject_conservations)
+{
+    const size_t new_conversations_count = jsobject_conservations.size();
+    if(0 == new_conversations_count) {
+        return;
+    }
+
+    m_conversations.reserve(m_conversations.size() + new_conversations_count);
+    for (auto it = jsobject_conservations.begin();
+            it != jsobject_conservations.end();
+            ++it) {
+        m_conversations.push_back(JSMessageConversation::getPrivateObject(context, *it));
+    }
+}
+
+std::vector<std::shared_ptr<MessageConversation>> ConversationCallbackData::getConversations() const
+{
+    return m_conversations;
+}
+
+void ConversationCallbackData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool ConversationCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+std::string ConversationCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string ConversationCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void ConversationCallbackData::setAccountId(int account_id){
+    m_account_id = account_id;
+}
+
+int ConversationCallbackData::getAccountId() const
+{
+    return m_account_id;
+}
+
+void ConversationCallbackData::setMessageServiceType(MessageType m_msg_type)
+{
+    m_service_type = m_msg_type;
+}
+
+MessageType ConversationCallbackData::getMessageServiceType() const
+{
+    return m_service_type;
+}
+
+Tizen::AbstractFilterPtr ConversationCallbackData::getFilter() const
+{
+    return m_filter;
+}
+
+Tizen::SortModePtr ConversationCallbackData::getSortMode() const
+{
+    return m_sort;
+}
+
+long ConversationCallbackData::getLimit() const
+{
+    return m_limit;
+}
+
+long ConversationCallbackData::getOffset() const
+{
+    return m_offset;
+}
+}//Messaging
+}//DeviceAPI
diff --git a/src/Messaging/ConversationCallbackData.h b/src/Messaging/ConversationCallbackData.h
new file mode 100644 (file)
index 0000000..4bc3a38
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONVERSATION_CALLBACK_DATA_H__
+#define __TIZEN_CONVERSATION_CALLBACK_DATA_H__
+
+#include <CallbackUserData.h>
+#include <memory>
+#include <string>
+#include <vector>
+#include <AttributeFilter.h>
+#include <SortMode.h>
+#include "MessagingUtil.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class Message;
+class MessageConversation;
+
+class ConversationCallbackData: public Common::CallbackUserData {
+public:
+    ConversationCallbackData(JSContextRef globalCtx);
+    virtual ~ConversationCallbackData();
+
+    void setFilter(Tizen::AbstractFilterPtr filter);
+    void setSortMode(Tizen::SortModePtr sortMode);
+    void setLimit(long limit);
+    void setOffset(long offset);
+    void addConversation(std::shared_ptr<MessageConversation> msg);
+    void addConversations(JSContextRef context,
+            const std::vector<JSValueRef>& jsobject_conservations);
+
+    std::vector<std::shared_ptr<MessageConversation>> getConversations() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    void setAccountId(int account_id);
+    int getAccountId() const;
+
+    void setMessageServiceType(MessageType m_msg_type);
+    MessageType getMessageServiceType() const;
+    Tizen::AbstractFilterPtr getFilter() const;
+    Tizen::SortModePtr getSortMode() const;
+    long getLimit() const;
+    long getOffset() const;
+
+private:
+    Tizen::AbstractFilterPtr m_filter;
+    Tizen::SortModePtr m_sort;
+    long m_limit;
+    long m_offset;
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+    std::vector<std::shared_ptr<MessageConversation>> m_conversations;
+    int m_account_id;
+    MessageType m_service_type;
+};
+
+}//Messaging
+}//DeviceAPI
+
+#endif // __TIZEN_CONVERSATION_CALLBACK_DATA_H__
diff --git a/src/Messaging/ConversationsChangeCallback.cpp b/src/Messaging/ConversationsChangeCallback.cpp
new file mode 100644 (file)
index 0000000..678513c
--- /dev/null
@@ -0,0 +1,198 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <GlobalContextManager.h>
+
+#include "MessagingUtil.h"
+#include "ConversationsChangeCallback.h"
+#include "JSMessageConversation.h"
+#include "MessagingUtil.h"
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+const char* CONVERSATIONSADDED = "conversationsadded";
+const char* CONVERSATIONSUPDATED = "conversationsupdated";
+const char* CONVERSATIONSREMOVED = "conversationsremoved";
+
+ConversationsChangeCallback::ConversationsChangeCallback(
+        JSContextRef global_ctx,
+        JSObjectRef on_added_obj,
+        JSObjectRef on_updated_obj,
+        JSObjectRef on_removed_obj,
+        int service_id,
+        MessageType service_type) :
+        m_callback_data(global_ctx),
+        m_id(service_id),
+        m_msg_type(service_type),
+        m_is_act(true)
+{
+    LOGD("Entered");
+
+    m_callback_data.setCallback(CONVERSATIONSADDED, on_added_obj);
+    m_callback_data.setCallback(CONVERSATIONSUPDATED, on_updated_obj);
+    m_callback_data.setCallback(CONVERSATIONSREMOVED, on_removed_obj);
+}
+
+ConversationsChangeCallback::~ConversationsChangeCallback()
+{
+    LOGD("Entered");
+}
+
+ConversationPtrVector ConversationsChangeCallback::filterConversations(
+        AbstractFilterPtr filter,
+        const ConversationPtrVector& source_conversations)
+{
+    if (filter) {
+        ConversationPtrVector filtered_conversations;
+        ConversationPtrVector::const_iterator it = source_conversations.begin();
+        ConversationPtrVector::const_iterator end_it = source_conversations.end();
+
+        for(int i = 0; it != end_it; ++i, ++it) {
+            const ConversationPtr& conversation = *it;
+            const bool matched = filter->isMatching(conversation.get());
+            if(matched) {
+                filtered_conversations.push_back(conversation);
+            }
+
+            LOGD("[%d] conversation id:%d", i, conversation->getConversationId());
+            LOGD("[%d] conversation subject :%s", i, conversation->getSubject().c_str());
+            LOGD("[%d] matched filter: %s", i, matched ? "YES" : "NO");
+        }
+
+        LOGD("returning matching %d of %d conversations", filtered_conversations.size(),
+                source_conversations.size());
+
+        return filtered_conversations;
+    }
+    else {
+        return source_conversations;
+    }
+}
+
+void ConversationsChangeCallback::added(
+        const ConversationPtrVector& conversations)
+{
+    LOGD("Entered conversations.size()=%d", conversations.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    JSContextRef ctx = m_callback_data.getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+    ConversationPtrVector filtered = filterConversations(m_filter, conversations);
+    JSObjectRef js_obj = MessagingUtil::vectorToJSObjectArray<ConversationPtr,
+            JSMessageConversation>(ctx, filtered);
+
+    LOGD("Calling:%s with:%d added conversations", CONVERSATIONSADDED,
+        filtered.size());
+
+    m_callback_data.invokeCallback(CONVERSATIONSADDED, js_obj);
+}
+
+void ConversationsChangeCallback::updated(
+        const ConversationPtrVector& conversations)
+{
+    LOGD("Entered conversations.size()=%d", conversations.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    JSContextRef ctx = m_callback_data.getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+    ConversationPtrVector filtered = filterConversations(m_filter, conversations);
+    JSObjectRef js_obj = MessagingUtil::vectorToJSObjectArray<ConversationPtr,
+            JSMessageConversation>(ctx, filtered);
+
+    LOGD("Calling:%s with:%d updated conversations", CONVERSATIONSUPDATED,
+            filtered.size());
+
+    m_callback_data.invokeCallback(CONVERSATIONSUPDATED, js_obj);
+}
+
+void ConversationsChangeCallback::removed(
+        const ConversationPtrVector& conversations)
+{
+    LOGD("Entered conversations.size()=%d", conversations.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    JSContextRef ctx = m_callback_data.getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+    ConversationPtrVector filtered = filterConversations(m_filter, conversations);
+    JSObjectRef js_obj = MessagingUtil::vectorToJSObjectArray<ConversationPtr,
+            JSMessageConversation>(ctx, filtered);
+
+    LOGD("Calling:%s with:%d removed conversations", CONVERSATIONSREMOVED,
+            filtered.size());
+
+    m_callback_data.invokeCallback(CONVERSATIONSREMOVED, js_obj);
+}
+
+void ConversationsChangeCallback::setFilter(DeviceAPI::Tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+DeviceAPI::Tizen::AbstractFilterPtr ConversationsChangeCallback::getFilter() const
+{
+    return m_filter;
+}
+
+int ConversationsChangeCallback::getServiceId() const
+{
+    return m_id;
+}
+
+MessageType ConversationsChangeCallback::getServiceType() const
+{
+    return m_msg_type;
+}
+
+void ConversationsChangeCallback::setActive(bool act) {
+    m_is_act = act;
+}
+
+bool ConversationsChangeCallback::isActive() {
+    return m_is_act;
+}
+
+void ConversationsChangeCallback::setItems(ConversationPtrVector& items)
+{
+    m_items = items;
+}
+ConversationPtrVector ConversationsChangeCallback::getItems()
+{
+    return m_items;
+}
+
+JSContextRef ConversationsChangeCallback::getContext() const
+{
+    return m_callback_data.getContext();
+}
+
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/ConversationsChangeCallback.h b/src/Messaging/ConversationsChangeCallback.h
new file mode 100644 (file)
index 0000000..612db76
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_CONVERSATIONS_CHANGE_CALLBACK_H__
+#define __TIZEN_CONVERSATIONS_CHANGE_CALLBACK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include <MultiCallbackUserData.h>
+
+#include <AbstractFilter.h>
+
+#include "MessageConversation.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+extern const char* CONVERSATIONSADDED;
+extern const char* CONVERSATIONSUPDATED;
+extern const char* CONVERSATIONSREMOVED;
+
+class ConversationsChangeCallback {
+public:
+    ConversationsChangeCallback(JSContextRef globalCtx,
+            JSObjectRef on_added_obj,
+            JSObjectRef on_updated_obj,
+            JSObjectRef on_removed_obj,
+            int service_id,
+            MessageType service_type);
+    virtual ~ConversationsChangeCallback();
+
+    void added(const ConversationPtrVector& conversations);
+    void updated(const ConversationPtrVector& conversations);
+    void removed(const ConversationPtrVector& conversations);
+
+    void setFilter(DeviceAPI::Tizen::AbstractFilterPtr filter);
+    DeviceAPI::Tizen::AbstractFilterPtr getFilter() const;
+
+    int getServiceId() const;
+    MessageType getServiceType() const;
+
+    void setActive(bool act);
+    bool isActive();
+
+    void setItems(ConversationPtrVector& items);
+    ConversationPtrVector getItems();
+    JSContextRef getContext() const;
+private:
+    static ConversationPtrVector filterConversations(
+            DeviceAPI::Tizen::AbstractFilterPtr a_filter,
+            const ConversationPtrVector& a_sourceConversations);
+
+    Common::MultiCallbackUserData m_callback_data;
+    DeviceAPI::Tizen::AbstractFilterPtr m_filter;
+    int m_id;
+    MessageType m_msg_type;
+    bool m_is_act;
+    ConversationPtrVector m_items;
+
+};
+
+} // Messaging
+} // DeviceAPI
+
+
+
+
+#endif // __TIZEN_CONVERSATIONS_CHANGE_CALLBACK_H__
diff --git a/src/Messaging/DBus/Connection.cpp b/src/Messaging/DBus/Connection.cpp
new file mode 100644 (file)
index 0000000..67c243c
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "Connection.h"
+#include <Logger.h>
+#include <PlatformException.h>
+#include <cstring>
+#include <email-types.h>
+#include "MessageService.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+Connection& Connection::getInstance()
+{
+    LOGD("Entered");
+    static Connection instance;
+    return instance;
+}
+
+GDBusConnection* Connection::getDBus()
+{
+    return m_dbus;
+}
+
+Connection::Connection()
+{
+    dbus_g_thread_init();
+    g_type_init();
+
+    m_dbus = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &m_error);
+    if (!m_dbus || m_error) {
+        LOGE("Could not get connection");
+    }
+    LOGD("Connection set");
+}
+
+Connection::~Connection()
+{
+    g_object_unref(m_dbus);
+}
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
diff --git a/src/Messaging/DBus/Connection.h b/src/Messaging/DBus/Connection.h
new file mode 100644 (file)
index 0000000..16afddc
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_DBUS_CONNECTION_H__
+#define __TIZEN_DBUS_CONNECTION_H__
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <gio/gio.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+class Connection {
+public:
+    static Connection& getInstance();
+
+    GDBusConnection* getDBus();
+
+private:
+    Connection();
+    Connection(const Connection&);
+    void operator=(const Connection&);
+    virtual ~Connection();
+
+    GDBusConnection* m_dbus;
+    GError* m_error;
+};
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
+
+#endif
diff --git a/src/Messaging/DBus/EmailSignalProxy.cpp b/src/Messaging/DBus/EmailSignalProxy.cpp
new file mode 100644 (file)
index 0000000..a3a9702
--- /dev/null
@@ -0,0 +1,85 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EmailSignalProxy.cpp
+ */
+
+#include "EmailSignalProxy.h"
+#include <Logger.h>
+#include <cstring>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+EmailSignalProxy::EmailSignalProxy(const std::string& proxy_path,
+        const std::string& proxy_iface) :
+        Proxy (proxy_path,
+                      proxy_iface,
+                      Proxy::DBUS_NAME_SIGNAL_EMAIL,   //specify email signal details
+                      DBUS_PATH_NETWORK_STATUS,
+                      DBUS_IFACE_NETWORK_STATUS)
+{
+}
+
+EmailSignalProxy::~EmailSignalProxy()
+{
+
+}
+
+void EmailSignalProxy::signalCallback(GDBusConnection* connection,
+        const gchar* sender_name,
+        const gchar* object_path,
+        const gchar* interface_name,
+        const gchar* signal_name,
+        GVariant* parameters)
+{
+    int status, mail_id, op_handle, error_code;
+    char* source = NULL;
+
+    try {
+        g_variant_get(parameters, "(iisii)",
+                &status,
+                &mail_id,
+                &source,
+                &op_handle,
+                &error_code);
+
+        //It is better to log this only when subclass is responsible of handling
+        //passed signal (usually determined by status value).
+        //
+        //LOGD("email:\n  status: %d\n  mail_id: %d\n  "
+        //        "source: %s\n  op_handle: %d\n  error_code: %d",
+        //        status, mail_id, source, op_handle, error_code);
+
+        handleEmailSignal(status, mail_id, source, op_handle, error_code);
+
+    } catch(const Common::BasePlatformException& exception) {
+        LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(),
+             (exception.getMessage()).c_str());
+    } catch(...) {
+        LOGE("Unhandled exception!");
+    }
+
+    g_free(source);
+}
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
diff --git a/src/Messaging/DBus/EmailSignalProxy.h b/src/Messaging/DBus/EmailSignalProxy.h
new file mode 100644 (file)
index 0000000..378076a
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        EmailSignalProxy.h
+ */
+
+#ifndef __TIZEN_DBUS_EMAIL_SIGNAL_PROXY_H__
+#define __TIZEN_DBUS_EMAIL_SIGNAL_PROXY_H__
+
+#include "Proxy.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+class EmailSignalProxy;
+typedef std::shared_ptr<EmailSignalProxy> EmailSignalProxyPtr;
+
+class EmailSignalProxy : public Proxy {
+public:
+    EmailSignalProxy(const std::string& proxy_path,
+            const std::string& proxy_iface);
+    virtual ~EmailSignalProxy();
+
+protected:
+    /**
+     * Override this method in subclass to handle email signal
+     */
+    virtual void handleEmailSignal(const int status,
+            const int mail_id,
+            const std::string& source,
+            const int op_handle,
+            const int error_code) = 0;
+
+    virtual void signalCallback(GDBusConnection *connection,
+            const gchar *sender_name,
+            const gchar *object_path,
+            const gchar *interface_name,
+            const gchar *signal_name,
+            GVariant *parameters);
+
+private:
+};
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
+
+#endif // __TIZEN_DBUS_EMAIL_SIGNAL_PROXY_H__
diff --git a/src/Messaging/DBus/LoadAttachmentProxy.cpp b/src/Messaging/DBus/LoadAttachmentProxy.cpp
new file mode 100644 (file)
index 0000000..55eac0b
--- /dev/null
@@ -0,0 +1,231 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        LoadAttachmentProxy.cpp
+ */
+
+#include "LoadAttachmentProxy.h"
+#include <Logger.h>
+#include <PlatformException.h>
+#include <cstring>
+#include <email-types.h>
+#include "MessageService.h"
+#include "Message.h"
+#include "MessageBody.h"
+#include "EmailManager.h"
+#include "JSMessageAttachment.h"
+#include <email-api.h>
+#include <JSWebAPIErrorFactory.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+/**
+  * This method perform very specified task (see warning comment) so it should not be
+  * visible outside LoadAttachmentProxy class.
+  */
+void updateAttachmentDataWithEmailGetAttachmentData(
+        std::shared_ptr<MessageAttachment> attachment)
+{
+    struct ScopedEmailAttachmentData {
+        ScopedEmailAttachmentData() : data(NULL) { }
+        ~ScopedEmailAttachmentData() {
+            if(data) {
+                email_free_attachment_data(&data, 1);
+            }
+        }
+        email_attachment_data_t* operator->() { return data; }
+        email_attachment_data_t* data;
+    } attachment_data_holder;
+
+    LOGD("attachmentId = %d", attachment->getId());
+
+    /*
+     * WARNING: email_get_attachment_data seems to be getting NOT COMPLETE
+     *          email_attachment_data_t object, observed that:
+     *              mail_id is 0
+     *              account_id is 0
+     *              mailbox_id is 0
+     *          Thus currently only attachment_path and attachment_mime_type is used!
+     *
+     *          To get COMPLETE data please use: Message::convertEmailToMessageAttachment
+     *          mtehod which fetches all attachments from specified email.
+     */
+    int err = email_get_attachment_data(attachment->getId(), &attachment_data_holder.data);
+    if (EMAIL_ERROR_NONE != err ||
+        NULL == attachment_data_holder.data) {
+        LOGE("Couldn't get attachment data for attachmentId:%d", attachment->getId());
+        throw Common::UnknownException("Couldn't get attachment.");
+    }
+
+    LOGD("attachment name : %s", attachment_data_holder->attachment_name);
+
+    if(attachment_data_holder->attachment_mime_type) {
+        attachment->setMimeType(attachment_data_holder->attachment_mime_type);
+    }
+
+    bool isSaved = false;
+    if (attachment_data_holder->attachment_path) {
+        LOGD("set attachment path: %s", attachment_data_holder->attachment_path);
+        attachment->setFilePath(attachment_data_holder->attachment_path);
+
+        LOGD("save_status: %d", attachment_data_holder->save_status);
+        LOGD("attachment_size : %d", attachment_data_holder->attachment_size);
+    }
+    isSaved = attachment_data_holder->save_status;
+    attachment->setIsSaved(isSaved);
+}
+
+LoadAttachmentProxy::LoadAttachmentProxy(const std::string& path,
+        const std::string& iface) :
+        EmailSignalProxy(path, iface)
+{
+}
+
+LoadAttachmentProxy::~LoadAttachmentProxy()
+{
+}
+
+void LoadAttachmentProxy::addCallback(MessageAttachmentCallbackData* callbackOwned)
+{
+    if(callbackOwned->getMessageAttachment()) {
+        LOGD("Registered callback for attachment_id: %d mail_id:%d op_handle:%d nth:%d",
+            callbackOwned->getMessageAttachment()->getId(),
+            callbackOwned->getMessageAttachment()->getMessageId(),
+            callbackOwned->getOperationHandle(),
+            callbackOwned->getNth());
+    }
+
+    m_callback_set.insert(callbackOwned);
+}
+
+void LoadAttachmentProxy::removeCallback(MessageAttachmentCallbackData* callback)
+{
+    if(callback->getMessageAttachment()) {
+        LOGD("Removed callback for attachment_id: %d mail_id:%d op_handle:%d nth:%d",
+            callback->getMessageAttachment()->getId(),
+            callback->getMessageAttachment()->getMessageId(),
+            callback->getOperationHandle(),
+            callback->getNth());
+    }
+
+    m_callback_set.erase(callback);
+}
+
+MessageAttachmentCallbackData* LoadAttachmentProxy::findCallback(const int nth,
+        const int mail_id)
+{
+    CallbackSet::iterator it = m_callback_set.begin();
+    for (; it != m_callback_set.end(); ++it) {
+        MessageAttachmentCallbackData* callback = *it;
+        if (nth == callback->getNth() &&
+            mail_id == callback->getMessageAttachment()->getMessageId()) {
+            return callback;
+        }
+    }
+
+    LOGW("Could not find callback with nth: %d and mail_id: %d", nth, mail_id);
+    return NULL;
+}
+
+void LoadAttachmentProxy::handleEmailSignal(const int status,
+            const int mail_id,
+            const std::string& source,
+            const int op_handle,
+            const int error_code)
+{
+    if(NOTI_DOWNLOAD_ATTACH_FINISH != status &&
+            NOTI_DOWNLOAD_ATTACH_FAIL != status) {
+        return;
+    }
+
+    LOGD("received email signal with:\n  status: %d\n  mail_id: %d\n  "
+            "source: %s\n  op_handle(nth): %d\n  error_code: %d",
+            status, mail_id, source.c_str(), op_handle, error_code);
+
+    MessageAttachmentCallbackData* callback = NULL;
+
+    //It seems that D-Bus signal op_handle is equal to nth in:
+    // int email_download_attachment(int mail_id, int nth, int *handle)
+    // and not handle returned from above call!!
+    const int nth = op_handle;
+
+    try {
+        // From old implementation it looks that op_handle(nth) is is equal to
+        // index (1 based) of attachment inside email thus it is not globally unique!
+        // Therfore we need to test if mail_id match.
+        // For details see old implementation MailSync.cp line 461
+
+        callback = findCallback(nth, mail_id);
+        if(!callback) {
+            //We should not log not found pair since it could be requested by
+            //different application.
+            return;
+        }
+
+        LOGD("Found callback for pair mailId:%d nth:%d", mail_id, nth);
+
+        if(NOTI_DOWNLOAD_ATTACH_FINISH == status) {
+            LOGD("Message attachment downloaded!");
+
+            std::shared_ptr<MessageAttachment> att = callback->getMessageAttachment();
+            updateAttachmentDataWithEmailGetAttachmentData(att);
+            LOGD("Updated Message attachment object");
+
+            try {
+                JSContextRef context = callback->getContext();
+                JSObjectRef jsMessageAtt = JSMessageAttachment::makeJSObject(context, att);
+                callback->callSuccessCallback(jsMessageAtt);
+            } catch (...) {
+                LOGW("Couldn't create JSMessageAttachment object!");
+                throw Common::UnknownException(
+                        "Couldn't create JSMessageAttachment object!");
+            }
+
+        } else if(NOTI_DOWNLOAD_ATTACH_FAIL) {
+            LOGD("Load message attachment failed!");
+            JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                    callback->getContext(),
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+    } catch (const Common::BasePlatformException& e) {
+        LOGE("Exception in signal callback");
+        JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                callback->getContext(), e);
+        callback->callErrorCallback(errobj);
+    } catch (...) {
+        LOGE("Exception in signal callback");
+        JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                callback->getContext(),
+                Common::JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Handling signal callback failed");
+        callback->callErrorCallback(errobj);
+    }
+
+    if(callback) {
+        removeCallback(callback);
+        delete callback;
+    }
+}
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
diff --git a/src/Messaging/DBus/LoadAttachmentProxy.h b/src/Messaging/DBus/LoadAttachmentProxy.h
new file mode 100644 (file)
index 0000000..06db27d
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        LoadAttachmentProxy.h
+ */
+
+#ifndef __TIZEN_DBUS_LOAD_ATTACHMENT_PROXY_H__
+#define __TIZEN_DBUS_LOAD_ATTACHMENT_PROXY_H__
+
+#include "EmailSignalProxy.h"
+#include <set>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageAttachmentCallbackData;
+
+namespace DBus {
+
+class LoadAttachmentProxy;
+typedef std::shared_ptr<LoadAttachmentProxy> LoadAttachmentProxyPtr;
+
+class LoadAttachmentProxy : public EmailSignalProxy {
+public:
+
+    // Callback is owned by this set
+    typedef std::set<MessageAttachmentCallbackData*> CallbackSet;
+
+    LoadAttachmentProxy(const std::string& path,
+            const std::string& iface);
+    virtual ~LoadAttachmentProxy();
+
+    //Passed callback will be owned by this proxy
+    void addCallback(MessageAttachmentCallbackData* callbackOwned);
+    void removeCallback(MessageAttachmentCallbackData* callback);
+
+protected:
+    virtual void handleEmailSignal(const int status,
+            const int mail_id,
+            const std::string& source,
+            const int op_handle,
+            const int error_code);
+
+private:
+    MessageAttachmentCallbackData* findCallback(const int nth, const int mail_id);
+
+    CallbackSet m_callback_set;
+};
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
+
+#endif // __TIZEN_DBUS_LOAD_ATTACHMENT_PROXY_H__
diff --git a/src/Messaging/DBus/LoadBodyProxy.cpp b/src/Messaging/DBus/LoadBodyProxy.cpp
new file mode 100644 (file)
index 0000000..990d04f
--- /dev/null
@@ -0,0 +1,206 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        LoadBodyProxy.cpp
+ */
+
+#include "LoadBodyProxy.h"
+#include <Logger.h>
+#include <PlatformException.h>
+#include <cstring>
+#include <email-types.h>
+#include "MessageService.h"
+#include "Message.h"
+#include "MessageBody.h"
+#include "EmailManager.h"
+#include "JSMessage.h"
+#include <JSWebAPIErrorFactory.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+LoadBodyProxy::LoadBodyProxy(const std::string& path,
+        const std::string& iface) :
+        EmailSignalProxy(path, iface)
+{
+
+}
+
+LoadBodyProxy::~LoadBodyProxy()
+{
+
+}
+
+void LoadBodyProxy::addCallback(MessageBodyCallbackData* callbackOwned)
+{
+    m_callback_set.insert(callbackOwned);
+}
+
+void LoadBodyProxy::removeCallback(MessageBodyCallbackData* callback)
+{
+    m_callback_set.erase(callback);
+}
+
+MessageBodyCallbackData* LoadBodyProxy::findCallbackByOpHandle(const int op_handle)
+{
+    CallbackSet::iterator it = m_callback_set.begin();
+    for (; it != m_callback_set.end(); ++it) {
+
+        MessageBodyCallbackData* callback = *it;
+        if (op_handle == callback->getOperationHandle()) {
+            return callback;
+        }
+    }
+
+    LOGW("Could not find callback with op_handle: %d", op_handle);
+    return NULL;
+}
+
+void LoadBodyProxy::handleEmailSignal(const int status,
+        const int mail_id,
+        const std::string& source,
+        const int op_handle,
+        const int error_code)
+{
+    switch(status) {
+        //We should handle this signal since it is DOWNLOAD_BODY_*
+        case NOTI_DOWNLOAD_BODY_START:
+        case NOTI_DOWNLOAD_BODY_FINISH:
+        case NOTI_DOWNLOAD_BODY_FAIL: {
+        } break;
+
+        // This values have not been explicitly handled in old implementation
+        //  NOTI_DOWNLOAD_BODY_CANCEL
+        //  NOTI_DOWNLOAD_MULTIPART_BODY
+        //
+        // 1. I assume that NOTI_DOWNLOAD_MULTIPART_BODY is called several times
+        // before final NOTI_DOWNLOAD_BODY_FINISH is called, thus we should not
+        // remove nor delete callback.
+        //
+        // 2. I assume that NOTI_DOWNLOAD_BODY_CANCEL is called before
+        // NOTI_DOWNLOAD_BODY_FAIL so we should do the same as in point 1.
+        case NOTI_DOWNLOAD_BODY_CANCEL:
+        case NOTI_DOWNLOAD_MULTIPART_BODY:
+        default: {
+            // This signal is not related with load message body or there is nothing
+            // to do so we can return now.
+            return;
+        } break;
+    }
+
+    LOGD("received email signal with:\n  status: %d\n  mail_id: %d\n  "
+        "source: %s\n  op_handle: %d\n  error_code: %d",
+        status, mail_id, source.c_str(), op_handle, error_code);
+
+    if(NOTI_DOWNLOAD_BODY_START == status) {
+        LOGD("Download message body started ...");
+        // There is nothing more to do so we can return now.
+        return;
+    }
+
+    MessageBodyCallbackData* callback = NULL;
+    try {
+        callback = findCallbackByOpHandle(op_handle);
+        if (!callback) {
+            LOGE("Callback is null");
+        } else {
+            if( (NOTI_DOWNLOAD_BODY_FINISH == status) ||
+                (NOTI_DOWNLOAD_BODY_FAIL == status &&
+                         EMAIL_ERROR_MAIL_IS_ALREADY_DOWNLOADED == error_code)) {
+
+                // Old implementation is not verifying whether message update failed,
+                // it just calls success callback.
+                if(callback->getMessage()) {
+                    email_mail_data_t* mail_data = EmailManager::loadMessage(
+                             callback->getMessage()->getId());
+                    if (mail_data) {
+                        callback->getMessage()->updateEmailMessage(*mail_data);
+                        EmailManager::freeMessage(mail_data);
+                        mail_data = NULL;
+                    }
+
+                    //TODO: this should be reviewed when attachments and
+                    //      loadAttachments have been completed.
+                    //TODO: see old implementation lines 608-635 in MailSync.cpp
+                    /*
+                    * This is original Messaging implementation:
+                    *
+                    * std::vector<IAttachmentPtr> attachments = mail->getAttachments();
+                    * std::vector<IAttachmentPtr> inlineAttachments = mail->getInlineAttachments();
+                    *
+                    * for (unsigned int idx = 0; idx < attachments.size() ; idx++ )
+                    * {
+                    *   LoggerD("set Attachment ID = " << attachments[idx]->getAttachmentID());
+                    *   attachments[idx]->setMessage(event->m_message);
+                    *
+                    * }
+                    * for (unsigned int idx = 0; idx < inlineAttachments.size() ; idx++ )
+                    * {
+                    *   LoggerD("set inline Attachment ID = " << inlineAttachments[idx]->getAttachmentID());
+                    *   inlineAttachments[idx]->setMessage(event->m_message);
+                    * }
+                    */
+                }
+
+                LOGD("Message body downloaded!");
+                try {
+                    JSContextRef context = callback->getContext();
+                    JSObjectRef jsMessage = JSMessage::makeJSObject(context,
+                             callback->getMessage());
+                    callback->callSuccessCallback(jsMessage);
+                } catch (...) {
+                    LOGW("Couldn't create JSMessage object!");
+                    throw Common::UnknownException(
+                            "Couldn't create JSMessage object!");
+                }
+
+            } else if(NOTI_DOWNLOAD_BODY_FAIL == status) {
+                LOGD("Load message body failed!");
+                JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                        callback->getContext(),
+                        callback->getErrorName(),
+                        callback->getErrorMessage());
+                callback->callErrorCallback(errobj);
+            }
+        }
+    }
+    catch (const Common::BasePlatformException& e) {
+        LOGE("Exception in signal callback");
+        JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                callback->getContext(), e);
+        callback->callErrorCallback(errobj);
+    }
+    catch (...) {
+        LOGE("Exception in signal callback");
+        JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                callback->getContext(),
+                Common::JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Handling signal callback failed");
+        callback->callErrorCallback(errobj);
+    }
+
+    if(callback) {
+        removeCallback(callback);
+        delete callback;
+    }
+}
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
diff --git a/src/Messaging/DBus/LoadBodyProxy.h b/src/Messaging/DBus/LoadBodyProxy.h
new file mode 100644 (file)
index 0000000..2fffa37
--- /dev/null
@@ -0,0 +1,73 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        LoadBodyProxy.h
+ */
+
+#ifndef __TIZEN_DBUS_LOAD_BODY_PROXY_H__
+#define __TIZEN_DBUS_LOAD_BODY_PROXY_H__
+
+#include "EmailSignalProxy.h"
+#include <set>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageBodyCallbackData;
+
+namespace DBus {
+
+class LoadBodyProxy;
+typedef std::shared_ptr<LoadBodyProxy> LoadBodyProxyPtr;
+
+class LoadBodyProxy : public EmailSignalProxy {
+public:
+
+    // Callback is owned by this set
+    typedef std::set<MessageBodyCallbackData*> CallbackSet;
+
+    LoadBodyProxy(const std::string& path,
+            const std::string& iface);
+    virtual ~LoadBodyProxy();
+
+    //Passed callback will be owned by this proxy
+    void addCallback(MessageBodyCallbackData* callbackOwned);
+    void removeCallback(MessageBodyCallbackData* callback);
+
+protected:
+    virtual void handleEmailSignal(const int status,
+            const int mail_id,
+            const std::string& source,
+            const int op_handle,
+            const int error_code);
+
+private:
+    /**
+     * Find callback by operation handle returned from:
+     *  int email_download_body(..., int *handle);
+     */
+    MessageBodyCallbackData* findCallbackByOpHandle(const int op_handle);
+
+    CallbackSet m_callback_set;
+};
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
+
+#endif // __TIZEN_DBUS_LOAD_BODY_PROXY_H__
diff --git a/src/Messaging/DBus/MessageProxy.cpp b/src/Messaging/DBus/MessageProxy.cpp
new file mode 100644 (file)
index 0000000..32d4782
--- /dev/null
@@ -0,0 +1,290 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MessageProxy.h"
+#include "Connection.h"
+#include <Logger.h>
+#include <Message.h>
+#include <MessageEmail.h>
+#include <MessageConversation.h>
+#include <MessageFolder.h>
+#include <ChangeListenerContainer.h>
+#include <EmailManager.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+MessageProxy::MessageProxy():
+        Proxy(Proxy::DBUS_PATH_EMAIL_STORAGE_CHANGE,
+                     Proxy::DBUS_IFACE_EMAIL_STORAGE_CHANGE,
+                     Proxy::DBUS_NAME_SIGNAL_EMAIL,
+                     Proxy::DBUS_PATH_EMAIL_STORAGE_CHANGE,
+                     Proxy::DBUS_IFACE_EMAIL_STORAGE_CHANGE)
+{
+}
+
+MessageProxy::~MessageProxy()
+{
+}
+
+void MessageProxy::signalCallback(GDBusConnection *connection,
+            const gchar *sender_name,
+            const gchar *object_path,
+            const gchar *interface_name,
+            const gchar *signal_name,
+            GVariant *parameters)
+{
+    LOGD("Enter");
+    int status, account_id, object_id, thread_id;
+    char* name;
+    g_variant_get(parameters, "(iiisi)",
+            &status,
+            &account_id,
+            &object_id,
+            &name,
+            &thread_id);
+    LOGD("status: %d", status);
+    LOGD("account_id: %d", account_id);
+    LOGD("object_id: %d", object_id);
+    LOGD("name: %s", name);
+    LOGD("thread_id: %d", thread_id);
+
+    try {
+        switch (status) {
+            case NOTI_MAIL_ADD:
+            case NOTI_MAIL_UPDATE:
+                handleEmailEvent(account_id, object_id, thread_id, status);
+                break;
+            case NOTI_MAIL_DELETE:
+                //ids of removing messages are sent with name in format:
+                //id1,id2,id3,
+                handleEmailRemoveEvent(account_id, name);
+                break;
+            case NOTI_MAIL_DELETE_FINISH:
+            case NOTI_MAIL_DELETE_FAIL:
+                //notify EmailManager, maybe it tries to delete mail
+                notifyEmailManager(name, static_cast<email_noti_on_storage_event>(status));
+                break;
+            case NOTI_THREAD_DELETE:
+                handleThreadRemoveEvent(account_id, object_id);
+                break;
+            case NOTI_MAILBOX_ADD:
+            case NOTI_MAILBOX_UPDATE:
+            case NOTI_MAILBOX_FIELD_UPDATE:
+            case NOTI_MAILBOX_RENAME:
+            case NOTI_MAILBOX_DELETE:
+                handleMailboxEvent(account_id, object_id, status);
+                break;
+            default:
+                LOGD("Unrecognized status: %d", status);
+        }
+    } catch (const Common::BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Failed to call callback");
+    }
+    g_free(name);
+}
+
+void MessageProxy::handleEmailEvent(int account_id, int mail_id, int thread_id, int event)
+{
+    LOGD("Enter");
+
+    if(NOTI_MAIL_UPDATE == event) {
+        //getting thread_id from message
+        email_mail_data_t *mail_data = NULL;
+
+        if(EMAIL_ERROR_NONE != email_get_mail_data(mail_id, &mail_data)) {
+            if (mail_data) email_free_mail_data(&mail_data, 1);
+
+            LOGE("Failed to get mail data during setting conversation id in MessageProxy.");
+            return;
+        }
+
+        thread_id = mail_data->thread_id;
+
+        if(EMAIL_ERROR_NONE != email_free_mail_data(&mail_data,1)) {
+            LOGE("Failed to free mail data memory");
+        }
+    }
+
+    email_mail_data_t* mail_data = EmailManager::getInstance().loadMessage(mail_id);
+    if (mail_data == NULL) {
+        throw Common::UnknownException("Failed to load email");
+    }
+    std::shared_ptr<Message> msg = Message::convertPlatformEmailToObject(*mail_data);
+    ConversationPtr conv = MessageConversation::convertEmailConversationToObject(
+            thread_id);
+
+    EventMessages* eventMsg = new EventMessages();
+    eventMsg->service_type = MessageType::EMAIL;
+    eventMsg->service_id = account_id;
+    eventMsg->items.push_back(msg);
+    EventConversations* eventConv = new EventConversations();
+    eventConv->service_type = MessageType::EMAIL;
+    eventConv->service_id = account_id;
+    eventConv->items.push_back(conv);
+    switch (event) {
+        case NOTI_MAIL_ADD:
+            ChangeListenerContainer::getInstance().callMessageAdded(eventMsg);
+            if (conv->getMessageCount() == 1) {
+                LOGD("This thread is new, triggering conversationAdded");
+                ChangeListenerContainer::getInstance().callConversationAdded(eventConv);
+            } else {
+                LOGD("This thread is not new, but it's updated");
+                ChangeListenerContainer::getInstance().callConversationUpdated(eventConv);
+            }
+            break;
+        case NOTI_MAIL_UPDATE:
+            ChangeListenerContainer::getInstance().callMessageUpdated(eventMsg);
+            ChangeListenerContainer::getInstance().callConversationUpdated(eventConv);
+            break;
+        default:
+            LOGW("Unknown event type: %d", event);
+            break;
+
+    }
+    delete eventMsg;
+    delete eventConv;
+
+    EmailManager::getInstance().freeMessage(mail_data);
+}
+
+std::vector<int> getMailIds(const std::string& idsString)
+{
+    std::stringstream idsStream(idsString);
+    std::string item;
+    std::vector<int> ids;
+    while (std::getline(idsStream, item, ',')) {
+        if (item.length() > 0) {
+            int id;
+            std::stringstream stream(item);
+            stream >> id;
+            if (stream) {
+                LOGD("Mail delete id: %d", id);
+                ids.push_back(id);
+            }
+        }
+    }
+    return ids;
+}
+
+void MessageProxy::handleEmailRemoveEvent(int account_id, const std::string& idsString)
+{
+    LOGD("Enter");
+    std::vector<int> ids = getMailIds(idsString);
+    if (ids.empty()) {
+        LOGD("Mail id list is empty.");
+        return;
+    }
+    EventMessages* eventMsg = new EventMessages();
+    eventMsg->service_type = MessageType::EMAIL;
+    eventMsg->service_id = account_id;
+    for (auto it = ids.begin(); it != ids.end(); ++it) {
+        //it turns out that this event is triggered after messages are removed
+        //so we just create empty messages with id and type
+        std::shared_ptr<Message> msg = std::make_shared<MessageEmail>();
+        msg->setId(*it);
+        eventMsg->items.push_back(msg);
+    }
+    ChangeListenerContainer::getInstance().callMessageRemoved(eventMsg);
+    delete eventMsg;
+    eventMsg = NULL;
+}
+
+void MessageProxy::notifyEmailManager(const std::string& idsString,
+        email_noti_on_storage_event status)
+{
+    LOGD("Enter");
+    std::vector<int> ids = getMailIds(idsString);
+    if (ids.empty()) {
+        LOGD("Mail id list is empty.");
+        return;
+    }
+    EmailManager::getInstance().removeStatusCallback(ids, status);
+}
+
+void MessageProxy::handleThreadRemoveEvent(int account_id, int thread_id)
+{
+    LOGD("Enter");
+    //event is called after thread is removed, so we just set thread id
+    ConversationPtr conv = std::make_shared<MessageConversation>();
+    conv->setConversationId(thread_id);
+
+    EventConversations* eventConv = new EventConversations();
+    eventConv->service_type = MessageType::EMAIL;
+    eventConv->service_id = account_id;
+    eventConv->items.push_back(conv);
+    ChangeListenerContainer::getInstance().callConversationRemoved(eventConv);
+    delete eventConv;
+    eventConv = NULL;
+}
+
+void MessageProxy::handleMailboxEvent(int account_id, int mailbox_id, int event)
+{
+    LOGD("Enter");
+
+    EventFolders* eventFolder = new EventFolders();
+    eventFolder->service_type = MessageType::EMAIL;
+    eventFolder->service_id = account_id;
+    FolderPtr folder;
+    if (event == NOTI_MAILBOX_DELETE) {
+        //this event is triggered after mailbox is removed
+        //so we just create folder with id
+        folder.reset(new MessageFolder(std::to_string(mailbox_id),
+                "", //parent_id
+                "", //service_id
+                "", //content_type
+                "", //name
+                "", //path
+                MessageFolderType::MESSAGE_FOLDER_TYPE_NOTSTANDARD,
+                false));
+    } else {
+        email_mailbox_t* mail_box = NULL;
+        if (EMAIL_ERROR_NONE != email_get_mailbox_by_mailbox_id(mailbox_id, &mail_box)) {
+            LOGE("Mailbox not retrieved");
+            delete eventFolder;
+            throw Common::UnknownException("Failed to load mailbox");
+        }
+        folder.reset(new MessageFolder(*mail_box));
+        if (EMAIL_ERROR_NONE != email_free_mailbox(&mail_box, 1)) {
+            LOGD("Failed to free email_free_mailbox");
+        }
+    }
+    eventFolder->items.push_back(folder);
+    switch (event) {
+        case NOTI_MAILBOX_ADD:
+            ChangeListenerContainer::getInstance().callFolderAdded(eventFolder);
+            break;
+        case NOTI_MAILBOX_UPDATE:
+        case NOTI_MAILBOX_FIELD_UPDATE:
+            ChangeListenerContainer::getInstance().callFolderUpdated(eventFolder);
+            break;
+        case NOTI_MAILBOX_DELETE:
+            ChangeListenerContainer::getInstance().callFolderRemoved(eventFolder);
+            break;
+        default:
+            LOGW("Unknown event type: %d", event);
+    }
+    delete eventFolder;
+}
+
+} //DBus
+} //Messaging
+} //DeviceAPI
diff --git a/src/Messaging/DBus/MessageProxy.h b/src/Messaging/DBus/MessageProxy.h
new file mode 100644 (file)
index 0000000..7b6d456
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGE_PROXY_H
+#define __TIZEN_MESSAGE_PROXY_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+#include <gio/gio.h>
+#include <memory>
+#include <string>
+#include <email-types.h>
+#include "Proxy.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+class MessageProxy: public Proxy {
+public:
+    MessageProxy();
+    virtual ~MessageProxy();
+protected:
+    virtual void signalCallback(GDBusConnection *connection,
+            const gchar *sender_name,
+            const gchar *object_path,
+            const gchar *interface_name,
+            const gchar *signal_name,
+            GVariant *parameters);
+    /**
+     * Handles e-mail add and update only.
+     * @param account_id
+     * @param mail_id
+     * @param thread_id
+     * @param event
+     */
+    void handleEmailEvent(int account_id, int mail_id, int thread_id, int event);
+    void handleEmailRemoveEvent(int account_id, const std::string& idsString);
+    void notifyEmailManager(const std::string& idsString, email_noti_on_storage_event status);
+    void handleThreadRemoveEvent(int account_id, int thread_id);
+    void handleMailboxEvent(int account_id, int mailbox_id, int event);
+};
+
+typedef std::shared_ptr<MessageProxy> MessageProxyPtr;
+
+} //DBus
+} //Messaging
+} //DeviceAPI
+
+#endif /* __TIZEN_MESSAGE_PROXY_H */
+
diff --git a/src/Messaging/DBus/Proxy.cpp b/src/Messaging/DBus/Proxy.cpp
new file mode 100644 (file)
index 0000000..422ab07
--- /dev/null
@@ -0,0 +1,163 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Proxy.cpp
+ */
+
+#include "Proxy.h"
+#include <Logger.h>
+#include <PlatformException.h>
+#include <cstring>
+#include <email-types.h>
+#include "MessageService.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+const char* Proxy::DBUS_PATH_NETWORK_STATUS = "/User/Email/NetworkStatus";
+const char* Proxy::DBUS_IFACE_NETWORK_STATUS = "User.Email.NetworkStatus";
+const char* Proxy::DBUS_PATH_EMAIL_STORAGE_CHANGE = "/User/Email/StorageChange";
+const char* Proxy::DBUS_IFACE_EMAIL_STORAGE_CHANGE = "User.Email.StorageChange";
+const char* Proxy::DBUS_NAME_SIGNAL_EMAIL = "email";
+
+Proxy::Proxy(const std::string& proxy_path,
+            const std::string& proxy_iface,
+            const std::string& signal_name,
+            const std::string& signal_path,
+            const std::string& signal_iface) :
+                m_conn(Connection::getInstance()),
+                m_sub_id(0),
+                m_path(proxy_path),
+                m_iface(proxy_iface),
+                m_signal_name(signal_name),
+                m_signal_path(signal_path),
+                m_signal_iface(signal_iface),
+                m_error(NULL),
+                m_dbus_signal_subscribed(false)
+{
+    LOGD("Proxy:\n"
+            "  proxy_path: %s\n  proxy_iface: %s"
+            "  signal_name: %s\n signal_path:%s\n signal_iface:%s",
+            m_path.c_str(), m_iface.c_str(),
+            m_signal_name.c_str(), m_signal_path.c_str(), m_signal_iface.c_str());
+
+    const gchar* unique_name = g_dbus_connection_get_unique_name(m_conn.getDBus());
+    LOGD("Generated unique name: %d", unique_name);
+
+    // path and interface are not obligatory to receive, but
+    // they should be set to send the signals.
+    m_proxy = g_dbus_proxy_new_sync(m_conn.getDBus(),
+            G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES,
+            NULL, unique_name, m_path.c_str(), m_iface.c_str(), NULL, &m_error);
+    if (!m_proxy || m_error) {
+        LOGE("Could not get proxy");
+        throw Common::UnknownException("Could not get proxy");
+    }
+}
+
+Proxy::~Proxy()
+{
+    signalUnsubscribe();
+}
+
+void Proxy::signalCallbackProxy(GDBusConnection *connection,
+        const gchar *sender_name,
+        const gchar *object_path,
+        const gchar *interface_name,
+        const gchar *signal_name,
+        GVariant *parameters,
+        gpointer user_data)
+{
+    Proxy* this_ptr = static_cast<Proxy*>(user_data);
+    if (!this_ptr) {
+        LOGW("Proxy is null, nothing to do");
+        return;
+    }
+
+    try {
+        //It is better to log this only when subclass is responsible of handling
+        //passed signal. If you need it put it into your signalCallback(...) method
+        //LOGD("signal: %s from: %s path: %s interface: %s",
+        //        signal_name, sender_name, object_path, interface_name);
+
+        this_ptr->signalCallback(connection, sender_name, object_path, interface_name,
+                signal_name, parameters);
+
+    } catch(const Common::BasePlatformException& exception) {
+        LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(),
+             (exception.getMessage()).c_str());
+    } catch(...) {
+        LOGE("Unhandled exception!");
+    }
+}
+
+void Proxy::signalSubscribe()
+{
+    if(m_dbus_signal_subscribed) {
+        LOGW("Proxy has already subscribed for listening DBus signal");
+        return;
+    }
+
+    const char* sender = NULL;
+    m_sub_id = g_dbus_connection_signal_subscribe(m_conn.getDBus(),
+            sender,
+            m_signal_iface.c_str(),
+            m_signal_name.c_str(),
+            m_signal_path.c_str(),
+            NULL,
+            G_DBUS_SIGNAL_FLAGS_NONE,
+            signalCallbackProxy,
+            static_cast<gpointer>(this),
+            NULL);
+    LOGD("g_dbus_connection_signal_subscribe returned id: %d", m_sub_id);
+
+    m_dbus_signal_subscribed = true;
+}
+
+void Proxy::signalUnsubscribe()
+{
+    if (!m_dbus_signal_subscribed) {
+        LOGW("Proxy hasn't subscribed for listening DBus signal");
+        return;
+    }
+
+    g_dbus_connection_signal_unsubscribe(m_conn.getDBus(), m_sub_id);
+    LOGD("g_dbus_connection_signal_unsubscribe finished");
+
+    m_dbus_signal_subscribed = false;
+}
+
+const std::string& Proxy::getSignalName() const
+{
+    return m_signal_name;
+}
+
+const std::string& Proxy::getSignalPath() const
+{
+    return m_signal_path;
+}
+
+const std::string& Proxy::getSignalInterfaceName() const
+{
+    return m_signal_iface;
+}
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
diff --git a/src/Messaging/DBus/Proxy.h b/src/Messaging/DBus/Proxy.h
new file mode 100644 (file)
index 0000000..f157f1e
--- /dev/null
@@ -0,0 +1,125 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Proxy.h
+ */
+
+#ifndef __TIZEN_DBUS_PROXY_H__
+#define __TIZEN_DBUS_PROXY_H__
+
+#include "Connection.h"
+#include <memory>
+#include <string>
+#include <mutex>
+#include <map>
+#include <CallbackUserData.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+
+class Proxy;
+typedef std::shared_ptr<Proxy> ProxyPtr;
+
+/**
+ * This is generic dbus signal listener proxy.
+ */
+class Proxy {
+public:
+    /**
+     * List of Tizen path and interface names:
+     */
+    static const char* DBUS_PATH_NETWORK_STATUS;
+    static const char* DBUS_IFACE_NETWORK_STATUS;
+    static const char* DBUS_PATH_EMAIL_STORAGE_CHANGE;
+    static const char* DBUS_IFACE_EMAIL_STORAGE_CHANGE;
+    /**
+     * Name of email signal
+     */
+    static const char* DBUS_NAME_SIGNAL_EMAIL;
+
+    /**
+     * @param proxy_path - path of this proxy
+     * @param proxy_iface - interface name of this proxy
+     *
+     * @param signal_name - expected signal name
+     * @param signal_path - expected signal path
+     * @param signal_iface - expected signal interface name
+     */
+    Proxy(const std::string& proxy_path,
+            const std::string& proxy_iface,
+            const std::string& signal_name,
+            const std::string& signal_path,
+            const std::string& signal_iface);
+
+    virtual ~Proxy();
+
+    void signalSubscribe();
+    void signalUnsubscribe();
+
+    const std::string& getSignalName() const;
+    const std::string& getSignalPath() const;
+    const std::string& getSignalInterfaceName() const;
+
+protected:
+    /**
+     * Please implement this method in subclass to handle signal.
+     * Executed by static void signalCallbackProxy(...).
+     */
+    virtual void signalCallback(GDBusConnection *connection,
+            const gchar *sender_name,
+            const gchar *object_path,
+            const gchar *interface_name,
+            const gchar *signal_name,
+            GVariant *parameters) = 0;
+
+private:
+    /**
+     * This method (registered with g_dbus_connection_signal_subscribe) is executed by
+     * DBus when signal is received. It calls
+     * (static_cast<Proxy*>(user_data))->signalCallback(...)
+     */
+    static void signalCallbackProxy(GDBusConnection *connection,
+            const gchar *sender_name,
+            const gchar *object_path,
+            const gchar *interface_name,
+            const gchar *signal_name,
+            GVariant *parameters,
+            gpointer user_data);
+
+    Connection& m_conn;
+    guint m_sub_id;
+
+    std::string m_path;
+    std::string m_iface;
+
+    std::string m_signal_name;
+    std::string m_signal_path;
+    std::string m_signal_iface;
+
+    GError* m_error;
+    GDBusProxy* m_proxy;
+    bool m_dbus_signal_subscribed;
+};
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
+
+#endif // __TIZEN_DBUS_PROXY_H__
diff --git a/src/Messaging/DBus/SendProxy.cpp b/src/Messaging/DBus/SendProxy.cpp
new file mode 100644 (file)
index 0000000..1e5a836
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SendProxy.h"
+
+#include <Logger.h>
+#include <email-types.h>
+#include <EmailManager.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+SendProxy::SendProxy():
+        EmailSignalProxy(Proxy::DBUS_PATH_NETWORK_STATUS,
+                     Proxy::DBUS_IFACE_NETWORK_STATUS)
+{
+}
+
+SendProxy::~SendProxy()
+{
+}
+
+void SendProxy::handleEmailSignal(const int status,
+            const int account_id,
+            const std::string& source,
+            const int mail_id,
+            const int error_code)
+{
+    LOGD("Enter");
+    switch (status) {
+        case NOTI_SEND_FINISH:
+        case NOTI_SEND_FAIL:
+            LOGD("Recognized status for email send");
+            LOGD("received email signal with:\n  status: %d\n  account_id: %d\n  "
+                "source: %s\n  mail_id: %d\n  error_code: %d",
+                status, account_id, source.c_str(), mail_id, error_code);
+            EmailManager::getInstance().sendStatusCallback(mail_id,
+                    static_cast<email_noti_on_network_event>(status),
+                    error_code);
+            break;
+        default:
+            LOGD("Unrecognized status %d, ignoring", status);
+    }
+}
+
+
+} //DBus
+} //Messaging
+} //DeviceAPI
\ No newline at end of file
diff --git a/src/Messaging/DBus/SendProxy.h b/src/Messaging/DBus/SendProxy.h
new file mode 100644 (file)
index 0000000..1493c8e
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SEND_PROXY_H
+#define __TIZEN_SEND_PROXY_H
+
+#include "EmailSignalProxy.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+class SendProxy: public EmailSignalProxy {
+public:
+    SendProxy();
+    virtual ~SendProxy();
+protected:
+    virtual void handleEmailSignal(const int status,
+            const int account_id,
+            const std::string& source,
+            const int op_handle,
+            const int error_code);
+
+};
+
+typedef std::shared_ptr<SendProxy> SendProxyPtr;
+
+} //DBus
+} //Messaging
+} //DeviceAPI
+
+#endif /* __TIZEN_SEND_PROXY_H */
+
diff --git a/src/Messaging/DBus/SyncProxy.cpp b/src/Messaging/DBus/SyncProxy.cpp
new file mode 100644 (file)
index 0000000..9e12d41
--- /dev/null
@@ -0,0 +1,166 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        SyncProxy.cpp
+ */
+
+#include "SyncProxy.h"
+#include <Logger.h>
+#include <PlatformException.h>
+#include <cstring>
+#include <email-types.h>
+#include "MessageService.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+SyncProxy::SyncProxy(const std::string& path,
+        const std::string& iface) :
+        EmailSignalProxy(path, iface)
+{
+
+}
+
+SyncProxy::~SyncProxy()
+{
+
+}
+
+void SyncProxy::addCallback(long op_id, Common::CallbackUserData* callbackOwned)
+{
+    m_callback_map.insert(std::make_pair(op_id, callbackOwned));
+}
+
+Common::CallbackUserData* SyncProxy::getCallback(long op_id)
+{
+    Common::CallbackUserData* cb = NULL;
+    CallbackMap::iterator it = m_callback_map.find(op_id);
+    if (it != m_callback_map.end()) {
+        cb = it->second;
+        return cb;
+    }
+    LOGE("Could not find callback");
+    throw Common::UnknownException("Could not find callback");
+    return cb;
+}
+
+void SyncProxy::removeCallback(long op_id){
+    CallbackMap::iterator it = m_callback_map.find(op_id);
+    if (it != m_callback_map.end()) {
+        Common::CallbackUserData* cb = it->second;
+        delete cb;
+        cb = NULL;
+        m_callback_map.erase(it);
+    }
+    else {
+        LOGE("Could not find callback");
+        throw Common::UnknownException("Could not find callback");
+    }
+}
+
+void SyncProxy::handleEmailSignal(const int status,
+            const int mail_id,
+            const std::string& source,
+            const int op_handle,
+            const int error_code)
+{
+    if( NOTI_DOWNLOAD_START != status &&
+            NOTI_DOWNLOAD_FINISH != status &&
+            NOTI_DOWNLOAD_FAIL != status ) {
+        // Nothing to do: this status is not related to sync nor syncFolder request
+        return;
+    }
+
+    LOGD("received email signal with:\n  status: %d\n  mail_id: %d\n  "
+            "source: %s\n  op_handle: %d\n  error_code: %d",
+            status, mail_id, source.c_str(), op_handle, error_code);
+
+    if (NOTI_DOWNLOAD_START == status) {
+        LOGD("Sync started...");
+        // There is nothing more to do so we can return now.
+        return;
+    }
+
+    Common::CallbackUserData* callback = NULL;
+    CallbackMap::iterator callback_it;
+
+    try {
+        callback_it =  findSyncCallbackByOpHandle(op_handle);
+        callback = callback_it->second;
+        if (!callback) {
+            LOGE("Callback is null");
+            throw Common::UnknownException("Callback is null");
+        }
+
+        switch (status) {
+            case NOTI_DOWNLOAD_FINISH:
+                LOGD("Sync finished!");
+                callback->callSuccessCallback();
+                break;
+
+            case NOTI_DOWNLOAD_FAIL:
+                LOGD("Sync failed!");
+                callback->callErrorCallback();
+                break;
+
+            default:
+                break;
+        }
+    }
+    catch (const Common::BasePlatformException& e) {
+        // this situation may occur when there is no callback in the
+        // map with specified opId (for example stopSync() has
+        // removed it), but sync() was already started - only
+        // warning here:
+        LOGE("Exception in signal callback");
+    }
+    catch(...)
+    {
+        LOGE("Exception in signal callback");
+    }
+
+    if(callback) {
+        delete callback;
+        m_callback_map.erase(callback_it);
+    }
+}
+
+SyncProxy::CallbackMap::iterator SyncProxy::findSyncCallbackByOpHandle(
+        const int op_handle)
+{
+    CallbackMap::iterator it = m_callback_map.begin();
+    for (; it != m_callback_map.end(); ++it) {
+        SyncCallbackData* cb = dynamic_cast<SyncCallbackData*>(it->second);
+        if (!cb) continue;
+
+        if (op_handle == cb->getOperationHandle()) {
+            return it;
+        }
+    }
+    // this situation may occur when there is no callback in the
+    // map with specified opId (for example stopSync() has
+    // removed it), but sync() was already started - only
+    // warning here:
+    LOGW("Could not find callback with op_handle: %d", op_handle);
+    throw Common::UnknownException("Could not find callback");
+}
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
diff --git a/src/Messaging/DBus/SyncProxy.h b/src/Messaging/DBus/SyncProxy.h
new file mode 100644 (file)
index 0000000..4953ff3
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        SyncProxy.h
+ */
+
+#ifndef __TIZEN_DBUS_SYNC_PROXY_H__
+#define __TIZEN_DBUS_SYNC_PROXY_H__
+
+#include "EmailSignalProxy.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+namespace DBus {
+
+class SyncProxy;
+typedef std::shared_ptr<SyncProxy> SyncProxyPtr;
+
+class SyncProxy : public EmailSignalProxy {
+public:
+
+    // Callback is owned by this map
+    typedef std::map<long, Common::CallbackUserData*> CallbackMap;
+
+    SyncProxy(const std::string& path,
+            const std::string& iface);
+    virtual ~SyncProxy();
+
+    //Passed callback will be owned by this proxy
+    void addCallback(long op_id, Common::CallbackUserData* callbackOwned);
+    Common::CallbackUserData* getCallback(long op_id);
+    void removeCallback(long op_id);
+
+protected:
+    virtual void handleEmailSignal(const int status,
+            const int mail_id,
+            const std::string& source,
+            const int op_handle,
+            const int error_code);
+
+private:
+    /**
+     * Find callback by operation handle returned from:
+     *  int email_sync_header(..., int *handle);
+     */
+    CallbackMap::iterator findSyncCallbackByOpHandle(const int op_handle);
+
+    CallbackMap m_callback_map;
+};
+
+} //namespace DBus
+} //namespace Messaging
+} //namespace DeviceAPI
+
+#endif // __TIZEN_DBUS_SYNC_PROXY_H__
diff --git a/src/Messaging/EmailManager.cpp b/src/Messaging/EmailManager.cpp
new file mode 100644 (file)
index 0000000..7e4b218
--- /dev/null
@@ -0,0 +1,1456 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file: EmailManager.cpp
+ */
+
+#include <JSWebAPIErrorFactory.h>
+#include <JSWebAPIError.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <memory>
+#include <PlatformException.h>
+#include <sstream>
+#include <GlobalContextManager.h>
+
+#include <AbstractFilter.h>
+
+#include <email-api-network.h>
+#include <email-api-account.h>
+#include <email-api-mail.h>
+#include <email-api-mailbox.h>
+
+#include "EmailManager.h"
+#include "MessagingUtil.h"
+#include "MessageService.h"
+#include "Message.h"
+#include "MessageConversation.h"
+#include "MessageCallbackUserData.h"
+#include "MessagesCallbackUserData.h"
+#include "FindMsgCallbackUserData.h"
+#include "ConversationCallbackData.h"
+#include "MessageEmail.h"
+#include "MessagingDatabaseManager.h"
+
+#include "JSMessage.h"
+#include "JSMessageConversation.h"
+#include "JSMessageFolder.h"
+
+#include <email-api.h>
+#include <vconf.h>
+
+#include "DBus/SyncProxy.h"
+#include "DBus/LoadBodyProxy.h"
+#include "DBus/LoadAttachmentProxy.h"
+
+#include <sstream>
+#include <FilterIterator.h>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+const int ACCOUNT_ID_NOT_INITIALIZED = -1;
+const std::string FIND_FOLDERS_ATTRIBUTE_ACCOUNTID_NAME  = "serviceId";
+} //anonymous namespace
+
+EmailManager& EmailManager::getInstance()
+{
+    LOGD("Entered");
+
+    static EmailManager instance;
+    return instance;
+}
+
+EmailManager::EmailManager()
+{
+    LOGD("Entered");
+    getUniqueOpId();
+
+    int err = email_service_begin();
+    if(EMAIL_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        MessagingUtil::throwEmailException<UnknownException>(
+                err, "email_service_begin()");
+    }
+
+    err = email_open_db();
+    if(EMAIL_ERROR_NONE != err){
+        LOGE("ret: %d", err);
+        MessagingUtil::throwEmailException<UnknownException>(
+                err, "email_open_db()");
+    }
+
+    int slot_size = -1;
+    vconf_get_int("db/private/email-service/slot_size", &(slot_size));
+    if (slot_size > 0) {
+        m_slot_size = slot_size;
+    }
+
+    m_proxy_sync = std::make_shared<DBus::SyncProxy>(
+                                      DBus::Proxy::DBUS_PATH_NETWORK_STATUS,
+                                      DBus::Proxy::DBUS_IFACE_NETWORK_STATUS);
+    if (!m_proxy_sync) {
+        LOGE("Sync proxy is null");
+        throw Common::UnknownException("Sync proxy is null");
+    }
+    m_proxy_sync->signalSubscribe();
+
+    m_proxy_load_body = std::make_shared<DBus::LoadBodyProxy>(
+                                        DBus::Proxy::DBUS_PATH_NETWORK_STATUS,
+                                        DBus::Proxy::DBUS_IFACE_NETWORK_STATUS);
+    if (!m_proxy_load_body) {
+        LOGE("Load body proxy is null");
+        throw Common::UnknownException("Load body proxy is null");
+    }
+    m_proxy_load_body->signalSubscribe();
+
+    m_proxy_load_attachment = std::make_shared<DBus::LoadAttachmentProxy>(
+                                        DBus::Proxy::DBUS_PATH_NETWORK_STATUS,
+                                        DBus::Proxy::DBUS_IFACE_NETWORK_STATUS);
+    if (!m_proxy_load_attachment) {
+        LOGE("Load attachment proxy is null");
+        throw Common::UnknownException("Load attachment proxy is null");
+    }
+    m_proxy_load_attachment->signalSubscribe();
+
+    m_proxy_messageStorage = std::make_shared<DBus::MessageProxy>();
+    if (!m_proxy_messageStorage) {
+        LOGE("Message proxy is null");
+        throw Common::UnknownException("Message proxy is null");
+    }
+    m_proxy_messageStorage->signalSubscribe();
+
+    m_proxy_send = std::make_shared<DBus::SendProxy>();
+    if (!m_proxy_send) {
+        LOGE("Send proxy is null");
+        throw Common::UnknownException("Send proxy is null");
+    }
+    m_proxy_send->signalSubscribe();
+}
+
+EmailManager::~EmailManager()
+{
+    LOGD("Entered");
+}
+
+void EmailManager::addDraftMessagePlatform(int account_id,
+    std::shared_ptr<Message> message)
+{
+    addMessagePlatform(account_id, message, EMAIL_MAILBOX_TYPE_DRAFT);
+}
+
+void EmailManager::addOutboxMessagePlatform(int account_id,
+    std::shared_ptr<Message> message)
+{
+    addMessagePlatform(account_id, message, EMAIL_MAILBOX_TYPE_OUTBOX);
+}
+
+void EmailManager::addMessagePlatform(int account_id,
+    std::shared_ptr<Message> message, email_mailbox_type_e mailbox_type)
+{
+    email_mail_data_t* mail_data = NULL;
+    email_mail_data_t* mail_data_final = NULL;
+    int err = EMAIL_ERROR_NONE;
+
+    mail_data = Message::convertPlatformEmail(message);
+
+    mail_data->account_id = account_id;
+
+    //Adding "from" email address
+    email_account_t* account = NULL;
+    err = email_get_account(account_id, EMAIL_ACC_GET_OPT_FULL_DATA, &account);
+    if(EMAIL_ERROR_NONE != err) {
+        int ret = email_free_mail_data(&mail_data,1);
+        if(EMAIL_ERROR_NONE != ret) {
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mail_data()").c_str());
+        }
+        LOGE("ret: %d", err);
+        MessagingUtil::throwEmailException<UnknownException>(err, "email_get_account()");
+    }
+    LOGD("FROM %s", account->user_email_address);
+    std::stringstream ss;
+    ss << "<" << account->user_email_address << ">";
+    std::string address_from;
+    ss >> address_from;
+    mail_data->full_address_from = strdup(address_from.c_str());
+    LOGD("FROM %s", mail_data->full_address_from);
+    err = email_free_account(&account,1);
+    if(EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_account()").c_str());
+    }
+    //Setting mailbox id
+    email_mailbox_t *mailbox_data = NULL;
+    err = email_get_mailbox_by_mailbox_type(account_id, mailbox_type,
+            &mailbox_data);
+    if(EMAIL_ERROR_NONE != err) {
+        int ret = email_free_mail_data(&mail_data,1);
+        if(EMAIL_ERROR_NONE != ret) {
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mail_data()").c_str());
+        }
+        LOGE("ret: %d", err);
+        MessagingUtil::throwEmailException<UnknownException>(
+                err, "email_get_mailbox_by_mailbox_type");
+    }
+    else {
+        LOGD("email_get_mailbox_by_mailbox_type success.\n");
+        mail_data->mailbox_id = mailbox_data->mailbox_id;
+        mail_data->mailbox_type = mailbox_data->mailbox_type;
+    }
+
+    mail_data->report_status = EMAIL_MAIL_REPORT_NONE;
+    mail_data->save_status = EMAIL_MAIL_STATUS_SAVED;
+    mail_data->flags_draft_field = 1;
+
+    //adding email without attachments
+    err = email_add_mail(mail_data, NULL, 0, NULL, 0);
+    if(EMAIL_ERROR_NONE != err) {
+        int ret = email_free_mail_data(&mail_data,1);
+        if(EMAIL_ERROR_NONE != ret) {
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mail_data()").c_str());
+        }
+        ret = email_free_mailbox(&mailbox_data, 1);
+        if (EMAIL_ERROR_NONE != ret) {
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mailbox()").c_str());
+        }
+        LOGE("ret: %d", err);
+        MessagingUtil::throwEmailException<UnknownException>(err, "email_add_mail()");
+    }
+    else {
+        LOGD("email_add_mail success.\n");
+    }
+
+    LOGD("saved mail without attachments id = [%d]\n", mail_data->mail_id);
+
+    message->setId(mail_data->mail_id);
+    message->setMessageStatus(MessageStatus::STATUS_DRAFT);
+
+    //Adding attachments
+    if (message->getHasAttachment()){
+        Message::addEmailAttachments(message);
+    }
+
+    err = email_get_mail_data(message->getId(), &mail_data_final);
+    if(EMAIL_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        MessagingUtil::throwEmailException<UnknownException>(err, "email_get_mail_data()");
+    }
+
+    message->updateEmailMessage(*mail_data_final);
+
+    err = email_free_mail_data(&mail_data_final,1);
+    if(EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mail_data()").c_str());
+    }
+
+    err = email_free_mail_data(&mail_data,1);
+    if(EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mail_data()").c_str());
+    }
+
+    err = email_free_mailbox(&mailbox_data, 1);
+    if (EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mailbox()").c_str());
+    }
+}
+
+static gboolean addDraftMessageCompleteCB(void *data)
+{
+    MessageCallbackUserData* callback =
+        static_cast<MessageCallbackUserData *>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+            callback->getMessage()->setMessageStatus(MessageStatus::STATUS_FAILED);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context, err);
+        callback->callErrorCallback(errobj);
+    } catch (...) {
+        LOGE("Message add draft failed");
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Message add draft failed");
+        callback->callErrorCallback(errobj);
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void EmailManager::addDraftMessage(MessageCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::shared_ptr<Message> message = callback->getMessage();
+        addDraftMessagePlatform(callback->getAccountId(), message);
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Message add draft failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Message add draft failed");
+    }
+
+    //Complete task
+    if (!g_idle_add(addDraftMessageCompleteCB, static_cast<void *>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+
+//**** sending email ****
+static gboolean sendEmailCompleteCB(void* data)
+{
+    LOGD("Entered");
+
+    MessageRecipientsCallbackData* callback =
+            static_cast<MessageRecipientsCallbackData*>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+            callback->getMessage()->setMessageStatus(MessageStatus::STATUS_FAILED);
+        }
+        else {
+            std::shared_ptr<Message> message = callback->getMessage();
+            callback->callSuccessCallback(
+                    JSUtil::toJSValueRef(context, message->getTO()));
+            callback->getMessage()->setMessageStatus(MessageStatus::STATUS_SENT);
+        }
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error when calling send message callback");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void EmailManager::sendMessage(MessageRecipientsCallbackData* callback)
+{
+    LOGD("Entered");
+    int err = EMAIL_ERROR_NONE;
+    email_mail_data_t *mail_data = NULL;
+
+    try{
+        if(!callback){
+            LOGE("Callback is null");
+            throw UnknownException("Callback is null");
+        }
+
+        std::shared_ptr<Message> message = callback->getMessage();
+        if(!message) {
+            LOGE("Message is null");
+            throw UnknownException("Message is null");
+        }
+
+        if(!(message->is_id_set())) {
+            addOutboxMessagePlatform(callback->getAccountId(),message);
+        }
+
+        err = email_get_mail_data(message->getId(),&mail_data);
+        if(EMAIL_ERROR_NONE != err) {
+            LOGE("ret: %d", err);
+            MessagingUtil::throwEmailException<UnknownException>(err, "email_get_mail_data()");
+        }
+
+        LOGD("email_get_mail_data success.\n");
+
+        //Sending EMAIL
+        mail_data->save_status = EMAIL_MAIL_STATUS_SENDING;
+
+        int req_id = 0;
+        err = email_send_mail(mail_data->mail_id, &req_id);
+        if (EMAIL_ERROR_NONE != err) {
+            LOGE("ret: %d", err);
+            MessagingUtil::throwEmailException<UnknownException>(err, "email_send_mail()");
+        }
+        LOGD("req_id: %d", req_id);
+        callback->getMessage()->setMessageStatus(MessageStatus::STATUS_SENDING);
+        m_sendRequests[req_id] = callback;
+
+    } catch (const BasePlatformException& ex) {
+         LOGE("%s (%s)", (ex.getName()).c_str(), (ex.getMessage()).c_str());
+         callback->setError(ex.getName(), ex.getMessage());
+         if (!g_idle_add(sendEmailCompleteCB, static_cast<void*>(callback))) {
+             LOGE("g_idle addition failed");
+             delete callback;
+             callback = NULL;
+         }
+    }catch (...) {
+        LOGE("Message send failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Message send failed");
+        if (!g_idle_add(sendEmailCompleteCB, static_cast<void*>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    }
+
+    err = email_free_mail_data(&mail_data,1);
+    if(EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mail_data()").c_str());
+    }
+
+    return;
+}
+
+void EmailManager::sendStatusCallback(int mail_id,
+        email_noti_on_network_event status,
+        int error_code)
+{
+    LOGD("Enter");
+
+    std::lock_guard<std::mutex> lock(m_mutex);
+    //find first request for this mail_id
+    SendReqMapIterator it = getSendRequest(mail_id);
+    if (it != m_sendRequests.end()) {
+        LOGD("Found request");
+        MessageRecipientsCallbackData* callback = it->second;
+        m_sendRequests.erase(it);
+
+        if (NOTI_SEND_FAIL == status) {
+            LOGD("Failed to send message, set proper error");
+            switch (error_code) {
+                case EMAIL_ERROR_NO_SIM_INSERTED:
+                case EMAIL_ERROR_SOCKET_FAILURE:
+                case EMAIL_ERROR_CONNECTION_FAILURE:
+                case EMAIL_ERROR_CONNECTION_BROKEN:
+                case EMAIL_ERROR_NO_SUCH_HOST:
+                case EMAIL_ERROR_NETWORK_NOT_AVAILABLE:
+                case EMAIL_ERROR_INVALID_STREAM:
+                case EMAIL_ERROR_NO_RESPONSE:
+                    LOGE("Network error %d", error_code);
+                    callback->setError(JSWebAPIErrorFactory::NETWORK_ERROR,
+                            "Failed to send message");
+                    break;
+                default:
+                    LOGE("Unknown error %d", error_code);
+                    callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                            "Failed to send message");
+            }
+        } else if (NOTI_SEND_FINISH == status) {
+            LOGD("Message sent successfully");
+        }
+
+        if (!g_idle_add(sendEmailCompleteCB, static_cast<void*>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    } else {
+        LOGW("No matching request found");
+    }
+}
+
+email_mail_data_t* EmailManager::loadMessage(int msg_id)
+{
+    email_mail_data_t* mail_data = NULL;
+    int err = EMAIL_ERROR_NONE;
+    err = email_get_mail_data(msg_id, &mail_data);
+    if (EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_get_mail_data()").c_str());
+    } else {
+        LOGD("email_get_mail_data success.");
+    }
+    return mail_data;
+}
+
+EmailManager::SendReqMapIterator EmailManager::getSendRequest(int mail_id)
+{
+    for (auto it = m_sendRequests.begin(); it != m_sendRequests.end(); it++) {
+        if (it->second->getMessage()->getId() == mail_id) {
+            return it;
+        }
+    }
+    return m_sendRequests.end();
+}
+
+void EmailManager::freeMessage(email_mail_data_t* mail_data)
+{
+    if(!mail_data) {
+        return;
+    }
+
+    int err = email_free_mail_data(&mail_data,1);
+    if(EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mail_data()").c_str());
+    }
+}
+
+void EmailManager::loadMessageBody(MessageBodyCallbackData* callback)
+{
+    LOGD("Entered");
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    if(!callback->getMessage()) {
+        LOGE("Callback's message is null");
+        return;
+    }
+
+    m_proxy_load_body->addCallback(callback);
+
+    const int mailId = callback->getMessage()->getId();
+    int err = EMAIL_ERROR_NONE;
+
+    int op_handle = -1;
+    err = email_download_body(mailId, 0, &op_handle);
+    if(EMAIL_ERROR_NONE != err){
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_download_body()").c_str());
+        m_proxy_load_body->removeCallback(callback);
+        return;
+    }
+    callback->setOperationHandle(op_handle);
+}
+
+void EmailManager::loadMessageAttachment(MessageAttachmentCallbackData* callback)
+{
+    LOGD("Entered");
+    if(!callback) {
+        LOGE("Callback is null");
+        throw Common::InvalidValuesException("Callback is null");
+    }
+    if(!callback->getMessageAttachment()) {
+        LOGE("Callback's message attachment is null");
+        throw Common::InvalidValuesException("Callback's message attachment is null");
+    }
+
+    std::shared_ptr<MessageAttachment> msgAttachment = callback->getMessageAttachment();
+    LOGD("attachmentId:%d mailId:%d", msgAttachment->getId(),
+            msgAttachment->getMessageId());
+
+    struct ScopedEmailMailData {
+        ScopedEmailMailData() : data(NULL) { }
+        ~ScopedEmailMailData() { EmailManager::freeMessage(data); }
+        email_mail_data_t* data;
+    } mail_data_holder;
+
+    mail_data_holder.data = EmailManager::loadMessage(msgAttachment->getMessageId());
+    if(!mail_data_holder.data) {
+        std::stringstream err_ss;
+        err_ss << "Couldn't get email_mail_data_t for messageId:"
+                << msgAttachment->getMessageId();
+        LOGE("%s",err_ss.str().c_str());
+        throw Common::UnknownException(err_ss.str().c_str());
+    }
+
+    AttachmentPtrVector attachments = Message::convertEmailToMessageAttachment(
+            *mail_data_holder.data);
+    LOGD("Mail:%d contain:%d attachments", msgAttachment->getMessageId(),
+        attachments.size());
+
+    AttachmentPtrVector::iterator it = attachments.begin();
+    int attachmentIndex = -1;
+    for(int i = 0; it != attachments.end(); ++i, ++it) {
+        if((*it)->getId() == msgAttachment->getId()) {
+            attachmentIndex = i;
+            break;
+        }
+    }
+
+    if(attachmentIndex < 0) {
+        std::stringstream err_ss;
+        err_ss << "Attachment with id:" << msgAttachment->getId() << "not found";
+        LOGE("%s",err_ss.str().c_str());
+        throw Common::UnknownException(err_ss.str().c_str());
+    }
+
+    LOGD("Attachment with id:%d is located at index:%d", msgAttachment->getId(),
+            attachmentIndex);
+
+    int op_handle = -1;
+    const int nth = attachmentIndex + 1; //in documentation: the minimum number is "1"
+    callback->setNth(nth);
+
+    int err = email_download_attachment(msgAttachment->getMessageId(), nth, &op_handle);
+    if (EMAIL_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        MessagingUtil::throwEmailException<UnknownException>(err, "email_download_attachment()");
+    } else  {
+        LOGD("email_download_attachment returned handle:%d",op_handle);
+        callback->setOperationHandle(op_handle);
+        m_proxy_load_attachment->addCallback(callback);
+    }
+}
+//#################################### sync: ###################################
+
+void EmailManager::sync(void* data)
+{
+    LOGD("Entered");
+    SyncCallbackData* callback = static_cast<SyncCallbackData*>(data);
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+    long op_id = callback->getOpId();
+    m_proxy_sync->addCallback(op_id, callback);
+
+    int err = EMAIL_ERROR_NONE;
+    int limit = callback->getLimit();
+    int slot_size = -1;
+    int account_id = callback->getAccountId();
+
+    if (limit < 0) {
+        slot_size = m_slot_size;
+    }
+    else {
+        slot_size = limit;
+    }
+
+    err = email_set_mail_slot_size(0, 0, slot_size);
+    if(EMAIL_ERROR_NONE != err){
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_set_mail_slot_size()").c_str());
+        m_proxy_sync->removeCallback(op_id);
+        return;
+    }
+
+    int op_handle = -1;
+    err = email_sync_header(account_id, 0, &op_handle);
+    if(EMAIL_ERROR_NONE != err){
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_sync_header()").c_str());
+        m_proxy_sync->removeCallback(op_id);
+    }
+    callback->setOperationHandle(op_handle);
+}
+
+//#################################### ^sync ###################################
+
+//################################## syncFolder: ###############################
+
+void EmailManager::syncFolder(SyncFolderCallbackData* callback)
+{
+    LOGD("Entered");
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    const long op_id = callback->getOpId();
+    m_proxy_sync->addCallback(op_id, callback);
+
+    if(!callback->getMessageFolder())
+    {
+        LOGE("Callback's messageFolder is null");
+        m_proxy_sync->removeCallback(op_id);
+        return;
+    }
+
+    int err = EMAIL_ERROR_NONE;
+
+    email_mailbox_t* mailbox = NULL;
+
+    const std::string folder_id_str = callback->getMessageFolder()->getId();
+    int folder_id = 0;
+    std::istringstream(folder_id_str) >> folder_id;
+
+    err = email_get_mailbox_by_mailbox_id(folder_id, &mailbox);
+
+    if(NULL == mailbox) {
+        LOGW("email_get_mailbox_by_mailbox_id() returned NULL mailbox");
+        if (EMAIL_ERROR_NONE == err) {
+            return;
+        }
+    }
+
+    if (EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(
+                    err, "email_get_mailbox_by_mailbox_id()").c_str());
+        m_proxy_sync->removeCallback(op_id);
+
+        if (mailbox) {
+            err = email_free_mailbox(&mailbox , 1);
+            if (EMAIL_ERROR_NONE !=  err) {
+                LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mailbox()").c_str());
+            }
+            mailbox = NULL;
+        }
+        return;
+    }
+
+    try {
+        const int limit = callback->getLimit();
+        int slot_size = -1;
+
+        if (limit < 0) {
+            slot_size = m_slot_size;
+        }
+        else {
+            slot_size = limit;
+        }
+
+        err = email_set_mail_slot_size(0, 0, slot_size);
+        if(EMAIL_ERROR_NONE != err){
+            LOGE("ret: %d", err);
+            MessagingUtil::throwEmailException<UnknownException>(
+                    err, "email_set_mail_slot_size()");
+        }
+
+        int op_handle = -1;
+        const int account_id = callback->getAccountId();
+        err = email_sync_header(account_id, mailbox->mailbox_id, &op_handle);
+        if(EMAIL_ERROR_NONE != err) {
+            m_proxy_sync->removeCallback(op_id);
+            LOGE("ret: %d", err);
+            MessagingUtil::throwEmailException<UnknownException>(
+                    err, "email_sync_header()");
+        }
+        callback->setOperationHandle(op_handle);
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("Exception in syncFolder");
+    }
+
+    if (NULL != mailbox)
+    {
+        err = email_free_mailbox(&mailbox , 1);
+        if  (EMAIL_ERROR_NONE !=  err) {
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mailbox()").c_str());
+        }
+        mailbox = NULL;
+    }
+}
+
+//#################################### ^syncFolder #############################
+
+//################################## stopSync: #################################
+
+void EmailManager::stopSync(long op_id)
+{
+    LOGD("Entered");
+    SyncCallbackData* callback = NULL;
+    try {
+        callback = dynamic_cast<SyncCallbackData*>(
+                m_proxy_sync->getCallback(op_id));
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("Could not get callback");
+    }
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    int err = EMAIL_ERROR_NONE;
+    err = email_cancel_job(callback->getAccountId(), callback->getOperationHandle(),
+            EMAIL_CANCELED_BY_USER);
+    if(EMAIL_ERROR_NONE != err){
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_cancel_job()").c_str());
+    }
+    JSObjectRef err_obj =
+            JSWebAPIErrorFactory::makeErrorObject(callback->getContext(),
+                    JSWebAPIErrorFactory::ABORT_ERROR,
+                    "Sync aborted by user");
+    callback->callErrorCallback(err_obj);
+    m_proxy_sync->removeCallback(op_id);
+}
+
+//################################## ^stopSync #################################
+
+void removeEmailCompleteCB(MessagesCallbackUserData* callback)
+{
+    LOGD("Entered");
+    if (!callback) {
+        LOGE("Callback is null");
+        return;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling removeEmail callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error when calling removeEmail callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+EmailManager::DeleteReqVector::iterator EmailManager::getDeleteRequest(
+        const std::vector<int> &ids)
+{
+    for (auto idIt = ids.begin(); idIt != ids.end(); ++idIt) {
+        for (auto reqIt = m_deleteRequests.begin(); reqIt != m_deleteRequests.end(); ++reqIt) {
+            MessagePtrVector msgs = reqIt->callback->getMessages();
+            for (auto msgIt = msgs.begin(); msgIt != msgs.end(); ++msgIt) {
+                if ((*msgIt)->getId() == *idIt) {
+                    return reqIt;
+                }
+            }
+        }
+    }
+    return m_deleteRequests.end();
+}
+
+void EmailManager::removeStatusCallback(const std::vector<int> &ids,
+            email_noti_on_storage_event status)
+{
+    LOGD("Enter");
+    std::lock_guard<std::mutex> lock(m_mutex);
+    DeleteReqVector::iterator it = getDeleteRequest(ids);
+    if (it != m_deleteRequests.end()) {
+        LOGD("Found request");
+        if (NOTI_MAIL_DELETE_FINISH == status) {
+            LOGD("Successfully removed %d mails", ids.size());
+            it->messagesDeleted += ids.size();
+        }
+        MessagesCallbackUserData* callback = it->callback;
+        if (NOTI_MAIL_DELETE_FAIL == status) {
+            LOGD("Failed to remove mail");
+            callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Messages remove failed");
+        }
+        //if one of mails failed, call error callback
+        //if all mails are deleted, call success.
+        // >= is used in case of duplicated dbus messages
+        if (NOTI_MAIL_DELETE_FAIL == status ||
+                static_cast<unsigned int>(it->messagesDeleted) >= it->callback->getMessages().size()) {
+            LOGD("Calling callback");
+            m_deleteRequests.erase(it);
+            m_mutex.unlock();
+            removeEmailCompleteCB(callback);
+        } else {
+            LOGD("Not all messages are removed, waiting for next callback");
+        }
+    } else {
+        LOGD("Request not found, ignoring");
+    }
+}
+
+void EmailManager::removeMessages(MessagesCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    int error;
+    email_mail_data_t *mail = NULL;
+
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<std::shared_ptr<Message>> messages = callback->getMessages();
+        MessageType type = callback->getMessageServiceType();
+        for(auto it = messages.begin() ; it != messages.end(); ++it) {
+            if((*it)->getType() != type) {
+                LOGE("Invalid message type");
+                throw TypeMismatchException("Error while deleting email");
+            }
+        }
+        for (auto it = messages.begin() ; it != messages.end(); ++it) {
+            error = email_get_mail_data((*it)->getId(), &mail);
+            if (EMAIL_ERROR_NONE != error) {
+                LOGE("ret: %d", error);
+                MessagingUtil::throwEmailException<UnknownException>(
+                        error, "email_get_mail_data()");
+            }
+
+            //This task (_EMAIL_API_DELETE_MAIL) is for async
+            error = email_delete_mail(mail->mailbox_id, &mail->mail_id, 1, 0);
+            if (EMAIL_ERROR_NONE != error) {
+                int ret = email_free_mail_data(&mail, 1);
+                if (EMAIL_ERROR_NONE != ret) {
+                    LOGW("%s", MessagingUtil::getEmailErrorMessage(
+                                ret, "email_free_mail_data()").c_str());
+                }
+                LOGE("ret: %d", error);
+                MessagingUtil::throwEmailException<UnknownException>(error, "email_delete_mail()");
+            }
+            error = email_free_mail_data(&mail, 1);
+            if (EMAIL_ERROR_NONE != error) {
+                LOGW("%s", MessagingUtil::getEmailErrorMessage(
+                            error, "email_free_mail_data()").c_str());
+            }
+        }
+        //store delete request and wait for dbus response
+        DeleteReq request;
+        request.callback = callback;
+        request.messagesDeleted = 0;
+        m_deleteRequests.push_back(request);
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+        removeEmailCompleteCB(callback);
+    } catch (...) {
+        LOGE("Messages remove failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Messages remove failed");
+        removeEmailCompleteCB(callback);
+    }
+}
+
+void EmailManager::updateMessages(MessagesCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    int error;
+    email_mail_data_t *mail = NULL;
+
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<std::shared_ptr<Message>> messages = callback->getMessages();
+        MessageType type = callback->getMessageServiceType();
+        for (auto it = messages.begin() ; it != messages.end(); ++it) {
+            if ((*it)->getType() != type) {
+                LOGE("Invalid message type");
+                throw TypeMismatchException("Error while updating message");
+            }
+        }
+        for (auto it = messages.begin() ; it != messages.end(); ++it) {
+
+            mail = Message::convertPlatformEmail((*it));
+
+            if((*it)->getHasAttachment())
+            {
+                LOGD("Message has attachments. Workaround need to be used.");
+                //Update of mail on server using function email_update_mail() is not possible.
+                //Attachment is updated only locally (can't be later loaded from server),
+                //so use of workaround is needed:
+                //1. add new mail
+                //2. delete old mail
+
+                //adding message again after changes
+                addDraftMessagePlatform(mail->account_id, (*it));
+                LOGD("mail added - new id = [%d]\n", (*it)->getId());
+
+                //deleting old mail
+                LOGD("mail deleted = [%d]\n", mail->mail_id);
+                error = email_delete_mail(mail->mailbox_id,&mail->mail_id,1,1);
+                if (EMAIL_ERROR_NONE != error) {
+                    int ret = email_free_mail_data(&mail, 1);
+                    if (EMAIL_ERROR_NONE != ret) {
+                        LOGW("%s", MessagingUtil::getEmailErrorMessage(
+                                    ret, "email_free_mail_data()").c_str());
+                    }
+                    LOGE("ret: %d", error);
+                    MessagingUtil::throwEmailException<UnknownException>(
+                            error, "email_delete_mail()");
+                }
+            } else {
+                LOGD("There are no attachments, updating only email data.");
+                error = email_update_mail(mail, NULL, 0, NULL, 0);
+                if (EMAIL_ERROR_NONE != error) {
+                    int ret = email_free_mail_data(&mail, 1);
+                    if (EMAIL_ERROR_NONE != ret) {
+                        LOGW("%s", MessagingUtil::getEmailErrorMessage(
+                                    ret, "email_free_mail_data()").c_str());
+                    }
+                    LOGE("ret %d", error);
+                    MessagingUtil::throwEmailException<UnknownException>(
+                            error, "email_update_mail()");
+                }
+            }
+
+            int ret = email_free_mail_data(&mail, 1);
+            if (EMAIL_ERROR_NONE != ret) {
+                LOGW("%s", MessagingUtil::getEmailErrorMessage(
+                        ret, "email_free_mail_data()").c_str());
+            }
+        }
+
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Messages update failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Messages update failed");
+    }
+
+    //Complete task
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling updateEmail callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error when calling updateEmail callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+
+void EmailManager::findMessages(FindMsgCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    email_mail_data_t* mailList = NULL;
+    int mailListCount = 0;
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::pair<int, email_mail_data_t*> emails =
+                MessagingDatabaseManager::getInstance().findEmails(callback);
+        mailListCount = emails.first;
+        LOGD("Found %d mails", mailListCount);
+
+        mailList = emails.second;
+        email_mail_data_t* nth_email = mailList;
+
+        for (int i = 0; i < mailListCount; ++i) {
+            std::shared_ptr<Message> email =
+                    Message::convertPlatformEmailToObject(*nth_email);
+            callback->addMessage(email);
+            nth_email++;
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Message find failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Message find failed");
+    }
+
+    if (mailListCount > 0 && mailList != NULL) {
+        int err = email_free_mail_data(&mailList, mailListCount);
+        if (EMAIL_ERROR_NONE != err) {
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mail_data()").c_str());
+        }
+    }
+
+    //Complete task
+    LOGD("callback: %p error:%d messages.size()=%d", callback, callback->isError(),
+            callback->getMessages().size());
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback(JSMessage::messageVectorToJSObjectArray(context,
+                    callback->getMessages()));
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling findMessages callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Failed to call findMessages callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+void EmailManager::findConversations(ConversationCallbackData* callback)
+{
+    LOGE("Entered");
+
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    int convListCount = 0;
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<EmailConversationInfo> conversationsInfo =
+                MessagingDatabaseManager::getInstance().findEmailConversations(callback);
+        convListCount = conversationsInfo.size();
+        LOGD("Found %d conversations", convListCount);
+
+        for (int i = 0; i < convListCount; ++i) {
+            std::shared_ptr<MessageConversation> conversation =
+                    MessageConversation::convertEmailConversationToObject(conversationsInfo.at(i).id);
+            conversation->setUnreadMessages(conversationsInfo.at(i).unreadMessages);
+            callback->addConversation(conversation);
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Conversation find failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Conversation find failed");
+    }
+
+    //Complete task
+    LOGD("callback: %p error:%d conversations.size()=%d", callback, callback->isError(),
+            callback->getConversations().size());
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback(
+                    MessagingUtil::vectorToJSObjectArray<ConversationPtr,
+                    JSMessageConversation>(context,
+                            callback->getConversations()));
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling findConversations callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Failed to call findConversations callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+long EmailManager::getUniqueOpId()
+{
+    // mutex is created only on first call (first call added to constructor
+    // to initialize mutex correctly)
+    static std::mutex op_id_mutex;
+    std::lock_guard<std::mutex> lock(op_id_mutex);
+    static long op_id = 0;
+    return op_id++;
+}
+
+void EmailManager::findFolders(FoldersCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    int ret = EMAIL_ERROR_UNKNOWN;
+    int account_id = ACCOUNT_ID_NOT_INITIALIZED;
+    email_mailbox_t* mailboxes = NULL;
+    email_mailbox_t* nth_mailbox = NULL;
+    int mailboxes_count;
+
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+
+        Tizen::AbstractFilterPtr filter = callback->getFilter();
+        if (!filter) {
+            LOGE("Filter not provided");
+            throw UnknownException("Filter not provided");
+        }
+
+        for(FilterIterator it(filter); false == it.isEnd(); it++) {
+
+            if(FIS_COMPOSITE_START == it.getState()) {
+                CompositeFilterPtr cf = castToCompositeFilter((*it));
+                if(cf && INTERSECTION != cf->getType()) {
+                    LOGE("[ERROR] >>> invalid Filter type: %d", cf->getType());
+                    throw TypeMismatchException("Invalid Filter Type");
+                }
+            }
+            else if(FIS_ATTRIBUTE_FILTER == it.getState()) {
+                AttributeFilterPtr attrf = castToAttributeFilter((*it));
+                if(attrf) {
+                    const std::string attr_name = attrf->getAttributeName();
+                    if (FIND_FOLDERS_ATTRIBUTE_ACCOUNTID_NAME == attr_name) {
+                        account_id = static_cast<int>(attrf->getMatchValue()->toLong());
+                    } else {
+                        LOGE("The attribute name: %s is invalid", attr_name.c_str());
+                        throw InvalidValuesException("The attribute name is invalid");
+                    }
+                }
+            }
+        }
+
+        LOGD("Listing folders for account ID: %d", account_id);
+        if (account_id > 0) {
+            ret = email_get_mailbox_list(account_id,
+                    -1,
+                    &mailboxes,
+                    &mailboxes_count);
+            if (EMAIL_ERROR_NONE != ret || !mailboxes) {
+                LOGE("ret: %d", ret);
+                MessagingUtil::throwEmailException<UnknownException>(
+                        ret, "email_get_mailbox_list()");
+            }
+
+            if (mailboxes_count <= 0) {
+                LOGD("Empty mailboxes");
+            }
+            else {
+                LOGD("Founded mailboxes: %d", mailboxes_count);
+
+                nth_mailbox = mailboxes;
+                for (int i = 0; i < mailboxes_count; ++i) {
+                    std::shared_ptr<MessageFolder> fd;
+                    fd = std::make_shared<MessageFolder>(*nth_mailbox);
+                    callback->addFolder(fd);
+                    nth_mailbox++;
+                }
+            }
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Messages update failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Messages update failed");
+    }
+
+    if (mailboxes != NULL) {
+        ret = email_free_mailbox(&mailboxes, mailboxes_count);
+        if (EMAIL_ERROR_NONE != ret) {
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mailbox()").c_str());
+        }
+    }
+
+    //Complete task
+    LOGD("callback: %p error:%d folders.size()=%d", callback, callback->isError(),
+            callback->getFolders().size());
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            JSObjectRef js_obj = MessagingUtil::vectorToJSObjectArray<FolderPtr,
+                    JSMessageFolder>(context, callback->getFolders());
+            callback->callSuccessCallback(js_obj);
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling findFolders callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error when calling findFolders callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+void EmailManager::removeConversations(ConversationCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    int error;
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<std::shared_ptr<MessageConversation>> conversations =
+                callback->getConversations();
+        MessageType type = callback->getMessageServiceType();
+
+        int thread_id = 0;
+        for(auto it = conversations.begin() ; it != conversations.end(); ++it) {
+            if((*it)->getType() != type) {
+                LOGE("Invalid message type");
+                throw TypeMismatchException("Error while deleting email conversation");
+            }
+        }
+
+        for (auto it = conversations.begin() ; it != conversations.end(); ++it) {
+            thread_id = (*it)->getConversationId();
+            error = email_delete_thread(thread_id, false);
+            if (EMAIL_ERROR_NONE != error) {
+                LOGE("ret: %d", error);
+                MessagingUtil::throwEmailException<UnknownException>(
+                        error, "email_delete_thread()");
+            }
+
+            // for now, there is no way to recognize deleting email thread job is completed.
+            // so use polling to wait the thread is removed.
+            email_mail_data_t *thread_info = NULL;
+            do {
+                usleep(300 * 1000);
+                LOGD("Waiting to delete this email thread...");
+                error = email_get_thread_information_by_thread_id(
+                    thread_id, &thread_info);
+                LOGD("email_get_thread_information_by_thread_id(): %d", error);
+
+                if (thread_info != NULL) {
+                    free(thread_info);
+                    thread_info = NULL;
+                }
+            } while (error != EMAIL_ERROR_MAIL_NOT_FOUND);
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Messages remove failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Messages remove failed");
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling removeConversations callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error when calling removeConversations callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/EmailManager.h b/src/Messaging/EmailManager.h
new file mode 100644 (file)
index 0000000..9513ce6
--- /dev/null
@@ -0,0 +1,134 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file: EmailManager.h
+ */
+
+#ifndef __TIZEN_EMAIL_MANAGER_H__
+#define __TIZEN_EMAIL_MANAGER_H__
+
+#include <glib.h>
+#include <mutex>
+#include <string>
+#include <map>
+#include <vector>
+
+#include "email-api-network.h"
+#include "email-api-account.h"
+#include "email-api-mail.h"
+#include "email-api-mailbox.h"
+
+#include <CallbackUserData.h>
+#include <PlatformException.h>
+
+#include "MessagingUtil.h"
+#include "MessageService.h"
+
+#include "DBus/Connection.h"
+#include "DBus/SyncProxy.h"
+#include "DBus/LoadBodyProxy.h"
+#include "DBus/LoadAttachmentProxy.h"
+#include "DBus/MessageProxy.h"
+#include "DBus/SendProxy.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class Message;
+class MessageCallbackUserData;
+class FindMsgCallbackUserData;
+class SyncFolderCallbackData;
+
+class EmailManager {
+public:
+    static EmailManager& getInstance();
+
+    void addDraftMessage(MessageCallbackUserData* callback);
+    void removeMessages(MessagesCallbackUserData* callback);
+    void updateMessages(MessagesCallbackUserData* callback);
+    void findMessages(FindMsgCallbackUserData* callback);
+    void findConversations(ConversationCallbackData* callback);
+    void findFolders(FoldersCallbackData* callback);
+    void removeConversations(ConversationCallbackData* callback);
+
+    void sendMessage(MessageRecipientsCallbackData* callback);
+    void sendStatusCallback(int mail_id, email_noti_on_network_event status,
+            int error_code);
+    void removeStatusCallback(const std::vector<int> &ids,
+            email_noti_on_storage_event status);
+
+    void loadMessageBody(MessageBodyCallbackData* callback);
+    void loadMessageAttachment(MessageAttachmentCallbackData* callback);
+
+    void sync(void* data);
+    void syncFolder(SyncFolderCallbackData* callback);
+    void stopSync(long op_id);
+
+    void registerStatusCallback(msg_handle_t msg_handle);
+
+    /**
+     * Use freeMessage() to release returned email_mail_data_t object.
+     */
+    static email_mail_data_t* loadMessage(int msg_id);
+    static void freeMessage(email_mail_data_t*);
+
+    long getUniqueOpId();
+
+private:
+    EmailManager();
+    EmailManager(const EmailManager &);
+    void operator=(const EmailManager &);
+    virtual ~EmailManager();
+    void addDraftMessagePlatform(int account_id,
+        std::shared_ptr<Message> message);
+    void addOutboxMessagePlatform(int account_id,
+        std::shared_ptr<Message> message);
+    void addMessagePlatform(int account_id, std::shared_ptr<Message> message,
+        email_mailbox_type_e mailbox_type);
+
+    typedef std::map<int, MessageRecipientsCallbackData*> SendReqMap;
+    typedef SendReqMap::iterator SendReqMapIterator;
+    SendReqMapIterator getSendRequest(int mail_id);
+    SendReqMap m_sendRequests;
+    struct DeleteReq {
+        MessagesCallbackUserData* callback;
+        int messagesDeleted;
+    };
+    typedef std::vector<DeleteReq> DeleteReqVector;
+    /**
+     * Find first request containing at least one message id
+     * @param ids
+     * @return
+     */
+    DeleteReqVector::iterator getDeleteRequest(const std::vector<int> &ids);
+    DeleteReqVector m_deleteRequests;
+
+    int m_slot_size;
+
+    DBus::SyncProxyPtr m_proxy_sync;
+    DBus::LoadBodyProxyPtr m_proxy_load_body;
+    DBus::LoadAttachmentProxyPtr m_proxy_load_attachment;
+    DBus::MessageProxyPtr m_proxy_messageStorage;
+    DBus::SendProxyPtr m_proxy_send;
+
+    std::mutex m_mutex;
+};
+
+} // Messaging
+} // DeviceAPI
+#endif // __TIZEN_EMAIL_MANAGER_H__
diff --git a/src/Messaging/FindMsgCallbackUserData.cpp b/src/Messaging/FindMsgCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..ab296ff
--- /dev/null
@@ -0,0 +1,136 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file: FindMsgCallbackUserData.cpp
+ */
+
+#include "FindMsgCallbackUserData.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+FindMsgCallbackUserData::FindMsgCallbackUserData(JSContextRef globalCtx):
+        CallbackUserData(globalCtx),
+        m_limit(0),
+        m_offset(0),
+        m_is_error(false),
+        m_account_id(0),
+        m_service_type(UNDEFINED)
+{
+}
+
+FindMsgCallbackUserData::~FindMsgCallbackUserData()
+{
+}
+
+void FindMsgCallbackUserData::setFilter(Tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+void FindMsgCallbackUserData::setSortMode(Tizen::SortModePtr sortMode)
+{
+    m_sort = sortMode;
+}
+
+void FindMsgCallbackUserData::setLimit(long limit)
+{
+    m_limit = limit;
+}
+
+void FindMsgCallbackUserData::setOffset(long offset)
+{
+    m_offset = offset;
+}
+
+void FindMsgCallbackUserData::addMessage(std::shared_ptr<Message> msg)
+{
+    m_messages.push_back(msg);
+}
+
+std::vector<std::shared_ptr<Message>> FindMsgCallbackUserData::getMessages() const
+{
+    return m_messages;
+}
+
+void FindMsgCallbackUserData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool FindMsgCallbackUserData::isError() const
+{
+    return m_is_error;
+}
+
+std::string FindMsgCallbackUserData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string FindMsgCallbackUserData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void FindMsgCallbackUserData::setAccountId(int account_id){
+    m_account_id = account_id;
+}
+
+int FindMsgCallbackUserData::getAccountId() const
+{
+    return m_account_id;
+}
+
+void FindMsgCallbackUserData::setMessageServiceType(MessageType m_msg_type)
+{
+    m_service_type = m_msg_type;
+}
+
+MessageType FindMsgCallbackUserData::getMessageServiceType() const
+{
+    return m_service_type;
+}
+
+Tizen::AbstractFilterPtr FindMsgCallbackUserData::getFilter() const
+{
+    return m_filter;
+}
+
+Tizen::SortModePtr FindMsgCallbackUserData::getSortMode() const
+{
+    return m_sort;
+}
+
+long FindMsgCallbackUserData::getLimit() const
+{
+    return m_limit;
+}
+
+long FindMsgCallbackUserData::getOffset() const
+{
+    return m_offset;
+}
+}//Messaging
+}//DeviceAPI
diff --git a/src/Messaging/FindMsgCallbackUserData.h b/src/Messaging/FindMsgCallbackUserData.h
new file mode 100644 (file)
index 0000000..d434b74
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file: FindMsgCallbackUserData.h
+ */
+
+#ifndef __TIZEN_FIND_MSG_CALLBACK_USER_DATA_H
+#define __TIZEN_FIND_MSG_CALLBACK_USER_DATA_H
+
+#include <CallbackUserData.h>
+#include <memory>
+#include <string>
+#include <vector>
+#include <AttributeFilter.h>
+#include <SortMode.h>
+#include "MessagingUtil.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class Message;
+
+class FindMsgCallbackUserData: public Common::CallbackUserData {
+public:
+    FindMsgCallbackUserData(JSContextRef globalCtx);
+    virtual ~FindMsgCallbackUserData();
+
+    void setFilter(Tizen::AbstractFilterPtr filter);
+    void setSortMode(Tizen::SortModePtr sortMode);
+    void setLimit(long limit);
+    void setOffset(long offset);
+    void addMessage(std::shared_ptr<Message> msg);
+    std::vector<std::shared_ptr<Message>> getMessages() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    void setAccountId(int account_id);
+    int getAccountId() const;
+
+    void setMessageServiceType(MessageType m_msg_type);
+    MessageType getMessageServiceType() const;
+    Tizen::AbstractFilterPtr getFilter() const;
+    Tizen::SortModePtr getSortMode() const;
+    long getLimit() const;
+    long getOffset() const;
+private:
+    //@TODO replace dpl shared_ptr when JSAttributeFilter is changed
+    Tizen::AbstractFilterPtr m_filter;
+    Tizen::SortModePtr m_sort;
+    long m_limit;
+    long m_offset;
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+    std::vector<std::shared_ptr<Message>> m_messages;
+    int m_account_id;
+    MessageType m_service_type;
+};
+
+}//Messaging
+}//DeviceAPI
+
+#endif /* __TIZEN_FIND_MSG_CALLBACK_USER_DATA_H */
diff --git a/src/Messaging/FoldersCallbackData.cpp b/src/Messaging/FoldersCallbackData.cpp
new file mode 100644 (file)
index 0000000..4f067ff
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "FoldersCallbackData.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+
+FoldersCallbackData::FoldersCallbackData(JSContextRef globalCtx):
+        CallbackUserData(globalCtx),
+        m_is_error(false)
+{
+}
+
+FoldersCallbackData::~FoldersCallbackData() {
+}
+
+void FoldersCallbackData::addFolder(std::shared_ptr<MessageFolder> folder)
+{
+    m_folders.push_back(folder);
+}
+
+const std::vector<std::shared_ptr<MessageFolder>>& FoldersCallbackData::getFolders() const
+{
+    return m_folders;
+}
+
+void FoldersCallbackData::setFilter(DeviceAPI::Tizen::AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+DeviceAPI::Tizen::AbstractFilterPtr FoldersCallbackData::getFilter() const
+{
+    return m_filter;
+}
+
+void FoldersCallbackData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool FoldersCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+std::string FoldersCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string FoldersCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+}//Messaging
+}//DeviceAPI
diff --git a/src/Messaging/FoldersCallbackData.h b/src/Messaging/FoldersCallbackData.h
new file mode 100644 (file)
index 0000000..bf444cf
--- /dev/null
@@ -0,0 +1,62 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_FOLDERS_CALLBACK_DATA_H__
+#define __TIZEN_FOLDERS_CALLBACK_DATA_H__
+
+#include <CallbackUserData.h>
+#include <memory>
+#include <vector>
+#include <string>
+
+#include <AbstractFilter.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageFolder;
+
+class FoldersCallbackData: public Common::CallbackUserData {
+public:
+    FoldersCallbackData(JSContextRef globalCtx);
+    virtual ~FoldersCallbackData();
+
+    void addFolder(std::shared_ptr<MessageFolder> folder);
+    const std::vector<std::shared_ptr<MessageFolder>>& getFolders() const;
+
+    void setFilter(DeviceAPI::Tizen::AbstractFilterPtr filter);
+    DeviceAPI::Tizen::AbstractFilterPtr getFilter() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+private:
+    std::vector<std::shared_ptr<MessageFolder>> m_folders;
+    DeviceAPI::Tizen::AbstractFilterPtr m_filter;
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+
+};
+
+}//Messaging
+}//DeviceAPI
+
+#endif /* __TIZEN_FOLDERS_CALLBACK_DATA_H__ */
diff --git a/src/Messaging/FoldersChangeCallback.cpp b/src/Messaging/FoldersChangeCallback.cpp
new file mode 100644 (file)
index 0000000..269b6b2
--- /dev/null
@@ -0,0 +1,191 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <GlobalContextManager.h>
+
+#include "FoldersChangeCallback.h"
+#include "JSMessageFolder.h"
+#include "MessagingUtil.h"
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+const char* FOLDERSADDED = "foldersadded";
+const char* FOLDERSUPDATED = "foldersupdated";
+const char* FOLDERSREMOVED = "foldersremoved";
+
+FoldersChangeCallback::FoldersChangeCallback(JSContextRef global_ctx,
+        JSObjectRef on_added_obj,
+        JSObjectRef on_updated_obj,
+        JSObjectRef on_removed_obj,
+        int service_id,
+        MessageType service_type):
+    m_callback_data(global_ctx),
+    m_id(service_id),
+    m_msg_type(service_type),
+    m_is_act(true)
+{
+    LOGD("Entered");
+
+    m_callback_data.setCallback(FOLDERSADDED, on_added_obj);
+    m_callback_data.setCallback(FOLDERSUPDATED, on_updated_obj);
+    m_callback_data.setCallback(FOLDERSREMOVED, on_removed_obj);
+}
+
+FoldersChangeCallback::~FoldersChangeCallback()
+{
+    LOGD("Entered");
+}
+
+FolderPtrVector FoldersChangeCallback::filterFolders(
+        AbstractFilterPtr filter,
+        const FolderPtrVector& source_folders)
+{
+    if (filter) {
+        FolderPtrVector filtered_folders;
+        FolderPtrVector::const_iterator it = source_folders.begin();
+        FolderPtrVector::const_iterator end_it = source_folders.end();
+
+        for(int i = 0; it != end_it; ++i, ++it) {
+            const FolderPtr& folder = *it;
+            const bool matched = filter->isMatching(folder.get());
+            if (matched) {
+                filtered_folders.push_back(folder);
+            }
+
+            LOGD("[%d] folder id:%s", i, folder->getId().c_str());
+            LOGD("[%d] folder name:%s", i, folder->getName().c_str());
+            LOGD("[%d] matched filter: %s", i, matched ? "YES" : "NO");
+        }
+
+        return filtered_folders;
+    }
+    else {
+        return source_folders;
+    }
+}
+
+void FoldersChangeCallback::added(const FolderPtrVector& folders)
+{
+    LOGD("Entered folders.size()=%d", folders.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    JSContextRef ctx = m_callback_data.getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+    FolderPtrVector filtered = filterFolders(m_filter, folders);
+    JSObjectRef js_obj = MessagingUtil::vectorToJSObjectArray<FolderPtr,JSMessageFolder>(
+            ctx, filtered);
+
+    LOGD("Calling:%s with:%d added folders", FOLDERSADDED,
+            filtered.size());
+
+    m_callback_data.invokeCallback(FOLDERSADDED, js_obj);
+}
+
+void FoldersChangeCallback::updated(const FolderPtrVector& folders)
+{
+    LOGD("Entered folders.size()=%d", folders.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    JSContextRef ctx = m_callback_data.getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+    FolderPtrVector filtered = filterFolders(m_filter, folders);
+    JSObjectRef js_obj = MessagingUtil::vectorToJSObjectArray<FolderPtr,JSMessageFolder>(
+            ctx, filtered);
+
+    LOGD("Calling:%s with:%d updated folders", FOLDERSUPDATED,
+            filtered.size());
+
+    m_callback_data.invokeCallback(FOLDERSUPDATED, js_obj);
+}
+
+void FoldersChangeCallback::removed(const FolderPtrVector& folders)
+{
+    LOGD("Entered folders.size()=%d", folders.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    JSContextRef ctx = m_callback_data.getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+    FolderPtrVector filtered = filterFolders(m_filter, folders);
+    JSObjectRef js_obj = MessagingUtil::vectorToJSObjectArray<FolderPtr,JSMessageFolder>(
+            ctx, filtered);
+
+    LOGD("Calling:%s with:%d removed folders", FOLDERSREMOVED,
+            filtered.size());
+
+    m_callback_data.invokeCallback(FOLDERSREMOVED, js_obj);
+}
+
+void FoldersChangeCallback::setFilter(AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+AbstractFilterPtr FoldersChangeCallback::getFilter() const
+{
+    return m_filter;
+}
+
+int FoldersChangeCallback::getServiceId() const
+{
+    return m_id;
+}
+
+MessageType FoldersChangeCallback::getServiceType() const
+{
+    return m_msg_type;
+}
+
+void FoldersChangeCallback::setActive(bool act) {
+    m_is_act = act;
+}
+
+bool FoldersChangeCallback::isActive() {
+    return m_is_act;
+}
+
+void FoldersChangeCallback::setItems(FolderPtrVector& items)
+{
+    m_items = items;
+}
+FolderPtrVector FoldersChangeCallback::getItems()
+{
+    return m_items;
+}
+
+JSContextRef FoldersChangeCallback::getContext() const
+{
+    return m_callback_data.getContext();
+}
+
+} // Messaging
+} // DeviceAPI
+
+
diff --git a/src/Messaging/FoldersChangeCallback.h b/src/Messaging/FoldersChangeCallback.h
new file mode 100644 (file)
index 0000000..fc2a888
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_FOLDERS_CHANGE_CALLBACK_H__
+#define __TIZEN_FOLDERS_CHANGE_CALLBACK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include <MultiCallbackUserData.h>
+
+#include <AbstractFilter.h>
+
+#include "MessageFolder.h"
+#include "MessagingUtil.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+extern const char* FOLDERSADDED;
+extern const char* FOLDERSUPDATED;
+extern const char* FOLDERSREMOVED;
+
+class FoldersChangeCallback {
+public:
+    FoldersChangeCallback(JSContextRef global_ctx,
+            JSObjectRef on_added_obj,
+            JSObjectRef on_updated_obj,
+            JSObjectRef on_removed_obj,
+            int service_id,
+            MessageType service_type);
+    virtual ~FoldersChangeCallback();
+
+    void added(const FolderPtrVector& folders);
+    void updated(const FolderPtrVector& folders);
+    void removed(const FolderPtrVector& folders);
+
+    void setFilter(Tizen::AbstractFilterPtr filter);
+    Tizen::AbstractFilterPtr getFilter() const;
+
+    int getServiceId() const;
+    MessageType getServiceType() const;
+
+    void setActive(bool act);
+    bool isActive();
+
+    void setItems(FolderPtrVector& items);
+    FolderPtrVector getItems();
+    JSContextRef getContext() const;
+private:
+    static FolderPtrVector filterFolders(Tizen::AbstractFilterPtr filter,
+            const FolderPtrVector& source_folders);
+
+    Common::MultiCallbackUserData m_callback_data;
+    Tizen::AbstractFilterPtr m_filter;
+    int m_id;
+    MessageType m_msg_type;
+    bool m_is_act;
+    FolderPtrVector m_items;
+};
+
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_FOLDERS_CHANGE_CALLBACK_H__
diff --git a/src/Messaging/JSMessage.cpp b/src/Messaging/JSMessage.cpp
new file mode 100644 (file)
index 0000000..3325dcb
--- /dev/null
@@ -0,0 +1,923 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+
+#include <GlobalContextManager.h>
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <Logger.h>
+
+#include "JSMessage.h"
+#include "JSMessageBody.h"
+#include "JSMessageAttachment.h"
+
+#include "plugin_config.h"
+
+#include "MessagingUtil.h"
+#include "Message.h"
+#include "MessageSMS.h"
+#include "MessageMMS.h"
+#include "MessageEmail.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+const char* MESSAGE = "Message";
+
+const char* MESSAGE_DICTIONARY_ATTRIBUTE_PLAIN_BODY = "plainBody";
+const char* MESSAGE_DICTIONARY_ATTRIBUTE_HTML_BODY = "htmlBody";
+}
+
+namespace JSMessageKeys {
+const char* MESSAGE_ATTRIBUTE_ID = "id";
+const char* MESSAGE_ATTRIBUTE_CONVERSATION_ID = "conversationId";
+const char* MESSAGE_ATTRIBUTE_FOLDER_ID = "folderId";
+const char* MESSAGE_ATTRIBUTE_TYPE = "type";
+const char* MESSAGE_ATTRIBUTE_TIMESTAMP = "timestamp";
+const char* MESSAGE_ATTRIBUTE_FROM = "from";
+const char* MESSAGE_ATTRIBUTE_TO = "to"; // used also in dictionary
+const char* MESSAGE_ATTRIBUTE_CC = "cc"; // used also in dictionary
+const char* MESSAGE_ATTRIBUTE_BCC = "bcc"; // used also in dictionary
+const char* MESSAGE_ATTRIBUTE_BODY = "body";
+const char* MESSAGE_ATTRIBUTE_IS_READ = "isRead";
+const char* MESSAGE_ATTRIBUTE_IS_HIGH_PRIORITY = "isHighPriority"; // used also in dictionary
+const char* MESSAGE_ATTRIBUTE_SUBJECT = "subject"; // used also in dictionary
+const char* MESSAGE_ATTRIBUTE_IN_RESPONSE_TO = "inResponseTo";
+const char* MESSAGE_ATTRIBUTE_MESSAGE_STATUS = "messageStatus";
+const char* MESSAGE_ATTRIBUTE_ATTACHMENTS = "attachments";
+const char* MESSAGE_ATTRIBUTE_HAS_ATTACHMENT = "hasAttachment";
+} // namespace JSMessage
+
+using namespace JSMessageKeys;
+
+JSClassRef JSMessage::m_jsClassRef = NULL;
+
+JSClassDefinition JSMessage::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    MESSAGE,
+    NULL,
+    JSMessage::m_property,
+    NULL, // m_function
+    JSMessage::initialize,
+    JSMessage::finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //callAsConstructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSMessage::m_property[] = {
+    { MESSAGE_ATTRIBUTE_ID, getMessageId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_ATTRIBUTE_CONVERSATION_ID, getConversationId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_ATTRIBUTE_FOLDER_ID, getFolder, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_ATTRIBUTE_TYPE, getMessageType, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_ATTRIBUTE_TIMESTAMP, getTime, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_ATTRIBUTE_FROM, getSourceAddress, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_ATTRIBUTE_TO, getDestinationAddress, setDestinationAddress, kJSPropertyAttributeDontDelete },
+    { MESSAGE_ATTRIBUTE_CC, getCcAddress, setCcAddress, kJSPropertyAttributeDontDelete },
+    { MESSAGE_ATTRIBUTE_BCC, getBccAddress, setBccAddress, kJSPropertyAttributeDontDelete },
+    { MESSAGE_ATTRIBUTE_BODY, getMessageBody, setMessageBody, kJSPropertyAttributeDontDelete },
+    { MESSAGE_ATTRIBUTE_IS_READ, getIsRead, setIsRead, kJSPropertyAttributeDontDelete },
+    { MESSAGE_ATTRIBUTE_IS_HIGH_PRIORITY, getMessagePriority, setMessagePriority, kJSPropertyAttributeDontDelete },
+    { MESSAGE_ATTRIBUTE_SUBJECT, getSubject, setSubject, kJSPropertyAttributeDontDelete },
+    { MESSAGE_ATTRIBUTE_IN_RESPONSE_TO, getInResponseTo, NULL, kJSPropertyAttributeDontDelete },
+    { MESSAGE_ATTRIBUTE_MESSAGE_STATUS, getMessageStatus, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { MESSAGE_ATTRIBUTE_ATTACHMENTS, getAttachments, setAttachments, kJSPropertyAttributeDontDelete },
+    { MESSAGE_ATTRIBUTE_HAS_ATTACHMENT, hasAttachment, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSMessage::getClassInfo()
+{
+    LOGD("Entered");
+    return &(m_classInfo);
+}
+
+JSClassRef DLL_EXPORT JSMessage::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+JSObjectRef DLL_EXPORT JSMessage::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, JSMessage::getClassRef(), NULL);
+
+    // constructor
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        std::shared_ptr<Message> priv;
+
+        std::string msgTypeString = validator.toString(0);
+        LOGD(" Message type : %s", msgTypeString.c_str());
+        JSObjectRef dictionary = validator.toObject(1, true);
+
+        try {
+            MessageType msgtype = MessagingUtil::stringToMessageType(msgTypeString);
+            switch(msgtype) {
+                case MessageType(SMS):
+                    priv = std::make_shared<MessageSMS>();
+                    break;
+                case MessageType(MMS):
+                    priv = std::make_shared<MessageMMS>();
+                    break;
+                case MessageType(EMAIL):
+                    priv = std::make_shared<MessageEmail>();
+                    break;
+                default:
+                    break;
+            }
+        }
+        catch(const BasePlatformException &ex) {
+            LOGE("Invalid message type given: %s.", msgTypeString.c_str());
+            throw ex;
+        }
+
+        setPrivateObject(jsObjRef, priv);
+
+        // both - dictionary and private object - have to be not NULL
+        if (dictionary != NULL && priv.get() != NULL) {
+            JSValueRef subjectData = JSUtil::getProperty(context, dictionary,
+                    MESSAGE_ATTRIBUTE_SUBJECT);
+            JSValueRef toData = JSUtil::getProperty(context, dictionary,
+                    MESSAGE_ATTRIBUTE_TO);
+            JSValueRef ccData = JSUtil::getProperty(context, dictionary,
+                    MESSAGE_ATTRIBUTE_CC);
+            JSValueRef bccData = JSUtil::getProperty(context, dictionary,
+                    MESSAGE_ATTRIBUTE_BCC);
+            JSValueRef plainBodyData = JSUtil::getProperty(context, dictionary,
+                    MESSAGE_DICTIONARY_ATTRIBUTE_PLAIN_BODY);
+            JSValueRef htmlBodyData = JSUtil::getProperty(context, dictionary,
+                    MESSAGE_DICTIONARY_ATTRIBUTE_HTML_BODY);
+            JSValueRef priorityData = JSUtil::getProperty(context, dictionary,
+                    MESSAGE_ATTRIBUTE_IS_HIGH_PRIORITY);
+
+            if (!JSValueIsUndefined(context, subjectData)) {
+                std::string subject = JSUtil::JSValueToString(context, subjectData);
+                LOGD(" Subject: %s", subject.c_str());
+                priv->setSubject(subject);
+            }
+            if (!JSValueIsUndefined(context, toData)) {
+                std::vector<std::string> to = JSUtil::JSArrayToStringVector(
+                        context, toData);
+                priv->setTO(to);
+            }
+            if (!JSValueIsUndefined(context, ccData)) {
+                std::vector<std::string> cc = JSUtil::JSArrayToStringVector(
+                        context, ccData);
+                priv->setCC(cc);
+            }
+            if (!JSValueIsUndefined(context, bccData)) {
+                std::vector<std::string> bcc = JSUtil::JSArrayToStringVector(
+                        context, bccData);
+                priv->setBCC(bcc);
+            }
+            if (!JSValueIsUndefined(context, htmlBodyData)) {
+                std::string htmlBody = JSUtil::JSValueToString(context, htmlBodyData);
+                LOGD(" htmlBody: %s", htmlBody.c_str());
+                priv->getBody()->setHtmlBody(htmlBody);
+            }
+            if (!JSValueIsUndefined(context, priorityData)) {
+                priv->setIsHighPriority(JSUtil::JSValueToBoolean(context, priorityData));
+            }
+            if (!JSValueIsUndefined(context, plainBodyData)) {
+                std::string plainBody = JSUtil::JSValueToString(context, plainBodyData);
+                LOGD(" plainBody: %s", plainBody.c_str());
+                priv->getBody()->setPlainBody(plainBody);
+            }
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Message creation failed: %s", err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Message creation failed - unsupported error.");
+    }
+
+    return jsObjRef;
+}
+
+void JSMessage::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSMessage::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    // Below holder is fetched from JSObject because holder
+    // with last shared_ptr instace should be removed
+    MessageHolder* priv = static_cast<MessageHolder*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+std::shared_ptr<Message> JSMessage::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not Message");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    MessageHolder* priv = static_cast<MessageHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSMessage::setPrivateObject(JSObjectRef object, std::shared_ptr<Message> data)
+{
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    MessageHolder* priv = static_cast<MessageHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new(std::nothrow) MessageHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in Message");
+            throw UnknownException(
+                    "Failed to set Message private data");
+        }
+    }
+}
+
+JSObjectRef JSMessage::makeJSObject(JSContextRef context,
+        std::shared_ptr<Message> ptr)
+{
+    if (!ptr) {
+        LOGE("NULL pointer to message given");
+        throw UnknownException("NULL pointer to message given");
+    }
+
+    MessageHolder* priv = new(std::nothrow) MessageHolder();
+    if (!priv) {
+        LOGW("Failed to allocate memory for MessageHolder");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = ptr;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
+        LOGE("Failed to set private in Message");
+        throw UnknownException("Private data not set");
+    }
+    return obj;
+}
+
+JSObjectRef JSMessage::messageVectorToJSObjectArray(JSContextRef context,
+        const MessagePtrVector& messages)
+{
+    size_t count = messages.size();
+
+    JSObjectRef array[count];
+    for (size_t i = 0; i < count; i++) {
+        array[i] = JSMessage::makeJSObject(context, messages[i]);
+    }
+    JSObjectRef result = JSObjectMakeArray(context, count,
+            count > 0 ? array : NULL, NULL);
+    if (!result) {
+        LOGW("Failed to create Message array");
+        throw UnknownException("Message array is null");
+    }
+    return result;
+}
+
+JSValueRef JSMessage::getAttachments(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return priv->getJSMessageAttachments(
+            Common::GlobalContextManager::getInstance()
+                ->getGlobalContext(context));
+    }
+    catch(const BasePlatformException& err) {
+        LOGE("Failed to get attachments: %s", err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting message attachment.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getBccAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return priv->getJSBCC(
+            Common::GlobalContextManager::getInstance()
+                ->getGlobalContext(context));
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get BCC. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting BCC.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getCcAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return priv->getJSCC(
+            Common::GlobalContextManager::getInstance()
+                ->getGlobalContext(context));
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get CC. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting CC.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getDestinationAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return priv->getJSTO(
+            Common::GlobalContextManager::getInstance()
+                ->getGlobalContext(context));
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get TO. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting TO.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getIsRead(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getIsRead());
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get is_read flag. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getMessageId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        if(priv->is_id_set()) {
+            std::string stringid = std::to_string(priv->getId());
+            return JSUtil::toJSValueRef(context, stringid);
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get message id. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting message id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getMessagePriority(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getIsHighPriority());
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get priority. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getMessageType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context,
+                MessagingUtil::messageTypeToString(priv->getType()));
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get message type. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting message type.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getSourceAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        if(priv->is_from_set()) {
+            return JSUtil::toJSValueRef(context, priv->getFrom());
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get source address. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting source address.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getSubject(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getSubject());
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get subject. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting subject.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getTime(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        if(priv->is_timestamp_set()) {
+            return JSUtil::makeDateObject(context, priv->getTimestamp());
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get timestamp. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting timestamp.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getFolder(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        if(priv->is_folder_id_set()) {
+            std::string stringid = std::to_string(priv->getFolderId());
+            return JSUtil::toJSValueRef(context, stringid);
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get folder id. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting subject.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getMessageBody(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSMessageBody::makeJSObject(context, priv->getBody());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get MessageBody: %s", err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while setting BCC.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSMessage::setAttachments(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        if(!JSIsArrayValue(context,value)) {
+            return true;
+        }
+
+        auto priv = getPrivateObject(context, object);
+
+        AttachmentPtrVector atts;
+        atts = JSUtil::JSArrayToType_<std::shared_ptr<MessageAttachment>>(
+                context, value, JSMessageAttachment::getPrivateObject);
+        priv->setMessageAttachments(atts);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to set Attachments: %s", err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while setting Attachments.");
+    }
+    return true;
+}
+
+bool JSMessage::setBccAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        if(!JSIsArrayValue(context,value)) {
+            return true;
+        }
+
+        auto priv = getPrivateObject(context, object);
+
+        std::vector<std::string> bcc = JSUtil::JSArrayToStringVector(
+                context, value);
+        priv->setBCC(bcc);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to set BCC. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while setting BCC.");
+    }
+    return true;
+}
+
+bool JSMessage::setCcAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        if(!JSIsArrayValue(context,value)) {
+            return true;
+        }
+
+        auto priv = getPrivateObject(context, object);
+
+        std::vector<std::string> cc = JSUtil::JSArrayToStringVector(
+                context, value);
+        priv->setCC(cc);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to set CC. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while setting CC.");
+    }
+    return true;
+}
+
+bool JSMessage::setDestinationAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef * exception)
+{
+    LOGD("Entered");
+    try {
+        if(!JSIsArrayValue(context,value)) {
+            return true;
+        }
+
+        auto priv = getPrivateObject(context, object);
+
+        std::vector<std::string> to = JSUtil::JSArrayToStringVector(
+                context, value);
+        priv->setTO(to);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to set TO. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while setting TO.");
+    }
+    return true;
+}
+
+bool JSMessage::setIsRead(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef * exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        priv->setIsRead(JSUtil::JSValueToBoolean(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to set isRead flag. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return true;
+}
+
+bool JSMessage::setMessagePriority(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef * exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        priv->setIsHighPriority(JSUtil::JSValueToBoolean(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to set priority. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return true;
+}
+
+bool JSMessage::setSubject(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef * exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        priv->setSubject(JSUtil::JSValueToString(context, value));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to set subject. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while setting subject.");
+    }
+    return true;
+}
+
+bool JSMessage::setMessageBody(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    // TODO: MessageBody setting problem should be solved in spec or implementation
+    return true;
+}
+
+JSValueRef JSMessage::getConversationId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        if(priv->is_conversation_id_set()) {
+            std::string stringid = std::to_string(priv->getConversationId());
+            return JSUtil::toJSValueRef(context, stringid);
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get conversation id. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting conversation id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getInResponseTo(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        if(priv->is_in_response_set()) {
+            std::string stringid = std::to_string(priv->getInResponseTo());
+            return JSUtil::toJSValueRef(context, stringid);
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get inResponeTo. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting inResponseTo.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::getMessageStatus(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context,
+                MessagingUtil::messageStatusToString(priv->getMessageStatus()));
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get message status. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    // Catch all exceptions not related to platform API execution failures
+    catch(...) {
+        LOGE("Unsupported error while getting message status.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessage::hasAttachment(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getHasAttachment());
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Failed to get hasAttachment flag. %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} //Messaging
+} //DeviceAPI
+
diff --git a/src/Messaging/JSMessage.h b/src/Messaging/JSMessage.h
new file mode 100644 (file)
index 0000000..4caa3ae
--- /dev/null
@@ -0,0 +1,253 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_MESSAGE_H__
+#define __TIZEN_JS_MESSAGE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <Logger.h>
+#include "Message.h"
+// headers below needed to declare function that converts vector of
+// MessageAttachment into JSArray
+#include <vector>
+#include <memory>
+#include "MessageAttachment.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace JSMessageKeys {
+extern const char* MESSAGE_ATTRIBUTE_ID;
+extern const char* MESSAGE_ATTRIBUTE_CONVERSATION_ID;
+extern const char* MESSAGE_ATTRIBUTE_FOLDER_ID;
+extern const char* MESSAGE_ATTRIBUTE_TYPE;
+extern const char* MESSAGE_ATTRIBUTE_TIMESTAMP;
+extern const char* MESSAGE_ATTRIBUTE_FROM;
+extern const char* MESSAGE_ATTRIBUTE_TO;
+extern const char* MESSAGE_ATTRIBUTE_CC;
+extern const char* MESSAGE_ATTRIBUTE_BCC;
+extern const char* MESSAGE_ATTRIBUTE_BODY;
+extern const char* MESSAGE_ATTRIBUTE_IS_READ;
+extern const char* MESSAGE_ATTRIBUTE_IS_HIGH_PRIORITY;
+extern const char* MESSAGE_ATTRIBUTE_SUBJECT;
+extern const char* MESSAGE_ATTRIBUTE_IN_RESPONSE_TO;
+extern const char* MESSAGE_ATTRIBUTE_MESSAGE_STATUS;
+extern const char* MESSAGE_ATTRIBUTE_ATTACHMENTS;
+extern const char* MESSAGE_ATTRIBUTE_HAS_ATTACHMENT;
+} //namespace MESSAGE_ATTRIBUTE
+
+class JSMessage
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef ctx,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static std::shared_ptr<Message> getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            std::shared_ptr<Message> data);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            std::shared_ptr<Message> ptr);
+
+    /**
+     * Function converts vector of shared_pointers with Message into JSArray
+     */
+    static JSObjectRef messageVectorToJSObjectArray(JSContextRef context,
+            const MessagePtrVector& messages);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getAttachments(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getBccAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCcAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDestinationAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsRead(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMessageId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMessagePriority(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMessageType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getSourceAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getSubject(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTime(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getFolder(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMessageBody(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setAttachments(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setBccAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setCcAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setDestinationAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setIsRead(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setMessagePriority(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setSubject(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setMessageBody(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getConversationId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getInResponseTo(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMessageStatus(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef hasAttachment(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //Messaging
+} //DeviceAPI
+
+#endif //__TIZEN_JS_MESSAGE_H__
+
diff --git a/src/Messaging/JSMessageAttachment.cpp b/src/Messaging/JSMessageAttachment.cpp
new file mode 100644 (file)
index 0000000..62ee120
--- /dev/null
@@ -0,0 +1,350 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <Logger.h>
+
+#include "JSMessageAttachment.h"
+#include "MessageAttachment.h"
+
+#include "plugin_config.h"
+
+#include <JSUtil.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+const char* MESSAGE_ATTACHMENT = "MessageAttachment";
+
+const char* MESSAGE_ATTACHMENT_ID = "id";
+const char* MESSAGE_ATTACHMENT_MSG_ID = "messageId";
+const char* MESSAGE_ATTACHMENT_MIME_TYPE = "mimeType";
+const char* MESSAGE_ATTACHMENT_FILE_PATH = "filePath";
+}
+
+JSClassRef JSMessageAttachment::m_jsClassRef = NULL;
+
+JSClassDefinition JSMessageAttachment::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    MESSAGE_ATTACHMENT,
+    NULL,
+    JSMessageAttachment::m_property,
+    NULL,
+    JSMessageAttachment::initialize,
+    JSMessageAttachment::finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //callAsConstructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSMessageAttachment::m_property[] = {
+    { MESSAGE_ATTACHMENT_ID, getId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_ATTACHMENT_MSG_ID, getMsgId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_ATTACHMENT_MIME_TYPE, getMimeType, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_ATTACHMENT_FILE_PATH, getFilePath, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSMessageAttachment::getClassInfo()
+{
+    LOGD("Entered");
+    return &(m_classInfo);
+}
+
+JSClassRef DLL_EXPORT JSMessageAttachment::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSMessageAttachment::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSMessageAttachment::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    // Below holder is fetched from JSObject because holder
+    // with last shared_ptr instace should be removed
+    MessageAttachmentHolder* priv =
+            static_cast<MessageAttachmentHolder*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+std::shared_ptr<MessageAttachment> JSMessageAttachment::getPrivateObject(
+        JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not MessageAttachment");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    MessageAttachmentHolder* priv = static_cast<MessageAttachmentHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSMessageAttachment::setPrivateObject(JSObjectRef object,
+        std::shared_ptr<MessageAttachment> data)
+{
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    MessageAttachmentHolder* priv = static_cast<MessageAttachmentHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new(std::nothrow) MessageAttachmentHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in MessageAttachment");
+            throw UnknownException("Failed to set MessageAttachment private data");
+        }
+    }
+}
+
+JSObjectRef JSMessageAttachment::makeJSObject(JSContextRef context,
+        std::shared_ptr<MessageAttachment> native)
+{
+    if (!native) {
+        LOGE("NULL pointer to attachment given");
+        throw UnknownException("NULL pointer to attachment given");
+    }
+
+    MessageAttachmentHolder* priv = new(std::nothrow) MessageAttachmentHolder();
+    if (!priv) {
+        LOGW("Failed to allocate memory for AttachmentHolder");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
+        LOGE("Failed to set private in MessageAttachment");
+        throw UnknownException("Private data not set");
+    }
+    return obj;
+}
+
+JSObjectRef JSMessageAttachment::attachmentVectorToJSObjectArray(
+        JSContextRef context, const AttachmentPtrVector& atts)
+{
+    size_t count = atts.size();
+
+    JSObjectRef array[count];
+    for (size_t i = 0; i < count; i++) {
+        array[i] = JSMessageAttachment::makeJSObject(context, atts[i]);
+    }
+    JSObjectRef result = JSObjectMakeArray(context, count,
+            count > 0 ? array : NULL, NULL);
+    if (!result) {
+        LOGW("Failed to create MessageAttachment array");
+        throw UnknownException("MessageAttachment array is null");
+    }
+    return result;
+}
+
+JSObjectRef DLL_EXPORT JSMessageAttachment::constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef jsObjRef = JSObjectMake(context, JSMessageAttachment::getClassRef(), NULL);
+
+    // constructor
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, jsObjRef, ctorName, constructor,
+        kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        std::string filePath = validator.toString(0);
+        LOGD(" filePath: %s", filePath.c_str());
+
+        auto priv = std::shared_ptr<MessageAttachment>(new (std::nothrow)
+                MessageAttachment());
+        if(!priv) {
+            LOGE("Failed to allocate memory for private data");
+            throw UnknownException("Memory allocation failuer");
+        }
+
+        priv->setFilePath(filePath);
+        if (!validator.isNull(1) && !validator.isOmitted(1)) {
+            std::string mimeType = validator.toString(1, true);
+            LOGD(" mimeType: %s", mimeType.c_str());
+            priv->setMimeType(mimeType);
+        }
+
+        JSMessageAttachment::setPrivateObject(jsObjRef, priv);
+    }
+    catch (BasePlatformException &err) {
+        LOGE("MessageAttachment creation failed: %s", err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("MessageAttachment creation failed: Unknown exception.");
+    }
+
+    return jsObjRef;
+}
+
+JSValueRef JSMessageAttachment::getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        auto priv = JSMessageAttachment::getPrivateObject(context, object);
+
+        if (priv->isIdSet()) {
+            std::string stringid = std::to_string(priv->getId());
+            return JSUtil::toJSValueRef(context, stringid);
+        }else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMessageAttachmentId - unknown exception.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageAttachment::getMsgId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSMessageAttachment::getPrivateObject(context, object);
+
+        if (priv->isMessageIdSet()) {
+            std::string stringid = std::to_string(priv->getMessageId());
+            return JSUtil::toJSValueRef(context, stringid);
+        } else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMessageAttachmentMsgId - unknown exception.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageAttachment::getMimeType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSMessageAttachment::getPrivateObject(context, object);
+
+        if (priv->isMimeTypeSet()) {
+            return JSUtil::toJSValueRef(context, priv->getMimeType());
+        } else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMessageAttachmentMimeType - unknown exception.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageAttachment::getFilePath(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSMessageAttachment::getPrivateObject(context, object);
+
+        if (priv->isFilePathSet() && priv->isSaved()) {
+            return JSUtil::toJSValueRef(context, priv->getFilePath());
+        } else {
+            return JSValueMakeNull(context);
+        }
+
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMessageAttachmentFilePath - unknown exception.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} //Messaging
+} //DeviceAPI
+
diff --git a/src/Messaging/JSMessageAttachment.h b/src/Messaging/JSMessageAttachment.h
new file mode 100755 (executable)
index 0000000..cfda6c7
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_MESSAGE_ATTACHMENT_H__
+#define __TIZEN_JS_MESSAGE_ATTACHMENT_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageAttachment;
+typedef std::vector<std::shared_ptr<MessageAttachment>> AttachmentPtrVector;
+
+class JSMessageAttachment
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef ctx,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static std::shared_ptr<MessageAttachment> getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            std::shared_ptr<MessageAttachment> data);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+        std::shared_ptr<MessageAttachment> attptr);
+
+    /**
+     * Function converts vector of shared_pointers with MessageAttachment
+     * into JSArray
+     */
+    static JSObjectRef attachmentVectorToJSObjectArray(JSContextRef context,
+            const AttachmentPtrVector& atts);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMsgId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMimeType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getFilePath(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+    * This structure describes a statically declared function property.
+    */
+    static JSStaticFunction m_function[];
+
+    /**
+    * This structure contains properties and callbacks that define a type of object.
+    */
+    static JSClassDefinition m_classInfo;
+
+    /**
+    * This member variable contains the initialization values for the static properties of this class.
+    * The values are given according to the data structure JSPropertySpec
+    */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //Messaging
+} //DeviceAPI
+
+#endif //__TIZEN_JS_MESSAGE_ATTACHMENT_H__
+
diff --git a/src/Messaging/JSMessageBody.cpp b/src/Messaging/JSMessageBody.cpp
new file mode 100644 (file)
index 0000000..afd250c
--- /dev/null
@@ -0,0 +1,342 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+
+#include <GlobalContextManager.h>
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <Logger.h>
+
+#include "JSMessageBody.h"
+#include "MessageBody.h"
+#include "JSMessageAttachment.h"
+
+#include "plugin_config.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+const char* MESSAGE_BODY = "MessageBody";
+
+const char* MESSAGE_BODY_ID = "messageId";
+const char* MESSAGE_BODY_LOADED = "loaded";
+const char* MESSAGE_BODY_PLAIN_BODY = "plainBody";
+const char* MESSAGE_BODY_HTML_BODY = "htmlBody";
+const char* MESSAGE_BODY_INLINE_ATT = "inlineAttachments";
+}
+
+JSClassRef JSMessageBody::m_jsClassRef = NULL;
+
+JSClassDefinition JSMessageBody::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    MESSAGE_BODY,
+    NULL,
+    JSMessageBody::m_property,
+    NULL,
+    JSMessageBody::initialize,
+    JSMessageBody::finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty
+    NULL, //setProperty
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames
+    NULL, //callAsFunction,
+    NULL, //callAsConstructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSMessageBody::m_property[] = {
+    { MESSAGE_BODY_ID, getId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_BODY_LOADED, getLoaded, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_BODY_PLAIN_BODY, getPlainBody, setPlainBody, kJSPropertyAttributeDontDelete },
+    { MESSAGE_BODY_HTML_BODY, getHTMLBody, setHTMLBody, kJSPropertyAttributeDontDelete },
+    { MESSAGE_BODY_INLINE_ATT, getInlineAtt, setInlineAtt, kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSMessageBody::getClassInfo()
+{
+    return &(m_classInfo);
+}
+
+JSClassRef JSMessageBody::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSMessageBody::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSMessageBody::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    // Below holder is fetched and deleted from JSObject because last shared_ptr
+    // instace should be removed
+    MessageBodyHolder* priv = static_cast<MessageBodyHolder*>(
+            JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+std::shared_ptr<MessageBody> JSMessageBody::getPrivateObject(
+        JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not MessageBody");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    MessageBodyHolder* priv = static_cast<MessageBodyHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSMessageBody::setPrivateObject(JSObjectRef object,
+        std::shared_ptr<MessageBody> data)
+{
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    MessageBodyHolder* priv = static_cast<MessageBodyHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new(std::nothrow) MessageBodyHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in MessageBody");
+            throw UnknownException(
+                    "Failed to set MessageBody private data");
+        }
+    }
+}
+
+JSObjectRef JSMessageBody::makeJSObject(JSContextRef context,
+        std::shared_ptr<MessageBody> ptr)
+{
+    if (!ptr) {
+        LOGE("NULL pointer to message body given");
+        throw UnknownException("NULL pointer to message body given");
+    }
+
+    MessageBodyHolder* priv = new(std::nothrow) MessageBodyHolder();
+    if (!priv) {
+        LOGW("Failed to allocate memory for MessageBodyHolder");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = ptr;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
+        LOGE("Failed to set private in MessageBody");
+        throw UnknownException("Private data not set");
+    }
+    return obj;
+}
+
+JSValueRef JSMessageBody::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        if(priv->is_message_id_set()) {
+            std::string stringid = std::to_string(priv->getMessageId());
+            return JSUtil::toJSValueRef(context, stringid);
+        }
+        else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageBody::getLoaded(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getLoaded());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageBody::getPlainBody(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getPlainBody());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageBody::getHTMLBody(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getHtmlBody());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageBody::getInlineAtt(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        return priv->getJSInlineAttachments(
+            Common::GlobalContextManager::getInstance()
+                ->getGlobalContext(context));
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSMessageBody::setPlainBody(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        std::string c_value = JSUtil::JSValueToString(context, value);
+        priv->setPlainBody(c_value);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return true;
+}
+
+bool JSMessageBody::setHTMLBody(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+
+        std::string c_value = JSUtil::JSValueToString(context, value);
+        priv->setHtmlBody(c_value);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return true;
+}
+
+bool JSMessageBody::setInlineAtt(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        if(!JSIsArrayValue(context,value)) {
+            return true;
+        }
+
+        auto priv = getPrivateObject(context, object);
+
+        AttachmentPtrVector atts;
+        atts = JSUtil::JSArrayToType_<std::shared_ptr<MessageAttachment>>(
+                context, value, JSMessageAttachment::getPrivateObject);
+        priv->setInlineAttachments(atts);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return true;
+}
+
+} //Messaging
+} //DeviceAPI
+
diff --git a/src/Messaging/JSMessageBody.h b/src/Messaging/JSMessageBody.h
new file mode 100755 (executable)
index 0000000..29448ca
--- /dev/null
@@ -0,0 +1,125 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_MESSAGE_BODY_H__
+#define __TIZEN_JS_MESSAGE_BODY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "MessageBody.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class JSMessageBody
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static std::shared_ptr<MessageBody> getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            std::shared_ptr<MessageBody> data);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            std::shared_ptr<MessageBody> ptr);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLoaded(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPlainBody(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getHTMLBody(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getInlineAtt(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setPlainBody(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setHTMLBody(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setInlineAtt(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+    * This member variable contains the initialization values for the static properties of this class.
+    * The values are given according to the data structure JSPropertySpec
+    */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //Messaging
+} //DeviceAPI
+
+#endif //__TIZEN_JS_MESSAGE_BODY_H__
+
diff --git a/src/Messaging/JSMessageConversation.cpp b/src/Messaging/JSMessageConversation.cpp
new file mode 100644 (file)
index 0000000..360e54d
--- /dev/null
@@ -0,0 +1,444 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+
+#include <GlobalContextManager.h>
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <Logger.h>
+
+#include "JSMessageConversation.h"
+#include "MessageConversation.h"
+
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+namespace {
+const char* MESSAGE_CONVERSATION = "MessageConversation";
+}
+
+namespace JSMessageConversationKeys {
+const char* MESSAGE_CONVERSATION_ID = "id";
+const char* MESSAGE_CONVERSATION_TYPE = "type";
+const char* MESSAGE_CONVERSATION_TIMESTAMP = "timestamp";
+const char* MESSAGE_CONVERSATION_MSG_COUNT = "messageCount";
+const char* MESSAGE_CONVERSATION_UNREAD_MSG = "unreadMessages";
+const char* MESSAGE_CONVERSATION_PREVIEW = "preview";
+const char* MESSAGE_CONVERSATION_SUBJECT = "subject";
+const char* MESSAGE_CONVERSATION_IS_READ = "isRead";
+const char* MESSAGE_CONVERSATION_FROM = "from";
+const char* MESSAGE_CONVERSATION_TO = "to";
+const char* MESSAGE_CONVERSATION_CC = "cc";
+const char* MESSAGE_CONVERSATION_BCC = "bcc";
+const char* MESSAGE_CONVERSATION_LAST_MSG_ID = "lastMessageId";
+}
+
+using namespace JSMessageConversationKeys;
+
+JSClassRef JSMessageConversation::m_jsClassRef = NULL;
+
+JSClassDefinition JSMessageConversation::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    MESSAGE_CONVERSATION,
+    NULL,
+    JSMessageConversation::m_property,
+    NULL,
+    JSMessageConversation::initialize,
+    JSMessageConversation::finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL,
+    NULL,
+    NULL, //hasInstance,
+    NULL
+};
+
+JSStaticValue JSMessageConversation::m_property[] = {
+    { MESSAGE_CONVERSATION_ID, getId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_TYPE, getType, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_TIMESTAMP, getTimestamp, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_MSG_COUNT, getMsgCount, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_UNREAD_MSG, getUnreadMsg, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_PREVIEW, getPreview, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_SUBJECT, getSubject, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_IS_READ, getIsRead, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_FROM, getFrom, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_TO, getTo, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_CC, getCC, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_BCC, getBCC, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_CONVERSATION_LAST_MSG_ID, getLastMsgId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef DLL_EXPORT JSMessageConversation::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSMessageConversation::getClassInfo()
+{
+    LOGD("Entered");
+    return &m_classInfo;
+}
+
+void JSMessageConversation::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSMessageConversation::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    MessageConversationHolder* priv =
+            static_cast<MessageConversationHolder*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object,NULL);
+    delete priv;
+}
+
+std::shared_ptr<MessageConversation> JSMessageConversation::getPrivateObject(
+        JSContextRef context, JSValueRef value)
+{
+    if(!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+
+    MessageConversationHolder* priv = static_cast<MessageConversationHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSMessageConversation::setPrivateObject(JSObjectRef object, std::shared_ptr<MessageConversation> data)
+{
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    MessageConversationHolder* priv = static_cast<MessageConversationHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new(std::nothrow) MessageConversationHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in MessageConversation");
+            throw UnknownException(
+                    "Failed to set MessageConversation private data");
+        }
+    }
+}
+
+JSObjectRef JSMessageConversation::makeJSObject(JSContextRef context,
+        std::shared_ptr<MessageConversation> ptr)
+{
+    if (!ptr) {
+        LOGE("NULL pointer to message conversation given");
+        throw UnknownException("NULL pointer to message conversation given");
+    }
+
+    MessageConversationHolder* priv = new(std::nothrow) MessageConversationHolder();
+    if (!priv) {
+        LOGW("Failed to allocate memory for MessageConversationHolder");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = ptr;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
+        LOGE("Failed to set private in MessageConversation");
+        throw UnknownException("Private data not set");
+    }
+    return obj;
+}
+
+JSValueRef JSMessageConversation::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        std::string stringid = std::to_string(priv->getConversationId());
+        return JSUtil::toJSValueRef(context, stringid);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, MessagingUtil::messageTypeToString(priv->getType()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting message conversation type.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getTimestamp(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::makeDateObject(context, priv->getTimestamp());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getMsgCount(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getMessageCount());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getUnreadMsg(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getUnreadMessages());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getPreview(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getPreview());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting message conversation preview.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getSubject(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getSubject());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting message conversation subject.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getIsRead(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getIsRead());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting message conversation isRead flag.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getFrom(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getFrom());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting message conversation source address.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getTo(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getTo());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting message conversation destination address.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getCC(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getCC());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting CC.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getBCC(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getBCC());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting BCC.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageConversation::getLastMsgId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        std::string stringid = std::to_string(priv->getLastMessageId());
+        return JSUtil::toJSValueRef(context, stringid);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting last message id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} //Messaging
+} //DeviceAPI
diff --git a/src/Messaging/JSMessageConversation.h b/src/Messaging/JSMessageConversation.h
new file mode 100755 (executable)
index 0000000..dd2c221
--- /dev/null
@@ -0,0 +1,162 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_MESSAGE_CONVERSATION_H__
+#define __TIZEN_JS_MESSAGE_CONVERSATION_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "MessageConversation.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace JSMessageConversationKeys {
+extern const char* MESSAGE_CONVERSATION_ID;
+extern const char* MESSAGE_CONVERSATION_TYPE;
+extern const char* MESSAGE_CONVERSATION_TIMESTAMP;
+extern const char* MESSAGE_CONVERSATION_MSG_COUNT;
+extern const char* MESSAGE_CONVERSATION_UNREAD_MSG;
+extern const char* MESSAGE_CONVERSATION_PREVIEW;
+extern const char* MESSAGE_CONVERSATION_SUBJECT;
+extern const char* MESSAGE_CONVERSATION_IS_READ;
+extern const char* MESSAGE_CONVERSATION_FROM;
+extern const char* MESSAGE_CONVERSATION_TO;
+extern const char* MESSAGE_CONVERSATION_CC;
+extern const char* MESSAGE_CONVERSATION_BCC;
+extern const char* MESSAGE_CONVERSATION_LAST_MSG_ID;
+}
+
+class JSMessageConversation
+{
+public:
+/* @struct JSClassDefinition
+ *@abstract This structure contains properties and callbacks that define a type of object.
+ *@abstract All fields other than the version field are optional. Any pointer may be NULL.
+ */
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static std::shared_ptr<MessageConversation> getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            std::shared_ptr<MessageConversation> data);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            std::shared_ptr<MessageConversation> ptr);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTimestamp(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMsgCount(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getUnreadMsg(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPreview(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getSubject(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsRead(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getFrom(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getTo(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getCC(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getBCC(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLastMsgId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties
+     * of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //Messaging
+} //DeviceAPI
+
+#endif //__TIZEN_JS_MESSAGE_CONVERSATION_H__
diff --git a/src/Messaging/JSMessageFolder.cpp b/src/Messaging/JSMessageFolder.cpp
new file mode 100644 (file)
index 0000000..e9c977b
--- /dev/null
@@ -0,0 +1,402 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSMessageFolder.cpp
+ */
+
+
+#include <JSUtil.h>
+#include <SecurityExceptions.h>
+
+#include <Export.h>
+#include <Logger.h>
+
+#include "JSMessageFolder.h"
+#include "MessageFolder.h"
+#include "MessagingUtil.h"
+#include "MessageFolder.h"
+
+#include "plugin_config.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+const char* MESSAGE_FOLDER = "MessageFolder";
+
+const char* MESSAGE_FOLDER_ID = "id";
+const char* MESSAGE_FOLDER_PARENT_ID = "parentId";
+const char* MESSAGE_FOLDER_SERVICE_ID = "serviceId";
+const char* MESSAGE_FOLDER_CONTENT_TYPE = "contentType";
+const char* MESSAGE_FOLDER_NAME = "name";
+const char* MESSAGE_FOLDER_PATH = "path";
+const char* MESSAGE_FOLDER_TYPE = "type";
+const char* MESSAGE_FOLDER_SYNCHRONIZABLE = "synchronizable";
+}
+
+JSClassRef JSMessageFolder::m_jsClassRef = NULL;
+
+JSClassDefinition JSMessageFolder::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    MESSAGE_FOLDER,
+    NULL,
+    JSMessageFolder::m_property,
+    NULL,
+    JSMessageFolder::initialize,
+    JSMessageFolder::finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //callAsConstructor,
+    NULL, //hasInstance,
+    NULL, //convertToType,
+};
+
+JSStaticValue JSMessageFolder::m_property[] = {
+    { MESSAGE_FOLDER_ID, getId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_FOLDER_PARENT_ID, getParentId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_FOLDER_SERVICE_ID, getServiceId, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_FOLDER_CONTENT_TYPE, getContentType, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_FOLDER_NAME, getName, setName, kJSPropertyAttributeDontDelete },
+    { MESSAGE_FOLDER_PATH, getPath, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_FOLDER_TYPE, getType, NULL, kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { MESSAGE_FOLDER_SYNCHRONIZABLE, getSynchronizable, setSynchronizable, kJSPropertyAttributeDontDelete },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSMessageFolder::getClassRef() {
+    LOGD("Entered");
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSMessageFolder::getClassInfo() {
+    LOGD("Entered");
+    return &(m_classInfo);
+}
+
+void JSMessageFolder::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSMessageFolder::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    MessageFolderHolder* priv = static_cast<MessageFolderHolder*>(JSObjectGetPrivate(object));
+    if(priv)
+    {
+        JSObjectSetPrivate(object,NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+std::shared_ptr<MessageFolder> JSMessageFolder::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if(!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+
+    MessageFolderHolder* priv = static_cast<MessageFolderHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw UnknownException("Private data is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSMessageFolder::setPrivateObject(JSObjectRef object, std::shared_ptr<MessageFolder> data)
+{
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    MessageFolderHolder* priv = static_cast<MessageFolderHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new(std::nothrow) MessageFolderHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in MessageFolder");
+            throw UnknownException(
+                    "Failed to set MessageFolder private data");
+        }
+    }
+}
+
+JSObjectRef JSMessageFolder::makeJSObject(JSContextRef context,
+        std::shared_ptr<MessageFolder> ptr)
+{
+    if (!ptr) {
+        LOGE("NULL pointer to message folder given");
+        throw UnknownException("NULL pointer to message folder given");
+    }
+
+    MessageFolderHolder* priv = new(std::nothrow) MessageFolderHolder();
+    if (!priv) {
+        LOGW("Failed to allocate memory for MessageFolderHolder");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = ptr;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    if(!JSObjectSetPrivate(obj, static_cast<void*>(priv))) {
+        LOGE("Failed to set private in MessageFolder");
+        throw UnknownException("Private data not set");
+    }
+    return obj;
+}
+
+JSValueRef JSMessageFolder::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getId());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get message folder id. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting message folder id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageFolder::getParentId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        if (priv->isParentIdSet()) {
+            return JSUtil::toJSValueRef(context, priv->getParentId());
+        } else {
+            return JSValueMakeNull(context);
+        }
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get message folder parent id. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting message folder parent id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageFolder::getServiceId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getServiceId());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get message folder service id. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting message folder service id.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageFolder::getContentType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getContentType());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get message folder content type. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting message folder content type.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageFolder::getName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getName());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get message folder name. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting message folder name.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageFolder::getPath(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getPath());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get message folder path. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting message folder path.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageFolder::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context,
+                MessagingUtil::messageFolderTypeToString(priv->getType()));
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get message folder type. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting message folder type.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageFolder::getSynchronizable(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getSynchronizable());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to get message folder is synchronizable flag. %s : %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSMessageFolder::setName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        std::string c_value = JSUtil::JSValueToString(context, value);
+        priv->setName(c_value);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to set message folder name. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while setting message folder name.");
+    }
+    return true;
+}
+
+bool JSMessageFolder::setSynchronizable(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = getPrivateObject(context, object);
+        bool c_value = JSUtil::JSValueToBoolean(context, value);
+        priv->setSynchronizable(c_value);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Failed to set message folder is synchronizable flag. %s : %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while setting message folder is synchronizable flag.");
+    }
+    return true;
+}
+
+} //Messaging
+} //DeviceAPI
+
diff --git a/src/Messaging/JSMessageFolder.h b/src/Messaging/JSMessageFolder.h
new file mode 100755 (executable)
index 0000000..892474b
--- /dev/null
@@ -0,0 +1,133 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        JSMessageFolder.h
+ */
+
+
+#ifndef __TIZEN_JS_MESSAGE_FOLDER_H__
+#define __TIZEN_JS_MESSAGE_FOLDER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "MessageFolder.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class JSMessageFolder
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static JSClassRef getClassRef();
+
+    static std::shared_ptr<MessageFolder> getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            std::shared_ptr<MessageFolder> data);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            std::shared_ptr<MessageFolder> ptr);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getParentId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getServiceId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getContentType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getPath(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getSynchronizable(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setSynchronizable(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties
+     * of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //Messaging
+} //DeviceAPI
+
+#endif //__TIZEN_JS_MESSAGE_FOLDER_H__
+
diff --git a/src/Messaging/JSMessageService.cpp b/src/Messaging/JSMessageService.cpp
new file mode 100644 (file)
index 0000000..cff7289
--- /dev/null
@@ -0,0 +1,587 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+
+#include <GlobalContextManager.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include <Export.h>
+#include <Logger.h>
+#include <PlatformException.h>
+#include <TimeTracer.h>
+#include <tapi_common.h>
+
+#include "JSMessage.h"
+#include "JSMessageService.h"
+#include "MessageService.h"
+#include "MessagingUtil.h"
+
+#include "plugin_config.h"
+#include "JSMessageStorage.h"
+
+#include "JSMessageFolder.h"
+#include "JSMessageAttachment.h"
+
+#include "MessagingManager.h"
+
+using namespace std;
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+const char* MESSAGE_SERVICE = "MessageService";
+
+const char* MESSAGE_SERVICE_ID = "id";
+const char* MESSAGE_SERVICE_TYPE = "type";
+const char* MESSAGE_SERVICE_NAME = "name";
+const char* MESSAGE_SERVICE_MSG_STORAGE = "messageStorage";
+}
+
+JSClassRef JSMessageService::m_jsClassRef = NULL;
+
+JSClassDefinition JSMessageService::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    MESSAGE_SERVICE,
+    NULL,
+    JSMessageService::m_property,
+    JSMessageService::m_function,
+    JSMessageService::initialize,
+    JSMessageService::finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL,
+    NULL,
+    NULL, //hasInstance,
+    NULL
+};
+
+JSStaticValue JSMessageService::m_property[] = {
+    { MESSAGE_SERVICE_ID, getId, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { MESSAGE_SERVICE_TYPE, getType, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { MESSAGE_SERVICE_NAME, getName, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { MESSAGE_SERVICE_MSG_STORAGE, getMsgStorage, NULL, kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSMessageService::m_function[] = {
+    { MESSAGING_FUNCTION_API_SEND_MESSAGE, JSMessageService::sendMessage,
+            kJSPropertyAttributeNone },
+    { MESSAGING_FUNCTION_API_LOAD_MESSAGE_BODY, JSMessageService::loadMessageBody,
+            kJSPropertyAttributeNone },
+    { MESSAGING_FUNCTION_API_LOAD_MESSAGE_ATTACHMENT,
+            JSMessageService::loadMessageAttachment, kJSPropertyAttributeNone },
+    { MESSAGING_FUNCTION_API_SYNC, JSMessageService::sync,
+            kJSPropertyAttributeNone },
+    { MESSAGING_FUNCTION_API_SYNC_FOLDER, JSMessageService::syncFolder,
+            kJSPropertyAttributeNone },
+    { MESSAGING_FUNCTION_API_STOP_SYNC, JSMessageService::stopSync,
+            kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSMessageService::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+MessageService* JSMessageService::getPrivateObject(
+        JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw Common::TypeMismatchException("Object type is not MessageService");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    MessageService* priv = static_cast<MessageService*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw Common::UnknownException("Private data is null");
+    }
+
+    return priv;
+}
+
+JSObjectRef JSMessageService::createJSObject(JSContextRef context,
+        MessageService* priv)
+{
+    LOGD("Entered");
+    if (!priv) {
+        LOGE("Private data is null");
+        return NULL;
+    }
+    priv->copyAceCheckAccessFunction(MessagingManager::getInstance());
+    JSObjectRef jsObject = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    if (NULL == jsObject) {
+        LOGE("object creation error");
+    }
+
+    return jsObject;
+}
+
+void JSMessageService::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSMessageService::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    MessageService* priv = static_cast<MessageService*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSMessageService::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        MessageService* priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context,
+            MessagingUtil::messageTypeToString(priv->getMsgServiceType()));
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error, cannot get property");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageService::getName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        MessageService* priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getMsgServiceName());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error, cannot get property");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageService::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        MessageService* priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getMsgServiceIdStr());
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error, cannot get property");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageService::getMsgStorage(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        MessageService* priv = getPrivateObject(context, object);
+
+        std::shared_ptr<MessageStorage> storage = priv->getMsgStorage();
+        storage->copyAceCheckAccessFunction(priv);
+
+        return JSMessageStorage::makeJSObject(context, storage);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error, cannot get property");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageService::sendMessage(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    MessageRecipientsCallbackData *callback = NULL;
+    try {
+        MessageService* priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                MESSAGING_FUNCTION_API_SEND_MESSAGE);
+
+        // void sendMessage(Message message,
+        //         optional MessageRecipientsCallback successCallback,
+        //         optional ErrorCallback? errorCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::shared_ptr<Message> message = JSMessage::getPrivateObject(context,
+                validator.toJSValueRef(0));
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) MessageRecipientsCallbackData(g_ctx);
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        callback->setMessage(message);
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        // internally TelNetworkDefaultDataSubs_t consists of -1(unknown), 0(sim_1), 1(sim_2)
+        // but in spec, simIndex parameter starts with 1.
+        // so if user set simIndex param, then minus 1 on it.
+        long tmp = validator.toLong(3, true, 0);
+        char **cp_list = tel_get_cp_name_list();
+        int sim_count = 0;
+
+        if (cp_list) {
+            while (cp_list[sim_count]) {
+                sim_count++;
+            }
+            g_strfreev(cp_list);
+        } else {
+            LOGD("Empty cp name list returned by function: tel_get_cp_name_list()");
+        }
+
+        tmp--;
+        if (tmp >= sim_count || tmp < -1) {
+            LOGE("Sim index out of bound %d : %d", tmp, sim_count);
+            Common::InvalidValuesException err("The index of sim is out of bound");
+            callback->setError(err.getName().c_str(), err.getMessage().c_str());
+            callback->callErrorCallback();
+
+            delete callback;
+            callback = NULL;
+            return JSValueMakeUndefined(context);
+        }
+
+        callback->setSimIndex(static_cast<TelNetworkDefaultDataSubs_t>(tmp));
+        priv->sendMessage(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error, cannot send message");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageService::loadMessageBody(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+
+    MessageBodyCallbackData *callback = NULL;
+    try {
+        MessageService* priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                MESSAGING_FUNCTION_API_LOAD_MESSAGE_BODY);
+        // void loadMessageBody(Message message,
+        //         MessageBodySuccessCallback successCallback,
+        //         optional ErrorCallback? errorCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::shared_ptr<Message> message = JSMessage::getPrivateObject(context,
+                validator.toJSValueRef(0));
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) MessageBodyCallbackData(g_ctx);
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        callback->setMessage(message);
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        priv->loadMessageBody(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Cannot load message body");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageService::loadMessageAttachment(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    MessageAttachmentCallbackData *callback = NULL;
+    try {
+        MessageService* priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                MESSAGING_FUNCTION_API_LOAD_MESSAGE_ATTACHMENT);
+        // void loadMessageAttachment(MessageAttachment attachment,
+        //         MessageAttachmentSuccessCallback successCallback,
+        //         optional ErrorCallback? errorCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSValueRef jsMsgAttachment = validator.toJSValueRef(0);
+        std::shared_ptr<MessageAttachment> attachment =
+                JSMessageAttachment::getPrivateObject(context, jsMsgAttachment);
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) MessageAttachmentCallbackData(g_ctx);
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        callback->setMessageAttachment(attachment);
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        priv->loadMessageAttachment(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Cannot load message attachment");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageService::sync(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    SyncCallbackData *callback = NULL;
+    try {
+        MessageService* priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                MESSAGING_FUNCTION_API_SYNC);
+        // long sync(optional SuccessCallback? successCallback,
+        //           optional ErrorCallback? errorCallback,
+        //           optional unsigned long? limit);
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) SyncCallbackData(g_ctx);
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        callback->setSuccessCallback(validator.toFunction(0, true));
+        callback->setErrorCallback(validator.toFunction(1, true));
+        // if limit is not provided or is null
+        // default value is used in MessageService
+        if (!validator.isOmitted(2) && !validator.isNull(2)) {
+            callback->setLimit(validator.toULong(2));
+        }
+
+        long op_id = priv->sync(callback);
+        return JSUtil::toJSValueRef(context, op_id);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Cannot sync with external mail server");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSMessageService::syncFolder(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    SyncFolderCallbackData *callback = NULL;
+    try {
+        MessageService* priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                MESSAGING_FUNCTION_API_SYNC_FOLDER);
+        // long syncFolder(MessageFolder folder,
+        //         optional SuccessCallback? successCallback,
+        //         optional ErrorCallback? errorCallback,
+        //         optional unsigned long? limit);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::shared_ptr<MessageFolder> messageFolder =
+                JSMessageFolder::getPrivateObject(context, validator.toJSValueRef(0));
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) SyncFolderCallbackData(g_ctx);
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        callback->setMessageFolder(messageFolder);
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        // if limit is not provided or is null
+        // default value is used in MessageService
+        if (!validator.isOmitted(3) && !validator.isNull(3)) {
+            callback->setLimit(validator.toULong(3));
+        }
+
+        long op_id = priv->syncFolder(callback);
+        return JSUtil::toJSValueRef(context, op_id);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Cannot sync folder with external server");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSMessageService::stopSync(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        MessageService* priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv,
+                MESSAGING_FUNCTION_API_STOP_SYNC);
+
+        // void stopSync(long opId);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        long opId = validator.toLong(0);
+
+        priv->stopSync(opId);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        Common::UnknownException err("Cannot stop sync with external server");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+} //Messaging
+} //DeviceAPI
+
diff --git a/src/Messaging/JSMessageService.h b/src/Messaging/JSMessageService.h
new file mode 100755 (executable)
index 0000000..d0c091d
--- /dev/null
@@ -0,0 +1,141 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_MESSAGE_SERVICE_H__
+#define __TIZEN_JS_MESSAGE_SERVICE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "MessageService.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class JSMessageService
+{
+public :
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static MessageService* getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static JSObjectRef createJSObject(JSContextRef context,
+            MessageService* priv);
+
+private :
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getMsgStorage(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef sendMessage(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef loadMessageBody(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef loadMessageAttachment(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef sync(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef syncFolder(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef stopSync(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSClassRef m_jsClassRef;
+
+}; //JSMessageService
+
+} //Messaging
+} //DeviceAPI
+
+#endif //__TIZEN_JS_MESSAGE_SERVICE_H__
+
diff --git a/src/Messaging/JSMessageStorage.cpp b/src/Messaging/JSMessageStorage.cpp
new file mode 100644 (file)
index 0000000..1ee110b
--- /dev/null
@@ -0,0 +1,882 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+
+#include <GlobalContextManager.h>
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <Logger.h>
+#include <PlatformException.h>
+#include <JSAttributeFilter.h>
+#include <JSSortMode.h>
+#include <JSUtil.h>
+#include <vector>
+#include <TimeTracer.h>
+
+
+#include "JSMessage.h"
+#include "JSMessageConversation.h"
+#include "Message.h"
+#include "MessageCallbackUserData.h"
+#include "JSMessageStorage.h"
+#include "MessagesChangeCallback.h"
+#include "ConversationsChangeCallback.h"
+#include "FoldersChangeCallback.h"
+#include "AbstractFilter.h"
+
+#include "plugin_config_impl.h"
+#include "MessagesCallbackUserData.h"
+#include "FindMsgCallbackUserData.h"
+#include "ConversationCallbackData.h"
+
+using namespace std;
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+const char* MESSAGE_STORAGE = "MessageStorage";
+}
+
+JSClassRef JSMessageStorage::m_jsClassRef = NULL;
+
+JSClassDefinition JSMessageStorage::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    MESSAGE_STORAGE,
+    NULL,
+    NULL,
+    JSMessageStorage::m_function,
+    JSMessageStorage::initialize,
+    JSMessageStorage::finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+JSStaticFunction JSMessageStorage::m_function[] = {
+    { MESSAGING_FUNCTION_API_ADD_DRAFT_MESSAGE, JSMessageStorage::addDraftMessage, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_FIND_MESSAGES, JSMessageStorage::findMessages, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_REMOVE_MESSAGES, JSMessageStorage::removeMessages, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_UPDATE_MESSAGES, JSMessageStorage::updateMessages, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_FIND_CONVERSATIONS, JSMessageStorage::findConversations, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_REMOVE_CONVERSATIONS, JSMessageStorage::removeConversations, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_FIND_FOLDERS, JSMessageStorage::findFolders, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_ADD_MESSAGES_CHANGE_LISTNER, JSMessageStorage::addMessagesChangeListener, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_ADD_CONVERSATIONS_CHANGE_LISTNER, JSMessageStorage::addConversationsChangeListener, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_ADD_FOLDERS_CHANGE_LISTNER, JSMessageStorage::addFoldersChangeListener, kJSPropertyAttributeDontDelete },
+    { MESSAGING_FUNCTION_API_REMOVE_CHANGE_LISTENER, JSMessageStorage::removeChangeListener, kJSPropertyAttributeDontDelete },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSMessageStorage::getClassRef()
+{
+    LOGD("Entered");
+    if (!m_jsClassRef)
+    {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+std::shared_ptr<MessageStorage> JSMessageStorage::getPrivateObject(
+        JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw Common::TypeMismatchException("Object type is not MessageStorage");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    MessageStorageHolder* priv = static_cast<MessageStorageHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw Common::UnknownException("Private data holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw Common::UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSMessageStorage::setPrivateObject(JSObjectRef object,
+        std::shared_ptr<MessageStorage> data)
+{
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw Common::UnknownException("NULL private data given");
+    }
+    MessageStorageHolder* priv = static_cast<MessageStorageHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    } else {
+        priv = new(std::nothrow) MessageStorageHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw Common::UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in MessageStorage");
+            throw Common::UnknownException(
+                    "Failed to set MessageStorage private data");
+        }
+    }
+}
+
+JSObjectRef JSMessageStorage::makeJSObject(JSContextRef context,
+    std::shared_ptr<MessageStorage> ptr)
+{
+    LOGD("Entered");
+    if (!ptr) {
+        LOGE("Private data is null");
+        throw Common::UnknownException("Private object is NULL");
+    }
+
+    MessageStorageHolder* priv = new(std::nothrow) MessageStorageHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory for MessageStorageHolder");
+        throw Common::UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = ptr;
+
+    JSObjectRef jsObject = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    if (!jsObject) {
+        LOGE("Object creation failed");
+        throw Common::UnknownException("Object creation failed");
+    }
+
+    return jsObject;
+}
+
+void JSMessageStorage::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSMessageStorage::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    MessageStorageHolder* priv =
+            static_cast<MessageStorageHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSMessageStorage::addDraftMessage(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    MessageCallbackUserData* callback = NULL;
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_ADD_DRAFT_MESSAGE);
+
+        // void addDraftMessage(Message message,
+        //         optional SuccessCallback? successCallback,
+        //.        optional ErrorCallback? errorCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::shared_ptr<Message> message = JSMessage::getPrivateObject(context,
+                validator.toJSValueRef(0));
+
+        JSContextRef g_ctx = GlobalContextManager::getInstance()
+                ->getGlobalContext(context);
+        callback = new(std::nothrow) MessageCallbackUserData(g_ctx);
+        LOGD("created new callback: %p", callback);
+
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        callback->setMessage(message);
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        priv->addDraftMessage(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error, cannot add draft message");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageStorage::findMessages(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    FindMsgCallbackUserData* callback = NULL;
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_FIND_MESSAGES);
+        /*
+         * void findMessages(AbstractFilter filter,
+         *          MessageArraySuccessCallback successCallback,
+         *          optional ErrorCallback? errorCallback,
+         *          optional SortMode? sort,
+         *          optional unsigned long? limit,
+         *          optional unsigned long? offset);
+         */
+        JSContextRef g_ctx = GlobalContextManager::getInstance()
+                ->getGlobalContext(context);
+        callback = new FindMsgCallbackUserData(g_ctx);
+        LOGD("created new callback: %p", callback);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        DeviceAPI::Tizen::AbstractFilterPtr filter = Tizen::AbstractFilter::
+                getPrivateObject(context, validator.toJSValueRef(0));
+
+        if (!filter) {
+            LOGE("Wrong filter");
+            throw Common::TypeMismatchException("Invalid filter");
+        }
+        callback->setFilter(filter);
+
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        JSObjectRef sortmodeobj = validator.toObject(3, true);
+        if(sortmodeobj != NULL){
+            DeviceAPI::Tizen::SortModePtr sortMode =
+                    Tizen::JSSortMode::getPrivateObject(context, sortmodeobj);
+            LOGD("sort mode is set");
+            callback->setSortMode(sortMode);
+        }
+
+        callback->setLimit(validator.toULong(4, true, 0));
+        callback->setOffset(validator.toULong(5, true, 0));
+        priv->findMessages(callback);
+    }
+    catch (const WrtDeviceApis::Commons::Exception& exc) {
+        LOGE("Wrong sort/filer mode: %s", exc.GetMessage().c_str());
+        Common::TypeMismatchException err(exc.GetMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }catch (...) {
+        Common::UnknownException err("Unknown error, cannot find messages");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageStorage::removeMessages(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    MessagesCallbackUserData* callback = NULL;
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_REMOVE_MESSAGES);
+        /**
+         * void removeMessages(Message[] messages,
+         *          optional SuccessCallback? successCallback,
+         *          optional ErrorCallback? errorCallback);
+         */
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::vector<JSValueRef> messages = validator.toJSValueRefVector(0);
+        JSContextRef g_ctx = GlobalContextManager::getInstance()
+                ->getGlobalContext(context);
+        callback = new MessagesCallbackUserData(g_ctx);
+        LOGD("created new callback: %p", callback);
+
+        callback->addMessages(context, messages);
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        priv->removeMessages(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error, cannot remove messages");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageStorage::updateMessages(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    MessagesCallbackUserData* callback = NULL;
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_UPDATE_MESSAGES);
+        /**
+         * void updateMessages (Message[] messages,
+         *          optional SuccessCallback? successCallback,
+         *          optional ErrorCallback? errorCallback)
+         */
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::vector<JSValueRef> messages = validator.toJSValueRefVector(0);
+        JSContextRef g_ctx = GlobalContextManager::getInstance()
+                ->getGlobalContext(context);
+        callback = new MessagesCallbackUserData(g_ctx);
+        LOGD("created new callback: %p", callback);
+
+        callback->addMessages(context, messages);
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        priv->updateMessages(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error, cannot update messages");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageStorage::findConversations(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ConversationCallbackData* callback = NULL;
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_FIND_CONVERSATIONS);
+        // void findConversations (AbstractFilter filter,
+        //         MessageConversationArraySuccessCallback successCallback,
+        //         optional ErrorCallback? errorCallback,
+        //         optional SortMode? sort,
+        //         optional unsigned long? limit,
+        //         optional unsigned long? offset)
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        DeviceAPI::Tizen::AbstractFilterPtr filter = Tizen::AbstractFilter::
+                getPrivateObject(context, validator.toJSValueRef(0));
+        if (!filter) {
+            LOGE("Wrong filter");
+            throw Common::TypeMismatchException("Invalid filter");
+        }
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new ConversationCallbackData(g_ctx);
+        LOGD("created new callback: %p", callback);
+
+        callback->setFilter(filter);
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        JSObjectRef sortmodeobj = validator.toObject(3, true);
+        if(sortmodeobj != NULL){
+            DeviceAPI::Tizen::SortModePtr sortMode =
+                    Tizen::JSSortMode::getPrivateObject(context, sortmodeobj);
+            if (!sortMode) {
+                LOGE("Wrong sort mode");
+                throw Common::TypeMismatchException("Invalid sort mode");
+            }
+            LOGD("sort mode is set");
+            callback->setSortMode(sortMode);
+        }
+
+        callback->setLimit(validator.toULong(4, true, 0));
+        callback->setOffset(validator.toULong(5, true, 0));
+
+        priv->findConversations(callback);
+    }
+    catch (const WrtDeviceApis::Commons::Exception& exc) {
+        LOGE("Wrong sort/filer mode: %s", exc.GetMessage().c_str());
+        Common::TypeMismatchException err(exc.GetMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Cannot find conversations");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageStorage::removeConversations(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ConversationCallbackData* callback = NULL;
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context,
+                thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_REMOVE_CONVERSATIONS);
+        // void removeConversation(MessageConversation[] conversations,
+        //         optional SuccessCallback? successCallback,
+        //         optional ErrorCallback? errorCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::vector<JSValueRef> conversations = validator.toJSValueRefVector(0);
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new ConversationCallbackData(g_ctx);
+        LOGD("created new callback: %p", callback);
+
+        callback->addConversations(context, conversations);
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        priv->removeConversations(callback);
+    } catch (const BasePlatformException& err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("Unknown error while removing conversation");
+        delete callback;
+        callback = NULL;
+        Common::UnknownException err("Cannot remove conversations");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageStorage::findFolders(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    FoldersCallbackData* callback = NULL;
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_FIND_FOLDERS);
+        // void findFolders(AbstractFilter filter,
+        //         MessageFolderArraySuccessCallback successCallback,
+        //         optional ErrorCallback? errorCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        DeviceAPI::Tizen::AbstractFilterPtr filter = Tizen::AbstractFilter::
+                getPrivateObject(context, validator.toJSValueRef(0));
+        if (!filter) {
+            LOGE("Wrong filter");
+            throw Common::TypeMismatchException("Invalid filter");
+        }
+
+        JSContextRef global_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        callback = new FoldersCallbackData(global_ctx);
+        LOGD("created new callback: %p", callback);
+
+        callback->setFilter(filter);
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        priv->findFolders(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Cannot find folders");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMessageStorage::addMessagesChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_ADD_MESSAGES_CHANGE_LISTNER);
+        // long addMessagesChangeListener (
+        //         MessagesChangeCallback messagesChangeCallback,
+        //         optional AbstractFilter filter)
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef js_callbacks_obj = validator.toCallbackObject(0, false,
+                MESSAGESADDED, MESSAGESUPDATED, MESSAGESREMOVED, NULL);
+
+        JSObjectRef on_added_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, MESSAGESADDED);
+        JSObjectRef on_updateded_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, MESSAGESUPDATED);
+        JSObjectRef on_removed_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, MESSAGESREMOVED);
+
+
+        JSContextRef global_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        auto callback = std::make_shared<MessagesChangeCallback>(
+                global_ctx,
+                on_added_obj,
+                on_updateded_obj,
+                on_removed_obj,
+                priv->getMsgServiceId(),
+                priv->getMsgServiceType());
+
+        JSObjectRef filterobj = validator.toObject(1, true);
+        if (filterobj != NULL) {
+            DeviceAPI::Tizen::AbstractFilterPtr filter = Tizen::AbstractFilter::
+                    getPrivateObject(context, validator.toJSValueRef(1));
+            if (!filter) {
+                LOGE("Wrong filter");
+                throw Common::TypeMismatchException("Invalid filter");
+            }
+            LOGD("filter is set");
+            callback->setFilter(filter);
+        }
+        return JSValueMakeNumber(context, priv->addMessagesChangeListener(callback));
+    }
+    catch (const WrtDeviceApis::Commons::Exception& exc) {
+        LOGE("Wrong sort/filer mode: %s", exc.GetMessage().c_str());
+        Common::TypeMismatchException err(exc.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Cannot add listener for messages");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSMessageStorage::addConversationsChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context,
+                thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_ADD_CONVERSATIONS_CHANGE_LISTNER);
+        // long addConversationsChangeListener(
+        //         MessageConversationsChangeCallback conversationsChangeCallback,
+        //         optional AbstractFilter? filter)
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef js_callbacks_obj = validator.toCallbackObject(0,false,
+                CONVERSATIONSADDED, CONVERSATIONSUPDATED, CONVERSATIONSREMOVED,
+                NULL);
+
+        JSObjectRef on_added_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, CONVERSATIONSADDED);
+        JSObjectRef on_updateded_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, CONVERSATIONSUPDATED);
+        JSObjectRef on_removed_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, CONVERSATIONSREMOVED);
+
+        JSContextRef global_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        auto callback = std::make_shared<ConversationsChangeCallback>(
+                global_ctx,
+                on_added_obj,
+                on_updateded_obj,
+                on_removed_obj,
+                priv->getMsgServiceId(),
+                priv->getMsgServiceType());
+
+        JSObjectRef filterobj = validator.toObject(1, true);
+        if (filterobj != NULL) {
+            DeviceAPI::Tizen::AbstractFilterPtr filter = Tizen::AbstractFilter::
+                    getPrivateObject(context, validator.toJSValueRef(1));
+            if (!filter) {
+                LOGE("Wrong filter");
+                throw Common::TypeMismatchException("Invalid filter");
+            }
+            LOGD("filter is set");
+            callback->setFilter(filter);
+        }
+
+        return JSValueMakeNumber(context,
+                priv->addConversationsChangeListener(callback));
+    }
+    catch (const WrtDeviceApis::Commons::Exception& exc) {
+        LOGE("Wrong filer mode: %s", exc.GetMessage().c_str());
+        Common::TypeMismatchException err(exc.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Cannot add listener for conversations");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+
+JSValueRef JSMessageStorage::addFoldersChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context,
+                thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_ADD_FOLDERS_CHANGE_LISTNER);
+        // long addFoldersChangeListener(
+        //         MessageFoldersChangeCallback foldersChangeCallback,
+        //         optional AbstractFilter? filter);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef js_callbacks_obj = validator.toCallbackObject(0, false,
+                FOLDERSADDED, FOLDERSUPDATED, FOLDERSREMOVED, NULL);
+
+        JSObjectRef on_added_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, FOLDERSADDED);
+        JSObjectRef on_updateded_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, FOLDERSUPDATED);
+        JSObjectRef on_removed_obj = getFunctionFromCallbackObj(context,
+                js_callbacks_obj, FOLDERSREMOVED);
+
+        JSContextRef global_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        auto callback = std::make_shared<FoldersChangeCallback>(
+                global_ctx,
+                on_added_obj,
+                on_updateded_obj,
+                on_removed_obj,
+                priv->getMsgServiceId(),
+                priv->getMsgServiceType());
+
+        JSObjectRef filterobj = validator.toObject(1, true);
+        if (filterobj != NULL) {
+            DeviceAPI::Tizen::AbstractFilterPtr filter = Tizen::AbstractFilter::
+                    getPrivateObject(context, validator.toJSValueRef(1));
+            if (!filter) {
+                LOGE("Wrong filter");
+                throw Common::TypeMismatchException("Invalid filter");
+            }
+            LOGD("filter is set");
+            callback->setFilter(filter);
+        }
+
+        return JSValueMakeNumber(context, priv->addFoldersChangeListener(callback));
+    }
+    catch (const WrtDeviceApis::Commons::Exception& exc) {
+        LOGE("Wrong filer mode: %s", exc.GetMessage().c_str());
+        Common::TypeMismatchException err(exc.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Cannot add listener for folders");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSMessageStorage::removeChangeListener(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        std::shared_ptr<MessageStorage> priv = getPrivateObject(context,
+                thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+                MESSAGING_FUNCTION_API_REMOVE_CHANGE_LISTENER);
+        // void removeChangeListener(long watchId);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        long watchId = validator.toLong(0);
+
+        priv->removeChangeListener(context, watchId);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Cannot add listener for folders");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSObjectRef JSMessageStorage::getFunctionFromCallbackObj(JSContextRef context,
+        JSObjectRef obj,
+        const char* name)
+{
+    JSObjectRef function_obj = NULL;
+    JSStringRef propertyName = JSStringCreateWithUTF8CString(name);
+    bool has = JSObjectHasProperty(context, obj, propertyName);
+    JSStringRelease(propertyName);
+    if (has) {
+        JSValueRef value = JSUtil::getProperty(context, obj, name);
+        function_obj = JSUtil::JSValueToObject(context, value);
+    }
+    return function_obj;
+}
+
+} //Messaging
+} //DeviceAPI
+
diff --git a/src/Messaging/JSMessageStorage.h b/src/Messaging/JSMessageStorage.h
new file mode 100755 (executable)
index 0000000..c841e08
--- /dev/null
@@ -0,0 +1,160 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_MESSAGE_STORAGE_H__
+#define __TIZEN_JS_MESSAGE_STORAGE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include <memory>
+
+#include "MessageStorage.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class JSMessageStorage
+{
+public:
+// @struct JSClassDefinition
+// @abstract This structure contains properties and callbacks that define a type of object. All fields other than the version field are optional. Any pointer may be NULL.
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static std::shared_ptr<MessageStorage> getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            std::shared_ptr<MessageStorage> data);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            std::shared_ptr<MessageStorage> ptr);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef addDraftMessage(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef findMessages(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef findConversations(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeConversations(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef findFolders(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+     static JSValueRef removeMessages(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+     static JSValueRef updateMessages(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addMessagesChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addConversationsChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addFoldersChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSClassRef m_jsClassRef;
+
+    static JSObjectRef getFunctionFromCallbackObj(JSContextRef context,
+            JSObjectRef obj,
+            const char* name);
+};
+
+} //Messaging
+} //DeviceAPI
+
+#endif //__TIZEN_JS_MESSAGE_STORAGE_H__
+
diff --git a/src/Messaging/JSMessagingManager.cpp b/src/Messaging/JSMessagingManager.cpp
new file mode 100755 (executable)
index 0000000..4422bce
--- /dev/null
@@ -0,0 +1,207 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string.h>
+
+#include <JSWebAPIErrorFactory.h>
+
+#include <GlobalContextManager.h>
+#include <ArgumentValidator.h>
+#include <Export.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <system_info.h>
+
+#include "JSMessagingManager.h"
+#include "MessagingManager.h"
+#include "MessagingUtil.h"
+
+#include "plugin_config_impl.h"
+
+using namespace std;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+const char* MESSAGING = "Messaging";
+}
+
+JSClassRef JSMessagingManager::m_jsClassRef = NULL;
+
+JSClassDefinition JSMessagingManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    MESSAGING,
+    NULL,
+    NULL,
+    JSMessagingManager::m_function,
+    JSMessagingManager::initialize,
+    JSMessagingManager::finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL,
+    NULL,
+    NULL, //hasInstance,
+    NULL
+};
+
+JSStaticFunction JSMessagingManager::m_function[] = {
+        { MESSAGING_FUNCTION_API_GET_MESSAGE_SERVICE,
+                JSMessagingManager::getMessageServices, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSMessagingManager::getClassInfo() {
+    LOGD("Entered");
+    return &(m_classInfo);
+}
+
+const JSClassRef DLL_EXPORT JSMessagingManager::getClassRef() {
+    LOGD("Entered");
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSMessagingManager::initialize(JSContextRef context,
+        JSObjectRef object)
+{
+    LOGD("Entered");
+    JSObjectSetPrivate(object, static_cast<void*>(&(MessagingManager::getInstance())));
+}
+
+void JSMessagingManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    JSObjectSetPrivate(object, NULL);
+}
+
+JSValueRef JSMessagingManager::getMessageServices(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    MessageServiceCallbackData *callback = NULL;
+    bool isSupported = false;
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        MessageType msgTag = MessagingUtil::stringToMessageType(validator.toString(0));
+        LOGD("Messaging Service Type: %d", msgTag);
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+        callback = new(std::nothrow) MessageServiceCallbackData(g_ctx);
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setMessageType(msgTag);
+
+        //TODO for error formating should be use function from SystemInfo utils class
+        int error = SYSTEM_INFO_ERROR_NONE;
+        auto getSystemInfoErrorLog = [error](std::string hint = "system_info_get_platform_bool()")->std::string{
+            std::stringstream ss;
+            ss << "Failed " << hint << " : ";
+            switch (error) {
+                case SYSTEM_INFO_ERROR_INVALID_PARAMETER:
+                    ss << "Cannot find the key in the model config file";
+                    break;
+                case SYSTEM_INFO_ERROR_IO_ERROR:
+                    ss << "An input/output error occurred while reading the value from the model config file";
+                    break;
+                case SYSTEM_INFO_ERROR_PERMISSION_DENIED:
+                    ss << "No permission to use the API";
+                    break;
+                default:
+                    ss << "Unknown Error";
+            }
+            ss << ", " << error;
+            return ss.str();
+        };
+
+        MessageType msgType = callback->getMessageType();
+        switch (msgType) {
+            case MessageType::SMS:
+                error = system_info_get_platform_bool("tizen.org/feature/network.telephony", &isSupported);
+                if (SYSTEM_INFO_ERROR_NONE != error) {
+                    LOGE("%s",getSystemInfoErrorLog().c_str());
+                    //TODO: need to throw unknown error
+                }
+                LoggerD("isSMSSupported " << isSupported);
+
+                if (isSupported == false) {
+                    LoggerE("SMS is not supported");
+                    throw DeviceAPI::Common::NotSupportedException("Unsupported message type (SMS)");
+                }
+                break;
+            case MessageType::MMS:
+                error = system_info_get_platform_bool("tizen.org/feature/network.telephony.mms", &isSupported);
+                if (SYSTEM_INFO_ERROR_NONE != error) {
+                    LoggerE("Can't know whether mms is supported or not");
+                    LOGE("%s",getSystemInfoErrorLog().c_str());
+                    //TODO: need to throw unknown error
+                }
+                LoggerD("isSupported " << isSupported);
+
+                if (isSupported == false) {
+                    LoggerE("mms is not supported");
+                    throw DeviceAPI::Common::NotSupportedException("Unsupported message type (MMS)");
+                }
+                break;
+            case MessageType::EMAIL:
+                LoggerD("Email type");
+                break;
+            default:
+                LoggerE("This type is not supported");
+                throw DeviceAPI::Common::TypeMismatchException("Unsupported message type");
+        }
+        MessagingManager::getInstance().getMessageServices(callback);
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        Common::UnknownException err("Unknown error, cannot get message services");
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // Messaging
+} // DeviceAPI
+
diff --git a/src/Messaging/JSMessagingManager.h b/src/Messaging/JSMessagingManager.h
new file mode 100755 (executable)
index 0000000..ad6850b
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_MESSAGING_MANAGER_H__
+#define __TIZEN_JS_MESSAGING_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class JSMessagingManager
+{
+public:
+// @struct JSClassDefinition
+// @abstract This structure contains properties and callbacks that define a type of object.
+//           All fields other than the version field are optional. Any pointer may be NULL.
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+    * The callback invoked when determining whether an object has a property.
+    */
+    static bool hasProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName);
+
+    static JSValueRef getMessageServices(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //Messaging
+} //DeviceAPI
+
+#endif //__TIZEN_JS_MESSAGING_MANAGER_H__
+
diff --git a/src/Messaging/Message.cpp b/src/Messaging/Message.cpp
new file mode 100644 (file)
index 0000000..f34fdc3
--- /dev/null
@@ -0,0 +1,1938 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Message.cpp
+ */
+
+#include "Message.h"
+#include "MessageSMS.h"
+#include "MessageMMS.h"
+#include "MessageEmail.h"
+#include "MessagingUtil.h"
+#include "FilesystemExternalUtils.h"
+#include "FilesystemUtils.h"
+#include "Ecore_File.h"
+#include "JSMessage.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <time.h>
+#include <sys/stat.h>
+#include <sstream>
+
+namespace DeviceAPI {
+
+using namespace Tizen;
+
+namespace Messaging {
+
+// *** constructor
+Message::Message():
+    m_id(-1), m_id_set(false), m_conversation_id(-1),
+    m_conversation_id_set(false), m_folder_id(-1), m_folder_id_set(false),
+    m_type(UNDEFINED), m_timestamp_set(false), m_from_set(false),
+    m_body(new(std::nothrow) MessageBody()),
+    m_service_id(0), m_is_read(false), m_has_attachment(false),
+    m_high_priority(false), m_in_response(-1), m_in_response_set(false),
+    m_service_id_set(false), m_status(STATUS_UNDEFINED),
+    m_sim_index(TAPI_NETWORK_DEFAULT_DATA_SUBS_UNKNOWN)
+{
+    LOGD("Message constructor (%p)", this);
+}
+
+Message::~Message()
+{
+    LOGD("Message destructor (%p)", this);
+}
+
+// *** attribute getters
+int Message::getId() const
+{
+    return m_id;
+}
+
+int Message::getConversationId() const
+{
+    return m_conversation_id;
+}
+
+int Message::getFolderId() const
+{
+    // TODO: folderId is supported different way in SMS/MMS and email
+    return m_folder_id;
+}
+
+MessageType Message::getType() const
+{
+    return m_type;
+}
+
+time_t Message::getTimestamp() const
+{
+    return m_timestamp;
+}
+
+std::string Message::getFrom() const
+{
+    return m_from;
+}
+
+std::vector<std::string> Message::getTO() const
+{
+    return m_to;
+}
+
+JSObjectRef Message::getJSTO(JSContextRef global_ctx)
+{
+    return m_to.getJSArray(global_ctx);
+}
+
+std::vector<std::string> Message::getCC() const
+{
+    return m_cc;
+}
+
+JSObjectRef Message::getJSCC(JSContextRef global_ctx)
+{
+    return m_cc.getJSArray(global_ctx);
+}
+
+std::vector<std::string> Message::getBCC() const
+{
+    return m_bcc;
+}
+
+JSObjectRef Message::getJSBCC(JSContextRef global_ctx)
+{
+    return m_bcc.getJSArray(global_ctx);
+}
+
+std::shared_ptr<MessageBody> Message::getBody() const
+{
+    return m_body;
+}
+
+bool Message::getIsRead() const
+{
+    return m_is_read;
+}
+
+bool Message::getHasAttachment() const
+{
+    // This function should be reimplemented for MMS and email
+    return m_has_attachment;
+}
+
+bool Message::getIsHighPriority() const
+{
+    return m_high_priority;
+}
+
+std::string Message::getSubject() const
+{
+    return m_subject;
+}
+
+int Message::getInResponseTo() const
+{
+    return m_in_response;
+}
+
+MessageStatus Message::getMessageStatus() const
+{
+    return m_status;
+}
+
+AttachmentPtrVector Message::getMessageAttachments() const
+{
+    return m_attachments;
+}
+
+JSObjectRef Message::getJSMessageAttachments(JSContextRef global_ctx)
+{
+    return m_attachments.getJSArray(global_ctx);
+}
+
+int Message::getServiceId() const
+{
+    return m_service_id;
+}
+
+TelNetworkDefaultDataSubs_t Message::getSimIndex() const
+{
+    return m_sim_index;
+}
+
+// *** attributes setters
+void Message::setId(int id)
+{
+    m_id = id;
+    m_id_set = true;
+    m_body->setMessageId(m_id);
+}
+
+void Message::setConversationId(int id)
+{
+    m_conversation_id = id;
+    m_conversation_id_set = true;
+}
+
+void Message::setFolderId(int id)
+{
+    m_folder_id = id;
+    m_folder_id_set = true;
+}
+
+// type setting not allowed - no setter for type
+
+void Message::setTimeStamp(time_t timestamp)
+{
+    m_timestamp = timestamp;
+    m_timestamp_set = true;
+}
+
+void Message::setFrom(std::string from)
+{
+    m_from = from;
+    m_from_set = true;
+}
+
+void Message::setTO(std::vector<std::string> &to)
+{
+    // Recipient's format validation should be done by Core API service
+    m_to = to;
+
+    if(m_to.empty()) {
+        LOGD("Recipient's list cleared");
+        return;
+    }
+}
+
+void Message::setCC(std::vector<std::string> &cc)
+{
+    // implementation (address/number format checking) is message specific
+}
+
+void Message::setBCC(std::vector<std::string> &bcc)
+{
+    // implementation (address/number format checking) is message specific
+}
+
+void Message::setBody(std::shared_ptr<MessageBody>& body)
+{
+    // while replacing message body old body should have some invalid id mark
+    m_body->setMessageId(-1);
+    m_body = body;
+    if(m_id_set) {
+        m_body->setMessageId(m_id);
+    }
+}
+
+void Message::setIsRead(bool read)
+{
+    m_is_read = read;
+}
+
+// has attachment can't be set explicity -> no setter for this flag
+
+void Message::setIsHighPriority(bool highpriority)
+{
+    // High priority field is used only in MessageEmail
+    m_high_priority = highpriority;
+}
+
+void Message::setSubject(std::string subject)
+{
+    // Subject is used only in MessageEmail and MessageMMS
+}
+
+void Message::setInResponseTo(int inresp)
+{
+    m_in_response = inresp;
+    m_in_response_set = true;
+}
+
+void Message::setMessageStatus(MessageStatus status)
+{
+    m_status = status;
+}
+
+void Message::setMessageAttachments(AttachmentPtrVector &attachments)
+{
+    // implementation provided only for MMS and email
+}
+
+
+void Message::setServiceId(int service_id)
+{
+    m_service_id = service_id;
+    m_service_id_set = true;
+}
+
+void Message::setSimIndex(TelNetworkDefaultDataSubs_t sim_index)
+{
+    m_sim_index = sim_index;
+}
+
+// ***  support for optional, nullable (at JS layer) attibutes
+bool Message::is_id_set() const
+{
+    return m_id_set;
+}
+
+bool Message::is_conversation_id_set() const
+{
+    return m_conversation_id_set;
+}
+
+bool Message::is_folder_id_set() const
+{
+    return m_folder_id_set;
+}
+
+bool Message::is_timestamp_set() const
+{
+    return m_timestamp_set;
+}
+
+bool Message::is_from_set() const
+{
+    return m_from_set;
+}
+
+bool Message::is_in_response_set() const
+{
+    return m_in_response_set;
+}
+
+bool Message::is_service_is_set() const
+{
+    return m_service_id_set;
+}
+
+std::string Message::convertEmailRecipients(const std::vector<std::string> &recipients)
+{
+    std::string address = "";
+    unsigned size = recipients.size();
+    for (unsigned i=0; i<size; ++i)
+    {
+        address += "<"+recipients[i]+">; ";
+    }
+
+    return address;
+}
+
+std::string saveToTempFile(const std::string &data)
+{
+    char buf[] = "XXXXXX";
+    int res = 0;
+
+    mode_t mask = umask(S_IWGRP | S_IWOTH);
+    res = mkstemp(buf);   //Just generate unique name
+
+    std::string fileName = std::string("/tmp/") + buf;
+
+    mode_t old_mask = umask(mask);
+    FILE *file = fopen(fileName.c_str(), "w");
+    umask(old_mask);
+
+    if (NULL == file) {
+        LOGE("Failed to create file");
+        throw Common::UnknownException("Failed to create file");
+    }
+    if (fprintf(file, "%s", data.c_str()) < 0) {
+        LOGE("Failed to write data into file");
+        throw Common::UnknownException("Failed to write data into file");
+    }
+    fflush(file);
+    fclose(file);
+    return fileName;
+}
+
+std::string copyFileToTemp(const std::string& sourcePath)
+{
+    LOGD("Entered");
+    char buf[] = "XXXXXX";
+    std::string dirPath, fileName, attPath, tmpPath;
+
+    mode_t mask = umask(S_IWGRP | S_IWOTH);
+    int err = mkstemp(buf);
+    if (-1 == err) {
+        LOGW("Failed to create unique filename");
+    }
+
+    umask(mask);
+    dirPath = "/tmp/" + std::string(buf);
+
+    if ( sourcePath[0] != '/' ) {
+        attPath = Filesystem::External::fromVirtualPath(sourcePath);
+    } else { // Assuming that the path is a real path
+        attPath = sourcePath;
+    }
+
+    // Looking for the last occurrence of slash in source path
+    std::size_t slashPos;
+    if ((slashPos = attPath.find_last_of('/')) == std::string::npos) {
+        LOGE("Error while copying file to temp: the source path is invalid.");
+        throw Common::UnknownException(
+                "Error while copying file to temp: the source path is invalid.");
+    }
+
+    fileName = attPath.substr(slashPos + 1);
+    tmpPath = dirPath + "/" + fileName;
+
+    LOGD("attPath: %s, tmpPath: %s", attPath.c_str(), tmpPath.c_str());
+    if(EINA_TRUE != ecore_file_mkdir(dirPath.c_str())) {
+        LOGE("Unknown error while creating temp directory.");
+        throw Common::UnknownException("Unknown error while creating temp directory.");
+    }
+
+    if(EINA_TRUE != ecore_file_cp(attPath.c_str(), tmpPath.c_str())) {
+        LOGE("Unknown error while copying file to temp.");
+        throw Common::UnknownException("Unknown error while copying file to temp.");
+    }
+
+    return dirPath;
+}
+
+void removeDirFromTemp(const std::string& dirPath)
+{
+    if(EINA_TRUE != ecore_file_rmdir(dirPath.c_str())) {
+        LOGE("Unknown error while deleting temp directory.");
+        throw Common::UnknownException("Unknown error while deleting temp directory.");
+    }
+}
+
+email_mail_data_t* Message::convertPlatformEmail(std::shared_ptr<Message> message)
+{
+    if(EMAIL != message->getType()) {
+        LOGE("Invalid type");
+        throw Common::InvalidValuesException("Invalid type.");
+    }
+
+    email_mail_data_t *mail_data = NULL;
+
+    if(message->is_id_set()) {
+        int ret = email_get_mail_data(message->getId(), &mail_data);
+        if( EMAIL_ERROR_NONE != ret ) {
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_get_mail_data()").c_str());
+        }
+    } else {
+        mail_data = (email_mail_data_t*)malloc(
+                sizeof(email_mail_data_t));
+        memset(mail_data, 0x00, sizeof(email_mail_data_t));
+    }
+
+    if(!message->getFrom().empty()) {
+        std::string from = "<"+message->getFrom()+">";
+        mail_data->full_address_from = strdup(from.c_str());
+    }
+
+    if(!message->getTO().empty()) {
+        std::string to = Message::convertEmailRecipients(message->getTO());
+        mail_data->full_address_to = strdup(to.c_str());
+    }
+
+    if(!message->getCC().empty()) {
+        std::string cc = Message::convertEmailRecipients(message->getCC());
+        mail_data->full_address_cc = strdup(cc.c_str());
+    }
+
+    if(!message->getBCC().empty()) {
+        std::string bcc = Message::convertEmailRecipients(message->getBCC());
+        mail_data->full_address_bcc = strdup(bcc.c_str());
+    }
+
+    if(!message->getSubject().empty()) {
+        std::string subject = message->getSubject();
+        mail_data->subject = strdup(subject.c_str());
+    }
+
+    if(message->getBody()) {
+        std::shared_ptr<MessageBody> body;
+        body = message->getBody();
+        if(!body->getPlainBody().empty()) {
+            std::string body_file_path = saveToTempFile(body->getPlainBody());
+            mail_data->file_path_plain = strdup(body_file_path.c_str());
+            if(!mail_data->file_path_plain)
+            {
+                LOGE("Plain Body file is NULL.");
+                free(mail_data);
+                mail_data = NULL;
+                throw Common::UnknownException("Plain Body file is NULL.");
+            }
+        }
+
+        if(!body->getHtmlBody().empty()) {
+            std::string html_file_path = saveToTempFile(body->getHtmlBody());
+            mail_data->file_path_html = strdup(html_file_path.c_str());
+            if(!mail_data->file_path_html)
+            {
+                LOGE("Html Body file is NULL.");
+                free(mail_data);
+                mail_data = NULL;
+                throw Common::UnknownException("Html Body file is NULL.");
+            }
+        } else if(!body->getPlainBody().empty()) {
+            // check html data is exist if not exist copy plain body to html body
+            std::string html_file_path = saveToTempFile(body->getPlainBody());
+            mail_data->file_path_html = strdup(html_file_path.c_str());
+            if(!mail_data->file_path_html)
+            {
+                LOGE("Plain Body file is NULL.");
+                free(mail_data);
+                mail_data = NULL;
+                throw Common::UnknownException("Plain Body file is NULL.");
+            }
+        }
+    }
+
+    mail_data->flags_seen_field = message->getIsRead()?1:0;
+
+    if(message->getIsHighPriority()) {
+        mail_data->priority = EMAIL_MAIL_PRIORITY_HIGH;
+    } else {
+        mail_data->priority = EMAIL_MAIL_PRIORITY_NORMAL;
+    }
+
+    return mail_data;
+}
+
+void addSingleEmailAttachment(std::shared_ptr<Message> message,
+        std::shared_ptr<MessageAttachment> att, AttachmentType attType)
+{
+    std::string dirPath = copyFileToTemp(att->getFilePath());
+
+    email_attachment_data_t* tmp = new email_attachment_data_t();
+    tmp->attachment_name = strdup(att->getShortFileName().c_str());
+    tmp->attachment_path  = strdup(std::string(dirPath + "/"
+            + att->getShortFileName()).c_str());
+    tmp->save_status = 1;
+    tmp->inline_content_status = attType;
+
+    int id = message->getId();
+    int err = email_add_attachment(id, tmp);
+    if(EMAIL_ERROR_NONE != err) {
+        LOGE("%s", MessagingUtil::getEmailErrorMessage(err, "email_add_attachment()").c_str());
+        int ret = email_free_attachment_data(&tmp, 1);
+        if (EMAIL_ERROR_NONE != ret) {
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_attachment_data()").c_str());
+        }
+        LOGE("ret: %d", err);
+        MessagingUtil::throwEmailException(err, "email_add_attachment()");
+    }
+
+    att->setId(tmp->attachment_id);
+    att->setMessageId(id);
+    err = email_free_attachment_data(&tmp, 1);
+    if (EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_attachment_data()").c_str());
+    }
+
+    removeDirFromTemp(dirPath);
+}
+
+void Message::addEmailAttachments(std::shared_ptr<Message> message)
+{
+    LOGD("Entered");
+
+    int attachment_data_count = 0, error;
+    email_mail_data_t *mail = NULL;
+    email_attachment_data_t *attachment_data_list = NULL;
+    email_meeting_request_t *meeting_req = NULL;
+
+
+    AttachmentPtrVector attachments = message->getMessageAttachments();
+    AttachmentPtrVector inlineAttachments = message->getBody()->getInlineAttachments();
+    LOGD("Attachments size: %d", attachments.size());
+    LOGD("Inline attachments size: %d", inlineAttachments.size());
+    LOGD("Adding attachments for mail id = [%d]\n", message->getId());
+    for (auto it = attachments.begin(); it != attachments.end(); ++it) {
+        addSingleEmailAttachment(message, *it, AttachmentType::EXTERNAL);
+    }
+    for (auto it = inlineAttachments.begin(); it != inlineAttachments.end(); ++it) {
+        addSingleEmailAttachment(message, *it, AttachmentType::INLINE);
+    }
+
+    //Update of mail on server using function email_update_mail() is not possible.
+    //Attachment is updated only locally, so there is need to use workaround:
+    //1. add new mail with null attachments list
+    //2. add attachments to mail (locally)
+    //3. create new email with attachments and add it to server
+    //4. delete mail without attachments
+
+    //getting mail and attachments data
+    mail = Message::convertPlatformEmail(message);
+    error = email_get_attachment_data_list(mail->mail_id, &attachment_data_list, &attachment_data_count);
+    if (EMAIL_ERROR_NONE != error) {
+        int ret = email_free_mail_data(&mail, 1);
+        if(EMAIL_ERROR_NONE != ret){
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mail_data()").c_str());
+        }
+        ret = email_free_attachment_data(&attachment_data_list,attachment_data_count);
+        if(EMAIL_ERROR_NONE != ret){
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_attachment_data()").c_str());
+        }
+        LOGE("ret: %d", error);
+        MessagingUtil::throwEmailException(error, "email_get_attachment_data_list()");
+    }
+
+    //save mail without attachments id
+    int tmp_id = mail->mail_id;
+
+    //adding new mail with attachments
+    error = email_add_mail(mail, attachment_data_list, attachment_data_count, meeting_req, 0);
+    if (EMAIL_ERROR_NONE != error) {
+        int ret = email_free_mail_data(&mail, 1);
+        if(EMAIL_ERROR_NONE != ret){
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mail_data()").c_str());
+        }
+        ret = email_free_attachment_data(&attachment_data_list,attachment_data_count);
+        if(EMAIL_ERROR_NONE != ret){
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_attachment_data()").c_str());
+        }
+        LOGE("ret: %d", error);
+        MessagingUtil::throwEmailException(error, "email_add_mail()");
+    }
+    LOGD("mail added - new id = [%d]\n", mail->mail_id);
+
+    //refresh message object
+    message->setId(mail->mail_id);
+    message->setMessageStatus(MessageStatus::STATUS_DRAFT);
+    for (auto it = attachments.begin(); it != attachments.end(); ++it) {
+        (*it)->setMessageId(mail->mail_id);
+    }
+    for (auto it = inlineAttachments.begin(); it != inlineAttachments.end(); ++it) {
+        (*it)->setMessageId(mail->mail_id);
+    }
+
+    int ret = email_free_attachment_data(&attachment_data_list,attachment_data_count);
+    if(EMAIL_ERROR_NONE != ret){
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_attachment_data()").c_str());
+    }
+
+    //deleting mail without attachments
+    error = email_delete_mail(mail->mailbox_id,&tmp_id,1,1);
+    if (EMAIL_ERROR_NONE != error) {
+        ret = email_free_mail_data(&mail, 1);
+        if(EMAIL_ERROR_NONE != ret){
+            LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mail_data()").c_str());
+        }
+        LOGE("ret: %d", error);
+        MessagingUtil::throwEmailException(error, "email_delete_mail()");
+    }
+    ret = email_free_mail_data(&mail, 1);
+    if(EMAIL_ERROR_NONE != ret){
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mail_data()").c_str());
+    }
+}
+
+void Message::addSMSRecipientsToStruct(const std::vector<std::string> &recipients,
+        msg_struct_t &msg)
+{
+    const unsigned size = recipients.size();
+    for (unsigned int i = 0; i < size; ++i) {
+        char *address = const_cast<char *>(recipients.at(i).c_str());
+
+        LOGD("[%d] address:[%s]", i, address);
+        msg_struct_t tmpAddr = NULL;
+        int err = msg_list_add_item(msg, MSG_MESSAGE_ADDR_LIST_HND, &tmpAddr);
+        if ( MSG_SUCCESS== err ) {
+            err = msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_TYPE_INT,
+                    MSG_ADDRESS_TYPE_PLMN);
+            if(MSG_SUCCESS != err) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_set_int_value()").c_str());
+            }
+            err = msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT,
+                    MSG_RECIPIENTS_TYPE_TO);
+            if(MSG_SUCCESS != err) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_set_int_value()").c_str());
+            }
+            err = msg_set_str_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                    address, strlen(address));
+            if(MSG_SUCCESS != err) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_set_str_value()").c_str());
+            }
+        }
+        else {
+            LOGE("failed to add address[%d] %s", i, address);
+            LOGE("ret: %d", err);
+            MessagingUtil::throwMsgException(err, "msg_list_add_item()");
+        }
+    }
+}
+
+void Message::addMMSRecipientsToStruct(const std::vector<std::string> &recipients,
+        msg_struct_t &msg, int type)
+{
+    const unsigned size = recipients.size();
+    for (unsigned int i = 0; i < size; ++i) {
+
+        msg_struct_t tmpAddr = NULL;
+        int address_type = MSG_ADDRESS_TYPE_PLMN;
+        const std::size_t found = recipients[i].find("@");
+        if (std::string::npos != found) {
+            address_type = MSG_ADDRESS_TYPE_EMAIL;
+        }
+
+        char *address = const_cast<char *>(recipients.at(i).c_str());
+        LOGD("[%d] address:[%s] address_type:%d type:%d", i, address, address_type, type);
+
+        int error = msg_list_add_item(msg, MSG_MESSAGE_ADDR_LIST_HND, &tmpAddr);
+        if (MSG_SUCCESS == error) {
+            error = msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_TYPE_INT,
+                    address_type);
+            if(MSG_SUCCESS != error) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(error, "msg_set_int_value()").c_str());
+            }
+            error = msg_set_int_value(tmpAddr, MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT,
+                    type);
+            if(MSG_SUCCESS != error) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(error, "msg_set_int_value()").c_str());
+            }
+            error = msg_set_str_value(tmpAddr, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                    address, strlen(address));
+            if(MSG_SUCCESS != error) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(error, "msg_set_str_value()").c_str());
+            }
+        }
+        else {
+            LOGE("[%d] failed to add address: [%s], error: %d", i, address, error);
+            LOGE("ret: %d", error);
+            MessagingUtil::throwMsgException(error, "msg_list_add_item()");
+        }
+    }
+}
+
+void Message::addMMSBodyAndAttachmentsToStruct(const AttachmentPtrVector attach,
+        msg_struct_t &mms_struct, Message* message)
+{
+    LOGD("Entered with %d attachments", attach.size());
+
+    int size = attach.size();
+    for (int i = 0; i < size; i++) {
+
+        msg_struct_t tmpAtt = NULL;
+        int error = msg_list_add_item(mms_struct, MSG_STRUCT_MMS_ATTACH, &tmpAtt);
+        if (MSG_SUCCESS == error) {
+
+            //Ensure we have right id set
+            attach[i]->setId(i+1);
+            attach[i]->setMessageId(message->getId());
+
+            //-------------------------------------------------------------------------
+            // set file path, file name, file size
+            if (attach.at(i)->isFilePathSet()) {
+                std::string filepath = attach.at(i)->getFilePath();
+                LOGD("att[%d]: org filepath: %s", i, filepath.c_str());
+                if(Filesystem::External::isVirtualPath(filepath)) {
+                    // TODO
+                    // When introducing below line fromVirtualPath() function
+                    // needed context, but never used it - allowing for null
+                    // context pointer. If it appears to need a real context
+                    // it will need a fix here.
+                    filepath = Filesystem::External::fromVirtualPath(filepath);
+                    LOGD("att[%d]: org virtual filepath: %s", i, filepath.c_str());
+                }
+                int ret = msg_set_str_value(tmpAtt, MSG_MMS_ATTACH_FILEPATH_STR,
+                        const_cast<char*>(filepath.c_str()), filepath.size());
+                if (MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_str_value()").c_str());
+                }
+                const size_t last_slash_idx = filepath.find_last_of("\\/");
+                if (std::string::npos != last_slash_idx) {
+                    filepath.erase(0, last_slash_idx + 1);
+                }
+
+                LOGD("att[%d] filename: %s", i, filepath.c_str());
+                ret = msg_set_str_value(tmpAtt, MSG_MMS_ATTACH_FILENAME_STR,
+                        const_cast<char*>(filepath.c_str()), filepath.size());
+                if (MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_str_value()").c_str());
+                }
+                struct stat st;
+                if (stat(const_cast<char*>(filepath.c_str()), &st)) {
+                    LOGE("Stat error");
+                }
+                const int fsize = st.st_size;
+                ret = msg_set_int_value(tmpAtt, MSG_MMS_ATTACH_FILESIZE_INT, fsize);
+                if (MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+                }
+                LOGD("att[%d]: filesize: %d", i,fsize);
+            }
+
+            //-------------------------------------------------------------------------
+            //set mime type
+            if (attach.at(i)->isMimeTypeSet()) {
+                unsigned int type = MessageAttachment::MIMETypeStringToEnum(
+                        attach.at(i)->getMimeType());
+                int ret = msg_set_int_value(tmpAtt, MSG_MMS_ATTACH_MIME_TYPE_INT, type);
+                if (MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+                }
+                ret = msg_set_str_value(tmpAtt, MSG_MMS_ATTACH_CONTENT_TYPE_STR,
+                                    const_cast<char*>(attach.at(i)->getMimeType().c_str()),
+                                    MSG_MSG_ID_LEN);
+                if (MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_str_value()").c_str());
+                }
+
+                LOGD("att[%d]: setting mime type:0x%x (orignal:%s)", i, type,
+                    attach.at(i)->getMimeType().c_str());
+            }
+        } else {
+            LOGE("ret: %d", error);
+            MessagingUtil::throwMsgException(error, "msg_list_add_item()");
+        }
+    }
+}
+
+msg_struct_t Message::convertPlatformShortMessageToStruct(Message* message,
+        msg_handle_t handle)
+{
+    LOGD("Entered");
+
+    if (message->getType() != SMS && message->getType() != MMS) {
+        LOGD("Invalid type");
+        throw Common::InvalidValuesException("Invalid type");
+    }
+
+    msg_error_t err = MSG_SUCCESS;
+    msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
+    msg_struct_t msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+
+    if (message->is_id_set()) { // id is set - the message exists in database
+        msg_message_id_t id = (msg_message_id_t) message->getId();
+        err = msg_get_message(handle, id, msg, sendOpt);
+        if (err != MSG_SUCCESS) {
+            int ret = msg_release_struct(&sendOpt);
+            if (MSG_SUCCESS != err) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+            }
+            ret = msg_release_struct(&msg);
+            if (MSG_SUCCESS != err) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+            }
+            LOGE("ret: %d", err);
+            MessagingUtil::throwMsgException(err, "msg_get_message()");
+        }
+        LOGD("Using existing msg for id: %d", id);
+    } else { // id is not set - the message does not exist in database
+        MessageType msgType = message->getType();
+        if (msgType == MessageType::SMS) {
+            // Set message type to SMS
+            err = msg_set_int_value(msg, MSG_MESSAGE_TYPE_INT, MSG_TYPE_SMS);
+            if (MSG_SUCCESS != err) {
+                int ret = msg_release_struct(&sendOpt);
+                if (MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+                }
+                ret = msg_release_struct(&msg);
+                if (MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+                }
+                LOGE("ret: %d", err);
+                MessagingUtil::throwMsgException(err, "msg_set_int_value()");
+            }
+        } else {
+            // Set message type to MMS
+            err = msg_set_int_value(msg, MSG_MESSAGE_TYPE_INT, MSG_TYPE_MMS);
+            if (MSG_SUCCESS != err) {
+                int ret = msg_release_struct(&sendOpt);
+                if(MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+                }
+                ret = msg_release_struct(&msg);
+                if(MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+                }
+                LOGE("ret: %d", err);
+                MessagingUtil::throwMsgException(err, "msg_set_int_value()");
+            }
+        }
+    }
+    err = msg_release_struct(&sendOpt);
+    if(MSG_SUCCESS != err) {
+           LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+    }
+
+    int type;
+    err = msg_get_int_value(msg, MSG_MESSAGE_TYPE_INT, &type);
+    if(MSG_SUCCESS != err) {
+           LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_get_int_value()").c_str());
+    }
+
+    LOGD("Message(%p): MSG_MESSAGE_TYPE = %d", message, type);
+
+    if (type == MSG_TYPE_SMS) {
+        // Set SMS message body text
+        std::shared_ptr<MessageBody> body;
+        body = message->getBody();
+        if (!body->getPlainBody().empty()) {
+            int ret = msg_set_str_value(msg, MSG_MESSAGE_SMS_DATA_STR, const_cast<char*>
+                    (body->getPlainBody().c_str()), body->getPlainBody().size());
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_str_value()").c_str());
+            }
+        }
+
+        // Reset SMS recipients
+        int error = msg_list_clear(msg, MSG_MESSAGE_ADDR_LIST_HND);
+        if( MSG_SUCCESS != error) {
+            LOGE("ret: %d", error);
+            MessagingUtil::throwMsgException(error, "msg_list_clear()");
+        }
+
+        // Set SMS recipients
+        std::vector<std::string> recp_list = message->getTO();
+        if (!recp_list.empty()) {
+            message->addSMSRecipientsToStruct(recp_list, msg);
+        }
+
+    } else if (type == MSG_TYPE_MMS) {
+        // Set message type to MMS
+        int ret = msg_set_int_value(msg, MSG_MESSAGE_TYPE_INT, MSG_TYPE_MMS);
+        if (MSG_SUCCESS != ret ) {
+            LOGE("ret: %d", ret);
+            MessagingUtil::throwMsgException(ret, "msg_set_int_value()");
+        }
+        // Create MMS data
+        msg_struct_t mms_data = msg_create_struct(MSG_STRUCT_MMS);
+        if (mms_data == NULL) {
+            LOGE("Message(%p): Set MMS data error", message);
+            throw Common::UnknownException("Set MMS data error: msg_create_struct()");
+        }
+        // Set MMS message subject
+        std::string subject = message->getSubject();
+        if (subject != "") {
+            int r = msg_set_str_value(msg, MSG_MESSAGE_SUBJECT_STR,
+                    const_cast<char*>(subject.c_str()), subject.size());
+            if (r != MSG_SUCCESS) {
+                LOGE("ret: %d", r);
+                MessagingUtil::throwMsgException(r, "msg_set_str_value()");
+            }
+        }
+        // Set MMS message text
+        std::shared_ptr<MessageBody> body;
+        body = message->getBody();
+        if (!body->getPlainBody().empty()) {
+            LOGD("Message(%p): PlainBody is NOT empty", message);
+
+            static const int ROOT_LAYOUT_WIDTH = 100;
+            static const int ROOT_LAYOUT_HEIGHT = 100;
+            static const int WHITE_COLOR = 0xffffff;
+            static const int BLACK_COLOR = 0x000000;
+
+            //----------------------------------------------------------------------------
+            //Region
+            msg_struct_t region;
+            ret = msg_list_add_item(mms_data, MSG_STRUCT_MMS_REGION, &region);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_list_add_item()").c_str());
+            }
+
+            ret = msg_set_str_value(region, MSG_MMS_REGION_ID_STR, const_cast<char*>("Text"), 4);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_str_value()").c_str());
+            }
+
+            ret = msg_set_int_value(region, MSG_MMS_REGION_LENGTH_LEFT_INT, 0);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+            }
+
+            ret = msg_set_int_value(region, MSG_MMS_REGION_LENGTH_TOP_INT, 0);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+            }
+
+            ret = msg_set_int_value(region, MSG_MMS_REGION_LENGTH_WIDTH_INT,
+                    ROOT_LAYOUT_WIDTH);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+            }
+
+            ret = msg_set_int_value(region, MSG_MMS_REGION_LENGTH_HEIGHT_INT,
+                    ROOT_LAYOUT_HEIGHT);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+            }
+
+            ret = msg_set_int_value(region, MSG_MMS_REGION_BGCOLOR_INT, WHITE_COLOR);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+            }
+
+            ret = msg_set_bool_value(region, MSG_MMS_REGION_LENGTH_LEFT_PERCENT_BOOL, true);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_bool_value()").c_str());
+            }
+
+            ret = msg_set_bool_value(region, MSG_MMS_REGION_LENGTH_TOP_PERCENT_BOOL, true);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_bool_value()").c_str());
+            }
+
+            ret = msg_set_bool_value(region, MSG_MMS_REGION_LENGTH_WIDTH_PERCENT_BOOL, true);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_bool_value()").c_str());
+            }
+
+            ret = msg_set_bool_value(region, MSG_MMS_REGION_LENGTH_HEIGHT_PERCENT_BOOL, true);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_bool_value()").c_str());
+            }
+            //----------------------------------------------------------------------------
+            //Page
+            msg_struct_t page;
+            ret = msg_list_add_item(mms_data, MSG_STRUCT_MMS_PAGE, &page);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_list_add_item()").c_str());
+            }
+
+            ret = msg_set_int_value(page, MSG_MMS_PAGE_PAGE_DURATION_INT, 0);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+            }
+            //----------------------------------------------------------------------------
+            //Media
+            msg_struct_t media;
+            ret = msg_list_add_item(page, MSG_STRUCT_MMS_MEDIA, &media);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_list_add_item()").c_str());
+            }
+
+            ret = msg_set_int_value(media, MSG_MMS_MEDIA_TYPE_INT, MMS_SMIL_MEDIA_TEXT);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+            }
+
+            ret = msg_set_str_value(media, MSG_MMS_MEDIA_REGION_ID_STR,
+                    const_cast<char*>("Text"), 4);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_str_value()").c_str());
+            }
+
+            std::string body_file_path = saveToTempFile(body->getPlainBody());
+            int error = msg_set_str_value(media,
+                    MSG_MMS_MEDIA_FILEPATH_STR,
+                    const_cast<char*>(body_file_path.c_str()),
+                    body_file_path.size());
+            if (error != MSG_SUCCESS) {
+                LOGE("ret: %d", error);
+                MessagingUtil::throwMsgException(error, "msg_set_str_value()");
+            }
+
+            ret = msg_set_str_value(media, MSG_MMS_MEDIA_CONTENT_TYPE_STR,
+                "text/plain", 10);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_str_value()").c_str());
+            }
+            //----------------------------------------------------------------------------
+            //Smile text
+            msg_struct_t smil_text;
+            ret = msg_get_struct_handle(media, MSG_MMS_MEDIA_SMIL_TEXT_HND, &smil_text);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_struct_handle()").c_str());
+            }
+
+            ret = msg_set_int_value(smil_text, MSG_MMS_SMIL_TEXT_COLOR_INT, BLACK_COLOR);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+            }
+
+            ret = msg_set_int_value(smil_text, MSG_MMS_SMIL_TEXT_SIZE_INT,
+                    MMS_SMIL_FONT_SIZE_NORMAL);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+            }
+
+            ret = msg_set_bool_value(smil_text, MSG_MMS_SMIL_TEXT_BOLD_BOOL, true);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_bool_value()").c_str());
+            }
+        } else {
+            LOGD("Message(%p): PlainBody is EMPTY", message);
+        }
+        // Set MMS attachments
+        AttachmentPtrVector attach_list = message->getMessageAttachments();
+        LOGD("Message(%p): id:%d subject:[%s] plainBody:[%s] contains %d attachments",
+                message, message->getId(), message->getSubject().c_str(),
+                message->getBody()->getPlainBody().c_str(), attach_list.size());
+
+        ret = msg_set_int_value(mms_data, MSG_MESSAGE_ATTACH_COUNT_INT,
+                attach_list.size());
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+        }
+
+        if (!attach_list.empty()) {
+            addMMSBodyAndAttachmentsToStruct(attach_list, mms_data, message);
+        }
+        // Set MMS body
+        int r = msg_set_mms_struct(msg, mms_data);
+        if (r != MSG_SUCCESS) {
+            LOGE("ret: %d", r);
+            MessagingUtil::throwMsgException(r, "msg_set_mms_struct()");
+        }
+        ret = msg_release_struct(&mms_data);
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+
+        // Reset MMS recipients
+        ret = msg_list_clear(msg, MSG_MESSAGE_ADDR_LIST_HND);
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_list_clear()").c_str());
+        }
+
+        std::vector<std::string> recp_list = message->getTO();
+        message->addMMSRecipientsToStruct(recp_list, msg, MSG_RECIPIENTS_TYPE_TO);
+
+        recp_list = message->getCC();
+        message->addMMSRecipientsToStruct(recp_list, msg, MSG_RECIPIENTS_TYPE_CC);
+
+        recp_list = message->getBCC();
+        message->addMMSRecipientsToStruct(recp_list, msg, MSG_RECIPIENTS_TYPE_BCC);
+    }
+    else {
+        int ret = msg_release_struct(&msg);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        LOGE("Message(%p): Invalid message type", message);
+        throw Common::InvalidValuesException("Invalid message type");
+    }
+
+    int ret = MSG_SUCCESS;
+    // set common attributes for SMS and MMS
+    // Set message conversation id
+    if (message->is_conversation_id_set()) {
+        ret = msg_set_int_value(msg, MSG_MESSAGE_THREAD_ID_INT, message->getConversationId());
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+        }
+    }
+    // Set message folder id
+    if (message->is_folder_id_set()) {
+        ret = msg_set_int_value(msg, MSG_MESSAGE_FOLDER_ID_INT, message->getFolderId());
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+        }
+    }
+    // Set message timestamp
+    if (message->is_timestamp_set()) {
+        ret = msg_set_int_value(msg, MSG_MESSAGE_DISPLAY_TIME_INT, message->getTimestamp());
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+        }
+    }
+    // Set message from
+    if (message->is_from_set()) {
+        ret = msg_set_str_value(msg, MSG_MESSAGE_REPLY_ADDR_STR, const_cast<char*>
+                (message->getFrom().c_str()), message->getFrom().size());
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_str_value()").c_str());
+        }
+    }
+    // Set message if is response
+    if (message->is_in_response_set()) {
+        ret = msg_set_int_value(msg, MSG_MESSAGE_DIRECTION_INT, message->getInResponseTo());
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_int_value()").c_str());
+        }
+    }
+
+    // Set SIM index
+    // -1 means unknown - so do not set simindex in that case.
+    int sim_index = static_cast<int>(message->getSimIndex());
+    if (sim_index != -1) {
+        int error =
+            msg_set_int_value(msg, MSG_MESSAGE_SIM_INDEX_INT, sim_index+1);
+        if ( MSG_SUCCESS != error) {
+            LOGE("ret: %d", error);
+            MessagingUtil::throwMsgException(error, "msg_set_int_value()");
+        }
+    }
+
+    // Set message if is read
+    ret = msg_set_bool_value(msg, MSG_MESSAGE_READ_BOOL, message->getIsRead());
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_bool_value()").c_str());
+    }
+
+    LOGD("End");
+    return msg;
+}
+
+std::string Message::getShortMsgSenderFromStruct(msg_struct_t &msg)
+{
+    msg_list_handle_t addr_list = NULL;
+    int ret = msg_get_list_handle(msg, MSG_MESSAGE_ADDR_LIST_HND, (void **)&addr_list);
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_list_handle()").c_str());
+    }
+
+    char str_phone_number[MAX_ADDRESS_VAL_LEN];
+    const int count = msg_list_length(addr_list);
+    LOGD("Number of addresses: %d", count);
+
+    for (int i = 0; i < count; ++i)
+    {
+        int tempInt = 0;
+        ret = msg_get_int_value(msg, MSG_MESSAGE_DIRECTION_INT, &tempInt);
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+        }
+
+        const int type = tempInt;
+
+        if (MSG_DIRECTION_TYPE_MT == type)
+        {
+            msg_struct_t cur_addr_info = (msg_struct_t) msg_list_nth_data(addr_list, i);
+            ret = msg_get_str_value(cur_addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                    str_phone_number, MAX_ADDRESS_VAL_LEN);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+            }
+
+            LOGD("[%d/%d] is TYPE_MT, phone number is: %s", i, count, str_phone_number);
+
+            if(0 != str_phone_number[0]) {
+                return std::string(str_phone_number);
+            }
+        } else {
+            LOGD("[%d/%d] is NOT of TYPE_MT skipping, is:%d", i, count, type);
+        }
+    }
+
+    return std::string();
+}
+
+std::vector<std::string> Message::getSMSRecipientsFromStruct(msg_struct_t &msg)
+{
+    std::vector<std::string> address;
+    msg_list_handle_t addr_list = NULL;
+    int ret = msg_get_list_handle(msg, MSG_MESSAGE_ADDR_LIST_HND,(void **) &addr_list);
+    if (MSG_SUCCESS == ret) {
+        unsigned size = msg_list_length(addr_list);
+        for (unsigned int i = 0; i < size; i++) {
+            msg_struct_t addr_info = NULL;
+            char infoStr[MAX_ADDRESS_VAL_LEN];
+            //get address
+            addr_info = (msg_struct_t) msg_list_nth_data(addr_list, i);
+            ret = msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                    infoStr, MAX_ADDRESS_VAL_LEN);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+            }
+
+            address.push_back(std::string(infoStr));
+        }
+    } else {
+        LOGE("ret: %d", ret);
+        MessagingUtil::throwMsgException(ret, "msg_get_list_handle()");
+    }
+    return address;
+}
+
+std::vector<std::string> Message::getMMSRecipientsFromStruct(msg_struct_t &msg,
+        int type)
+{
+    std::vector<std::string> address;
+    msg_list_handle_t addr_list = NULL;
+    int ret = msg_get_list_handle(msg, MSG_MESSAGE_ADDR_LIST_HND, (void **) &addr_list);
+    if (MSG_SUCCESS == ret) {
+        unsigned size = msg_list_length(addr_list);
+        for (unsigned int i = 0; i < size; i++) {
+            msg_struct_t addr_info = NULL;
+            char infoStr[MAX_ADDRESS_VAL_LEN];
+            int tempInt;
+            //get address
+            addr_info = (msg_struct_t) msg_list_nth_data(addr_list, i);
+            ret = msg_get_int_value(addr_info, MSG_ADDRESS_INFO_RECIPIENT_TYPE_INT, &tempInt);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+            }
+            if (tempInt == type) {
+                ret = msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR,
+                        infoStr, MAX_ADDRESS_VAL_LEN);
+                if(MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+                }
+                address.push_back(std::string(infoStr));
+            }
+        }
+    } else {
+        LOGE("ret: %d", ret);
+        MessagingUtil::throwMsgException(ret, "msg_get_list_handle()");
+    }
+    return address;
+}
+
+void Message::setMMSBodyAndAttachmentsFromStruct(Message* message,
+        msg_struct_t &msg)
+{
+    LOGD("Entered message(%p)", message);
+    int tempInt = 0;
+    char infoStr[MSG_FILEPATH_LEN_MAX + 1];
+
+    msg_struct_t mms_struct = msg_create_struct(MSG_STRUCT_MMS);
+    int error = msg_get_mms_struct(msg, mms_struct);
+    if (MSG_SUCCESS != error) {
+        LOGE("Cannot get mms struct, error:%d", error);
+        int ret = msg_release_struct(&mms_struct);
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+
+        LOGE("ret: %d", ret);;
+        MessagingUtil::throwMsgException(ret, "msg_release_struct()");
+    }
+
+    bool body_has_been_set = false;
+    // if there are some pages in msg_struct_t
+    msg_list_handle_t page_list = NULL;
+    error = msg_get_list_handle(mms_struct, MSG_MMS_PAGE_LIST_HND, (void **) &page_list);
+    if (MSG_SUCCESS == error) {
+        int pageLen = msg_list_length(page_list);
+        LOGD("MSG_MMS_PAGE_LIST length:%d", pageLen);
+
+        for (int p = 0; p < pageLen; ++p) {
+            int ret = MSG_SUCCESS;
+            msg_struct_t page = (msg_struct_t) msg_list_nth_data(page_list, p);
+            if (!page) {
+                LOGE("returned page is null, continue");
+                continue;
+            }
+
+            msg_list_handle_t media_list = NULL;
+            error = msg_get_list_handle(page, MSG_MMS_PAGE_MEDIA_LIST_HND,
+                    (void **) &media_list);
+            if (MSG_SUCCESS == error) {
+                int mediaLen = msg_list_length(media_list);
+                LOGD("[p:%d] MSG_MMS_PAGE_MEDIA_LIST length:%d", p, mediaLen);
+
+                for (int m = 0; m < mediaLen; ++m) {
+                    msg_struct_t media = (msg_struct_t) msg_list_nth_data(media_list, m);
+                    if (NULL == media) {
+                        LOGE("returned media is null, continue");
+                        continue;
+                    }
+                    // add media from pages to attachments vector
+                    //set file path
+                    memset(infoStr, 0, MSG_FILEPATH_LEN_MAX + 1);
+                    ret = msg_get_str_value(media, MSG_MMS_MEDIA_FILEPATH_STR, infoStr,
+                            MSG_FILEPATH_LEN_MAX);
+                    if(MSG_SUCCESS != ret) {
+                        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+                    }
+
+                    LOGD("[p:%d, m:%d] attachment file path:%s", p, m, infoStr);
+
+                    ret = msg_get_int_value(media, MSG_MMS_MEDIA_TYPE_INT, &tempInt);
+                    if(MSG_SUCCESS != ret) {
+                        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+                    }
+
+                    const int msg_media_type = tempInt;
+                    std::string msg_media_type_str =
+                            MessageAttachment::MIMETypeEnumToString(msg_media_type);
+
+                    LOGD("[p:%d, m:%d] MSG_MMS_MEDIA_TYPE: %d (%s)", p, m, msg_media_type,
+                            msg_media_type_str.c_str());
+
+                    //According to old implementation
+                    // "text value on first page goes to body attribute"
+                    if ((0 == p) && (MMS_SMIL_MEDIA_TEXT == msg_media_type)) {
+                        LOGD("Loading body from file: %s ", infoStr);
+
+                        try {
+                            message->getBody()->setPlainBody(
+                                    MessagingUtil::loadFileContentToString(infoStr));
+                            body_has_been_set = true;
+
+                            LOGD("Loaded body: %s",
+                                    message->getBody()->getPlainBody().c_str());
+
+                        } catch(const Common::BasePlatformException& exception) {
+                            LOGE("Unhandled exception: %s (%s)!",
+                                 (exception.getName()).c_str(),
+                                 (exception.getMessage()).c_str());
+                            LOGD("[p:%d, m:%d] body is not set", p, m);
+                        }
+                        catch (...) {
+                            LOGE("Unknown exception occured during plain body loading");
+                            LOGD("[p:%d, m:%d] body is not set", p, m);
+                        }
+
+                    } else {
+                        std::shared_ptr<MessageAttachment> ma (new MessageAttachment());
+                        ma->setFilePath(infoStr);
+
+                        //set message id
+                        ret = msg_get_int_value(msg, MSG_MESSAGE_STORAGE_ID_INT, &tempInt);
+                        if(MSG_SUCCESS != ret) {
+                            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+                        }
+
+                        ma->setMessageId(tempInt);
+
+                        //set id
+                        ma->setId(message->m_attachments.size() + 1);
+                        message->m_attachments.push_back(ma);
+                        message->m_has_attachment = true;
+
+                        //set mime type
+                        ma->setMimeType(msg_media_type_str);
+
+                        MessageAttachment* att = ma.get();
+                        LOGD("[p:%d, m:%d] added attachment: %p "
+                                "(mime:0x%x mime:%s messageId:%d)", p, m, att,
+                                msg_media_type, msg_media_type_str.c_str(),
+                                ma->getMessageId());
+                    }
+
+                    ret = msg_release_struct(&media);
+                    if(MSG_SUCCESS != ret) {
+                        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+                    }
+                }
+            } else {
+                int ret = msg_release_struct(&mms_struct);
+                if(MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+                }
+                LOGE("failed to get attachment");
+                MessagingUtil::throwMsgException(error, "msg_get_list_handle()");
+            }
+            ret = msg_release_struct(&page);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+            }
+        }
+    } else {
+        int ret = msg_release_struct(&mms_struct);
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        LOGE("ret: %d", error);
+        MessagingUtil::throwMsgException(error, "msg_get_list_handle()");
+    }
+
+    if(false == body_has_been_set) {
+        LOGW("Warning: body has not been set!");
+    }
+
+    LOGD("after MSG_MMS_PAGE_LIST attachments count is:%d",
+            message->m_attachments.size());
+
+    // if there are some other attachments add it to attachments vector
+    msg_list_handle_t attach_list = NULL;
+    error = msg_get_list_handle(mms_struct, MSG_MMS_ATTACH_LIST_HND, (void **)
+            &attach_list);
+    if (MSG_SUCCESS == error) {
+        int ret = MSG_SUCCESS;
+        unsigned size = msg_list_length(attach_list);
+        LOGD("MSG_MMS_ATTACH_LIST length:%d", size);
+
+        for (unsigned int i = 0; i < size; i++) {
+            msg_struct_t attach_info = NULL;
+            attach_info = (msg_struct_t) msg_list_nth_data(attach_list, i);
+            if(!attach_info) {
+                LOGW("[att:%d] attach_info is NULL!", i);
+                continue;
+            }
+
+            std::shared_ptr<MessageAttachment> ma (new MessageAttachment());
+
+            //set message id
+            ret = msg_get_int_value(msg, MSG_MESSAGE_ID_INT, &tempInt);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+            }
+
+            ma->setMessageId(tempInt);
+
+            //set file path
+            ret = msg_get_str_value(attach_info, MSG_MMS_ATTACH_FILEPATH_STR, infoStr,
+                    MSG_FILEPATH_LEN_MAX);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+            }
+
+            ma->setFilePath(infoStr);
+
+            //set attachment id
+            ma->setId(message->m_attachments.size() + 1);
+
+            //set mime type
+            ret = msg_get_int_value(attach_info, MSG_MMS_ATTACH_MIME_TYPE_INT, &tempInt);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+            }
+
+            std::string type = MessageAttachment::MIMETypeEnumToString(tempInt);
+            ma->setMimeType(type);
+
+            MessageAttachment* att = ma.get();
+            LOGD("[att:%d] added attachement: %p (mime:0x%x mime:%s path:%s id:%d)",
+                i, att, tempInt, type.c_str(), infoStr, ma->getId());
+
+            message->m_attachments.push_back(ma);
+            message->m_has_attachment = true;
+
+            ret = msg_release_struct(&attach_info);
+            if(MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+            }
+        }
+    } else {
+        int ret = msg_release_struct(&mms_struct);
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        LOGE("ret: %d", error);
+        MessagingUtil::throwMsgException(error, "msg_get_list_handle()");
+    }
+
+    LOGD("after MSG_MMS_ATTACH_LIST attachments count is:%d",
+            message->m_attachments.size());
+    int ret = msg_release_struct(&mms_struct);
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+    }
+}
+
+Message* Message::convertPlatformShortMessageToObject(msg_struct_t msg){
+    Message *message = NULL;
+    int infoInt;
+    bool infoBool;
+    char infoStr[MAX_ADDRESS_VAL_LEN + 1];
+    //get type
+    int ret = msg_get_int_value(msg, MSG_MESSAGE_TYPE_INT, &infoInt);
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+    }
+
+    if (infoInt == MSG_TYPE_SMS) {
+        message = new MessageSMS();
+        // get SMS body
+        std::shared_ptr<MessageBody> body(new MessageBody());
+        char msgInfoStr[MAX_MSG_TEXT_LEN + 1];
+        ret = msg_get_str_value(msg, MSG_MESSAGE_SMS_DATA_STR, msgInfoStr, MAX_MSG_TEXT_LEN);
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+        }
+
+        body->setPlainBody(std::string(msgInfoStr));
+        message->setBody(body);
+        // get recipients
+        std::vector<std::string> recp_list = message->getSMSRecipientsFromStruct(msg);
+        message->setTO(recp_list);
+    } else if (infoInt == MSG_TYPE_MMS) {
+        message = new MessageMMS();
+
+        // get MMS body
+        ret = msg_get_int_value(msg, MSG_MESSAGE_DATA_SIZE_INT, &infoInt);
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+        }
+
+        const int mms_body_length = infoInt;
+
+        if(mms_body_length > 0) {
+            std::unique_ptr<char[]> mms_body_str(new char[mms_body_length + 1]);
+            memset(mms_body_str.get(), 0, (mms_body_length + 1) * sizeof(char));
+
+            int error = msg_get_str_value(msg, MSG_MESSAGE_MMS_TEXT_STR,
+                    mms_body_str.get(), mms_body_length);
+            if(MSG_SUCCESS != error) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(error, "msg_get_str_value()").c_str());
+            } else {
+                //Check if fetched string is not empty
+                if((mms_body_str.get())[0] != 0) {
+                    LOGD("Fetched plain body (with MSG_MESSAGE_MMS_TEXT_STR):"
+                            "[%s] length:%d", mms_body_str.get(), mms_body_length);
+
+                    std::shared_ptr<MessageBody> body (new MessageBody());
+                    std::string infoString;
+                    infoString.assign(mms_body_str.get());
+                    body->setPlainBody(infoString);
+                    message->setBody(body);
+                } else {
+                    LOGW("Warning: fetched plain body is empty "
+                            "despite reported length is:%d!", mms_body_length);
+                }
+
+                LOGD("Set plain body: [%s]", message->getBody()->getPlainBody().c_str());
+            }
+        } else {
+            LOGW("Warning: mms plain body length is 0!");
+        }
+
+        // get recipients
+        std::vector<std::string> recp_list = getMMSRecipientsFromStruct(msg,
+                MSG_RECIPIENTS_TYPE_TO);
+        message->setTO(recp_list);
+        recp_list = getMMSRecipientsFromStruct(msg, MSG_RECIPIENTS_TYPE_CC);
+        message->setCC(recp_list);
+        recp_list = getMMSRecipientsFromStruct(msg, MSG_RECIPIENTS_TYPE_BCC);
+        message->setBCC(recp_list);
+        // get subject
+        memset(infoStr, 0, MAX_ADDRESS_VAL_LEN + 1);
+        ret = msg_get_str_value(msg, MSG_MESSAGE_SUBJECT_STR, infoStr, MAX_SUBJECT_LEN);
+        if(MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+        }
+
+        message->setSubject(infoStr);
+        //set attachments
+        setMMSBodyAndAttachmentsFromStruct(message, msg);
+    } else {
+        LOGE("Invalid Message type: %d", infoInt);
+        throw Common::InvalidValuesException("Invalid Message type");
+    }
+
+    // get id
+    ret = msg_get_int_value(msg, MSG_MESSAGE_ID_INT, &infoInt);
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+    }
+
+    message->setId(infoInt);
+    // get conversation id
+    ret = msg_get_int_value(msg, MSG_MESSAGE_THREAD_ID_INT, &infoInt);
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+    }
+
+    message->setConversationId(infoInt);
+    // get folder id
+    ret = msg_get_int_value(msg, MSG_MESSAGE_FOLDER_ID_INT, &infoInt);
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+    }
+
+    message->setFolderId(infoInt);
+    // get timestamp
+    ret = msg_get_int_value(msg, MSG_MESSAGE_DISPLAY_TIME_INT, &infoInt);
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+    }
+
+    message->setTimeStamp(infoInt);
+    // get from
+    const std::string& from = Message::getShortMsgSenderFromStruct(msg);
+    message->setFrom(from);
+    LOGD("Message(%p) from is: %s", message, message->getFrom().c_str());
+    // get if is in response
+    ret = msg_get_int_value(msg, MSG_MESSAGE_DIRECTION_INT, &infoInt);
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+    }
+
+    LOGD("Message(%p) direction is: %d", message, infoInt);
+    message->setInResponseTo(infoInt);
+    // get is read
+    ret = msg_get_bool_value(msg, MSG_MESSAGE_READ_BOOL, &infoBool);
+    if(MSG_SUCCESS != ret) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_bool_value()").c_str());
+    }
+
+    message->setIsRead(infoBool);
+
+    // get status
+
+    // This "strange" fix has been taken from old implementation:
+    // void Mms::readMessageStatus(msg_struct_t& messageData)
+    //
+    int error = msg_get_int_value(msg, MSG_MESSAGE_FOLDER_ID_INT, &infoInt);
+    if(MSG_SUCCESS == error) {
+        MessageStatus msg_status;
+        switch (infoInt) {
+            case MSG_INBOX_ID: msg_status = MessageStatus::STATUS_LOADED; break;
+            case MSG_OUTBOX_ID: msg_status = MessageStatus::STATUS_SENDING; break;
+            case MSG_SENTBOX_ID: msg_status = MessageStatus::STATUS_SENT; break;
+            case MSG_DRAFT_ID: msg_status = MessageStatus::STATUS_DRAFT; break;
+            default: msg_status = MessageStatus::STATUS_LOADED; break;
+        }
+        message->setMessageStatus(msg_status);
+
+        LOGD("MSG_MESSAGE_FOLDER_ID:%d -> messageStatus:%s", infoInt,
+                MessagingUtil::messageStatusToString(msg_status).c_str());
+    }
+    else
+    {
+        LOGE("%s", MessagingUtil::getMsgErrorMessage(error, "msg_get_int_value()").c_str());
+        error = msg_get_int_value(msg, MSG_SENT_STATUS_NETWORK_STATUS_INT, &infoInt);
+
+        if(MSG_SUCCESS == error) {
+            MessageStatus msg_status;
+            if (infoInt == MSG_NETWORK_SEND_SUCCESS) {
+                msg_status = MessageStatus::STATUS_SENT;
+            } else if (infoInt == MSG_NETWORK_SENDING) {
+                msg_status = MessageStatus::STATUS_SENDING;
+            } else if (infoInt == MSG_NETWORK_SEND_FAIL) {
+                msg_status = MessageStatus::STATUS_FAILED;
+            } else if (infoInt == MSG_NETWORK_NOT_SEND) {
+                msg_status = MessageStatus::STATUS_DRAFT;
+            } else {
+                LOGW("warning undefined messageStatus: %d!", infoInt);
+                msg_status = MessageStatus::STATUS_UNDEFINED;
+            }
+            message->setMessageStatus(msg_status);
+
+            LOGD("MSG_SENT_STATUS_NETWORK_STATUS:%d MessageStatus:%s", infoInt,
+                MessagingUtil::messageStatusToString(msg_status).c_str());
+        } else {
+            LOGE("%s", MessagingUtil::getMsgErrorMessage(error, "msg_get_int_value()").c_str());
+
+            if(0 == message->getId()) {
+                LOGW("Both MSG_SENT_STATUS_NETWORK_STATUS_INT and "
+                        "MSG_MESSAGE_FOLDER_ID_INT failed, messageId == 0 ASSUMING that"
+                        "this message is in DRAFT");
+                message->setMessageStatus(MessageStatus::STATUS_DRAFT);
+            }
+        }
+    }
+
+    LOGD("End");
+    return message;
+}
+
+std::vector<std::string> Message::split(const std::string& input,
+        char delimiter)
+{
+    std::vector<std::string> ret;
+    std::stringstream stream(input);
+    std::string item;
+    while (getline(stream, item, delimiter)) {
+        ret.push_back(item);
+    }
+    return ret;
+}
+
+std::vector<std::string> Message::getEmailRecipientsFromStruct(const char *recipients)
+{
+    std::vector<std::string> tmp = Message::split(recipients, ';');
+    for (std::vector<std::string>::iterator it = tmp.begin(); it != tmp.end(); ++it) {
+        *it = MessagingUtil::ltrim(*it);
+    }
+
+    if (tmp.begin() != tmp.end()) {
+        if (*(tmp.begin()) == "") {
+            tmp.erase(tmp.begin());
+        }
+
+        if (*(tmp.end() - 1) == "") {
+            tmp.erase(tmp.end() - 1);
+        }
+    }
+
+    // remove '<' and '>'
+    tmp = MessagingUtil::extractEmailAddresses(tmp);
+    return tmp;
+}
+
+std::shared_ptr<MessageBody> Message::convertEmailToMessageBody(
+        email_mail_data_t& mail)
+{
+    LOGD("Enter");
+    std::shared_ptr<MessageBody> body (new MessageBody());
+    body->updateBody(mail);
+    return body;
+}
+
+AttachmentPtrVector Message::convertEmailToMessageAttachment(email_mail_data_t& mail)
+{
+    LOGD("Enter");
+    email_attachment_data_t* attachment = NULL;
+    int attachmentCount = 0;
+
+    AttachmentPtrVector att;
+
+    int err = email_get_attachment_data_list(mail.mail_id, &attachment, &attachmentCount);
+    if (EMAIL_ERROR_NONE != err) {
+        LOGE("ret: %d", err);
+        MessagingUtil::throwEmailException(err, "email_get_attachment_data_list()");
+    }
+    if ( attachment && attachmentCount > 0) {
+        for (int i = 0; i < attachmentCount; i++) {
+            std::shared_ptr<MessageAttachment> tmp_att (new MessageAttachment());
+            tmp_att->updateWithAttachmentData(attachment[i]);
+            att.push_back(tmp_att);
+        }
+    }
+
+    err = email_free_attachment_data(&attachment, attachmentCount);
+    if(EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "mail_free_attachment_data()").c_str());
+    }
+    return att;
+}
+
+std::shared_ptr<Message> Message::convertPlatformEmailToObject(
+        email_mail_data_t& mail)
+{
+    LOGD("Enter");
+    std::shared_ptr<Message> message(new MessageEmail());
+    message->updateEmailMessage(mail);
+    return message;
+}
+
+void Message::updateEmailMessage(email_mail_data_t& mail)
+{
+    LOGW("This should be called on MessageEmail instance");
+}
+
+/**
+ *  Attribute      | Attribute filter| Attribute range filter
+ *                 | supported       | supported
+ * ----------------+-----------------+------------------------
+ *  id             | Yes             | No
+ *  serviceId      | Yes             | No
+ *  conversationId | No              | No
+ *  folderId       | Yes             | No
+ *  type           | Yes             | No
+ *  timestamp      | No              | Yes
+ *  from           | Yes             | No
+ *  to             | Yes             | No
+ *  cc             | Yes             | No
+ *  bcc            | Yes             | No
+ *  body.plainBody | Yes             | No
+ *  isRead         | Yes             | No
+ *  hasAttachment  | Yes             | No
+ *  isHighPriority | Yes             | No
+ *  subject        | Yes             | No
+ *  isResponseTo   | No              | No
+ *  messageStatus  | No              | No
+ *  attachments    | No              | No
+ **/
+namespace MESSAGE_FILTER_ATTRIBUTE {
+
+const std::string ID = JSMessageKeys::MESSAGE_ATTRIBUTE_ID;
+const std::string SERVICE_ID = "serviceId";
+const std::string CONVERSATION_ID = JSMessageKeys::MESSAGE_ATTRIBUTE_CONVERSATION_ID;
+const std::string FOLDER_ID = JSMessageKeys::MESSAGE_ATTRIBUTE_FOLDER_ID;
+const std::string TYPE = JSMessageKeys::MESSAGE_ATTRIBUTE_TYPE;
+const std::string TIMESTAMP = JSMessageKeys::MESSAGE_ATTRIBUTE_TIMESTAMP;
+const std::string FROM = JSMessageKeys::MESSAGE_ATTRIBUTE_FROM;
+const std::string TO = JSMessageKeys::MESSAGE_ATTRIBUTE_TO;
+const std::string CC = JSMessageKeys::MESSAGE_ATTRIBUTE_CC;
+const std::string BCC = JSMessageKeys::MESSAGE_ATTRIBUTE_BCC;
+const std::string BODY_PLAIN_BODY = "body.plainBody";
+const std::string IS_READ = JSMessageKeys::MESSAGE_ATTRIBUTE_IS_READ;
+const std::string HAS_ATTACHMENT = JSMessageKeys::MESSAGE_ATTRIBUTE_HAS_ATTACHMENT;
+const std::string IS_HIGH_PRIORITY = JSMessageKeys::MESSAGE_ATTRIBUTE_IS_HIGH_PRIORITY;
+const std::string SUBJECT = JSMessageKeys::MESSAGE_ATTRIBUTE_SUBJECT;
+
+} //namespace MESSAGE_FILTER_ATTRIBUTE
+
+bool Message::isMatchingAttribute(const std::string& attribute_name,
+            const FilterMatchFlag match_flag,
+            AnyPtr match_value) const
+{
+    LOGD("Entered");
+    auto key = match_value->toString();
+    LOGD("attribute_name:%s match_flag:%d matchValue:%s", attribute_name.c_str(),
+            match_flag, key.c_str());
+
+    using namespace MESSAGE_FILTER_ATTRIBUTE;
+
+    if (ID == attribute_name) {
+        return FilterUtils::isStringMatching(key, std::to_string(getId()),
+                match_flag);
+    }
+    else if (SERVICE_ID == attribute_name) {
+        if(is_service_is_set()) {
+            return FilterUtils::isStringMatching(key, std::to_string(getServiceId()),
+                    match_flag);
+        }
+    }
+    else if (FOLDER_ID == attribute_name) {
+        return FilterUtils::isStringMatching(key, std::to_string(getFolderId()),
+                match_flag);
+    }
+    else if (TYPE == attribute_name) {
+        const std::string msgTypeStr = MessagingUtil::messageTypeToString(getType());
+        return FilterUtils::isStringMatching(key, msgTypeStr, match_flag);
+    }
+    else if (FROM == attribute_name) {
+        return FilterUtils::isStringMatching(key, getFrom() , match_flag);
+    }
+    else if (TO == attribute_name) {
+        return FilterUtils::isAnyStringMatching(key, getTO(), match_flag);
+    }
+    else if (CC == attribute_name) {
+        return FilterUtils::isAnyStringMatching(key, getCC(), match_flag);
+    }
+    else if (BCC == attribute_name) {
+        return FilterUtils::isAnyStringMatching(key, getBCC(), match_flag);
+    }
+    else if (BODY_PLAIN_BODY == attribute_name) {
+        if(getBody()) {
+            return FilterUtils::isStringMatching(key, getBody()->getPlainBody(),
+                    match_flag);
+        }
+    }
+    else if (IS_READ == attribute_name) {
+        return FilterUtils::isStringMatching(key, FilterUtils::boolToString(getIsRead()),
+                match_flag);
+    }
+    else if (HAS_ATTACHMENT == attribute_name) {
+        return FilterUtils::isStringMatching(key,
+                FilterUtils::boolToString(getHasAttachment()),
+                match_flag);
+    }
+    else if (IS_HIGH_PRIORITY == attribute_name) {
+        return FilterUtils::isStringMatching(key,
+                FilterUtils::boolToString(getIsHighPriority()),
+                match_flag);
+    }
+    else if (SUBJECT == attribute_name) {
+        return FilterUtils::isStringMatching(key, getSubject(), match_flag);
+    }
+    else {
+        LOGD("attribute:%s is NOT SUPPORTED", attribute_name.c_str());
+    }
+
+    return false;
+}
+
+bool Message::isMatchingAttributeRange(const std::string& attribute_name,
+            AnyPtr initial_value,
+            AnyPtr end_value) const
+{
+    LOGD("Entered attribute_name: %s", attribute_name.c_str());
+
+    using namespace MESSAGE_FILTER_ATTRIBUTE;
+    if(TIMESTAMP == attribute_name) {
+        return FilterUtils::isTimeStampInRange(getTimestamp(), initial_value,
+                end_value);
+    }
+    else {
+        LOGD("attribute:%s is NOT SUPPORTED", attribute_name.c_str());
+    }
+
+    return false;
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/Message.h b/src/Messaging/Message.h
new file mode 100644 (file)
index 0000000..7ae399f
--- /dev/null
@@ -0,0 +1,229 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        Message.h
+ */
+
+#ifndef __TIZEN_MESSAGE_H__
+#define __TIZEN_MESSAGE_H__
+
+#include <time.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string>
+#include <vector>
+#include <memory>
+#include <msg_storage.h>
+#include "MessagingUtil.h"
+#include "MessageAttachment.h"
+#include "MessageBody.h"
+#include "JSVector.h"
+#include <email-api.h>
+#include <AbstractFilter.h>
+#include <TelNetwork.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class Message;
+
+struct MessageHolder {
+    std::shared_ptr<Message> ptr;
+};
+
+typedef std::shared_ptr<Message> MessagePtr;
+typedef std::vector<MessagePtr> MessagePtrVector;
+
+enum AttachmentType {
+    EXTERNAL = 0,
+    INLINE = 1
+};
+
+class Message : public Tizen::FilterableObject {
+public:
+// constructor
+    Message();
+    virtual ~Message();
+
+// attributes getters
+    int getId() const;
+    int getConversationId() const;
+    int getFolderId() const;
+    MessageType getType() const;
+    time_t getTimestamp() const;
+    std::string getFrom() const;
+    std::vector<std::string> getTO() const;
+    JSObjectRef getJSTO(JSContextRef global_ctx);
+    std::vector<std::string> getCC() const;
+    JSObjectRef getJSCC(JSContextRef global_ctx);
+    std::vector<std::string> getBCC() const;
+    JSObjectRef getJSBCC(JSContextRef global_ctx);
+    std::shared_ptr<MessageBody> getBody() const;
+    bool getIsRead() const;
+     // getHasAttachment() is virtual to support MMS and email differently
+    virtual bool getHasAttachment() const;
+    bool getIsHighPriority() const;
+    std::string getSubject() const;
+    int getInResponseTo() const;
+    MessageStatus getMessageStatus() const;
+    AttachmentPtrVector getMessageAttachments() const;
+    JSObjectRef getJSMessageAttachments(JSContextRef global_ctx);
+    int getServiceId() const;
+    TelNetworkDefaultDataSubs_t getSimIndex() const;
+
+// attributes setters (virtual because some of them can be overriden in sub classes)
+    virtual void setId(int id);
+    virtual void setConversationId(int id);
+    virtual void setFolderId(int id);
+    // type setting not allowed so no setter provided
+    virtual void setTimeStamp(time_t timestamp);
+    virtual void setFrom(std::string from);
+    virtual void setTO(std::vector<std::string> &to);
+    virtual void setCC(std::vector<std::string> &cc);
+    virtual void setBCC(std::vector<std::string> &bcc);
+    virtual void setBody(std::shared_ptr<MessageBody>& body);
+    virtual void setIsRead(bool read);
+    // has attachment can't be set explicity -> no setter for this flag
+    virtual void setIsHighPriority(bool highpriority);
+    virtual void setSubject(std::string subject);
+    virtual void setInResponseTo(int inresp);
+    virtual void setMessageStatus(MessageStatus status);
+    virtual void setMessageAttachments(AttachmentPtrVector &attachments);
+    virtual void setServiceId(int service_id);
+    virtual void setSimIndex(TelNetworkDefaultDataSubs_t sim_index);
+
+// support for optional, nullable (at JS layer) attibutes
+    // message id
+    bool is_id_set() const;
+    // conversation id
+    bool is_conversation_id_set() const;
+    // folder id
+    bool is_folder_id_set() const;
+    // timestamp
+    bool is_timestamp_set() const;
+    // message sender
+    bool is_from_set() const;
+    // related message ("parent" message)
+    bool is_in_response_set() const;
+    // service id
+    bool is_service_is_set() const;
+    // gets recipients list for SMS message
+    void addSMSRecipientsToStruct(const std::vector<std::string> &recipients,
+            msg_struct_t &msg);
+    // gets recipients list for SMS message
+    void addMMSRecipientsToStruct(const std::vector<std::string> &recipients,
+            msg_struct_t &msg, int type);
+    /**
+     * Updates message with data from email_mail_data_t structure.
+     * @param mail
+     */
+    virtual void updateEmailMessage(email_mail_data_t& mail);
+
+    // gets from(sender) address from short msg struct
+    static std::string getShortMsgSenderFromStruct(msg_struct_t &msg);
+    // function for filling msg_struct_t fields
+    static msg_struct_t convertPlatformShortMessageToStruct(Message* message,
+            msg_handle_t handle);
+    // gets recipients list for SMS message
+    std::vector<std::string> getSMSRecipientsFromStruct(msg_struct_t &msg);
+    // gets recipients list for MMS message
+    static std::vector<std::string> getMMSRecipientsFromStruct(msg_struct_t &msg, int type);
+    // function for filling Message attributes
+    static Message* convertPlatformShortMessageToObject(msg_struct_t msg);
+    static void addMMSBodyAndAttachmentsToStruct(const AttachmentPtrVector attach,
+            msg_struct_t &mms_struct, Message* message);
+    static void setMMSBodyAndAttachmentsFromStruct(Message *message, msg_struct_t &msg);
+
+    static email_mail_data_t* convertPlatformEmail(std::shared_ptr<Message> message);
+    static void addEmailAttachments(std::shared_ptr<Message> message);
+    static std::string convertEmailRecipients(const std::vector<std::string> &recipients);
+    static std::vector<std::string> getEmailRecipientsFromStruct(const char *recipients);
+    static std::shared_ptr<Message> convertPlatformEmailToObject(email_mail_data_t& mail);
+    static std::shared_ptr<MessageBody> convertEmailToMessageBody(email_mail_data_t& mail);
+    static AttachmentPtrVector convertEmailToMessageAttachment(email_mail_data_t& mail);
+
+    // Tizen::FilterableObject
+    virtual bool isMatchingAttribute(const std::string& attribute_name,
+            const Tizen::FilterMatchFlag match_flag,
+            Tizen::AnyPtr match_value) const;
+
+    virtual bool isMatchingAttributeRange(const std::string& attribute_name,
+            Tizen::AnyPtr initial_value,
+            Tizen::AnyPtr end_value) const;
+protected:
+    //! Message id
+    int m_id;
+    //! Flag for checking if id is set (false means: not set)
+    bool m_id_set;
+    //! Conversation id
+    int m_conversation_id;
+    //! Flag for checking if conversation id is set (false means: not set)
+    bool m_conversation_id_set;
+    //! Folder id
+    int m_folder_id;
+    //! Flag for checking if folder id is set (false means: not set)
+    bool m_folder_id_set;
+    //! Message type (messaging.sms, messaging.mms, messaging.email)
+    MessageType m_type;
+    //! Timestamp - time when message has been sent/received
+    time_t m_timestamp;
+    //! Flag for checking if timestamp is set (false means: not set)
+    bool m_timestamp_set;
+    //! Message sender address (email) or number (SMS, MMS)
+    std::string m_from;
+    //! Flag for checking if sender is set (false means: not set)
+    bool m_from_set;
+    //! Message recipients
+    Common::JSStringVector m_to;
+    //! Message CarbonCopy recipients (used only for email)
+    Common::JSStringVector m_cc;
+    //! Message BlindCarbonCopy recipients (used only for email)
+    Common::JSStringVector m_bcc;
+    //! MessageBody (object containg plainBody and htmlBody for emails)
+    std::shared_ptr<MessageBody> m_body;
+    //! Service id
+    int m_service_id;
+    //! Message isRead flag
+    bool m_is_read;
+    //! Message hasAttachment flag
+    bool m_has_attachment;
+    //! Message isHighPriority flag
+    bool m_high_priority;
+    //! Message subject (used in MMS and email)
+    std::string m_subject;
+    //! Id of original message when message is a reply or forward
+    int m_in_response;
+    //! Flag for checking if id of related message is set (false means: not set)
+    bool m_in_response_set;
+    //! Flag for checking if service id is set
+    bool m_service_id_set;
+    //! Outgoing Message status (SENT, SENDING, DRAFT etc)
+    MessageStatus m_status;
+    //! Attachments attached to this message
+    JSAttachmentsVector m_attachments;
+    //! SIM index which indicate a sim to send message.
+    TelNetworkDefaultDataSubs_t m_sim_index;
+private:
+    static std::vector<std::string> split(const std::string& input,
+            char delimiter);
+};
+
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_MESSAGE_H__
diff --git a/src/Messaging/MessageAttachment.cpp b/src/Messaging/MessageAttachment.cpp
new file mode 100755 (executable)
index 0000000..68d6844
--- /dev/null
@@ -0,0 +1,590 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageAttachment.cpp
+ */
+
+#include "MessageAttachment.h"
+#include <email-api.h>
+#include <PlatformException.h>
+#include <Logger.h>
+namespace DeviceAPI {
+namespace Messaging {
+
+std::map<std::string,unsigned int>& MessageAttachment::MIMETypeStringToEnumMap = initializeMIMETypeStringToEnumMap();
+std::map<unsigned int, std::string>& MessageAttachment::MIMETypeEnumToStringMap = initializeMIMETypeEnumToStringMap();
+
+
+
+MessageAttachment::MessageAttachment()
+{
+    LOGD("MessageAttachment constructor (%p)", this);
+    m_id = -1;
+    m_isIdSet = false;
+    m_messageId = -1;
+    m_isMessageIdSet = false;
+    m_mimeType = "";
+    m_isMimeTypeSet = false;
+    m_filePath = "";
+    m_isFilePathSet = false;
+    m_isSaved = true;
+}
+
+MessageAttachment::~MessageAttachment()
+{
+    LOGD("MessageAttachment destructor (%p)", this);
+}
+
+// id
+
+int MessageAttachment::getId()
+{
+    return m_id;
+}
+
+void MessageAttachment::setId(int value)
+{
+    m_id = value;
+    m_isIdSet = true;
+}
+
+bool MessageAttachment::isIdSet()
+{
+    return m_isIdSet;
+}
+
+void MessageAttachment::unsetId()
+{
+    m_isIdSet = false;
+}
+
+// messageId
+
+int MessageAttachment::getMessageId()
+{
+    return m_messageId;
+}
+
+void MessageAttachment::setMessageId(int value)
+{
+    m_messageId = value;
+    m_isMessageIdSet = true;
+}
+
+bool MessageAttachment::isMessageIdSet()
+{
+    return m_isMessageIdSet;
+}
+
+void MessageAttachment::unsetMessageId()
+{
+    m_isMessageIdSet = false;
+}
+
+// mimeType
+
+std::string MessageAttachment::getMimeType()
+{
+    return m_mimeType;
+}
+
+void MessageAttachment::setMimeType(const std::string &value)
+{
+    m_mimeType = value;
+    m_isMimeTypeSet = true;
+}
+
+bool MessageAttachment::isMimeTypeSet()
+{
+    return m_isMimeTypeSet;
+}
+
+void MessageAttachment::unsetMimeType()
+{
+    m_isMimeTypeSet = false;
+}
+
+// filePath
+
+std::string MessageAttachment::getFilePath()
+{
+    return m_filePath;
+}
+
+std::string MessageAttachment::getShortFileName() const
+{
+    if (!m_isFilePathSet) {
+        return "";
+    }
+    size_t pos;
+    // find position of last occurence of / sign (get only file name from all path
+    pos = m_filePath.find_last_of("/");
+
+    if ((pos + 1) >= m_filePath.size() || pos == std::string::npos) {
+        return m_filePath;
+    }
+    return m_filePath.substr(pos + 1);
+}
+
+void MessageAttachment::setFilePath(const std::string &value)
+{
+    m_filePath = value;
+    m_isFilePathSet = true;
+}
+
+bool MessageAttachment::isFilePathSet()
+{
+    return m_isFilePathSet;
+}
+
+void MessageAttachment::unsetFilePath()
+{
+    m_isFilePathSet = false;
+}
+
+void MessageAttachment::setIsSaved(bool isSaved)
+{
+    m_isSaved = isSaved;
+}
+
+bool MessageAttachment::isSaved() const
+{
+    return m_isSaved;
+}
+
+std::map<unsigned int, std::string>& MessageAttachment::initializeMIMETypeEnumToStringMap(){
+    static std::map<unsigned int, std::string> enumToString;
+    //0
+    enumToString[MIME_ASTERISK] = "*/*";
+    //1
+    enumToString[MIME_APPLICATION_XML] = "application/xml";
+    enumToString[MIME_APPLICATION_WML_XML] = "application/wml+xml";
+    enumToString[MIME_APPLICATION_XHTML_XML] = "application/xhtml+xml";
+    enumToString[MIME_APPLICATION_JAVA_VM] = "application/java-vm";
+    enumToString[MIME_APPLICATION_SMIL] = "application/smil";
+    enumToString[MIME_APPLICATION_JAVA_ARCHIVE] = "application/java-archive";
+    enumToString[MIME_APPLICATION_JAVA] = "application/java";
+    enumToString[MIME_APPLICATION_OCTET_STREAM] = "application/octet-stream";
+    enumToString[MIME_APPLICATION_STUDIOM] = "application/studiom";
+    enumToString[MIME_APPLICATION_FUNMEDIA] = "application/funMedia";
+    enumToString[MIME_APPLICATION_MSWORD] = "application/msword";
+    enumToString[MIME_APPLICATION_PDF] = "application/pdf";
+    enumToString[MIME_APPLICATION_SDP] = "application/sdp";
+    enumToString[MIME_APPLICATION_RAM] = "application/ram";
+    enumToString[MIME_APPLICATION_ASTERIC] = "application/*";
+    //16
+    enumToString[MIME_APPLICATION_VND_WAP_XHTMLXML] = "application/vnd.wap.xhtml+xml";
+    enumToString[MIME_APPLICATION_VND_WAP_WMLC] = "application/vnd.wap.wmlc";
+    enumToString[MIME_APPLICATION_VND_WAP_WMLSCRIPTC] = "application/vnd.wap.wmlscriptc";
+    enumToString[MIME_APPLICATION_VND_WAP_WTA_EVENTC] = "application/vnd.wap.wta-eventc";
+    enumToString[MIME_APPLICATION_VND_WAP_UAPROF] = "application/vnd.wap.uaprof";
+    enumToString[MIME_APPLICATION_VND_WAP_SIC] = "application/vnd.wap.sic";
+    enumToString[MIME_APPLICATION_VND_WAP_SLC] = "application/vnd.wap.slc";
+    enumToString[MIME_APPLICATION_VND_WAP_COC] = "application/vnd.wap.coc";
+    enumToString[MIME_APPLICATION_VND_WAP_SIA] = "application/vnd.wap.sia";
+    enumToString[MIME_APPLICATION_VND_WAP_CONNECTIVITY_WBXML] = "application/vnd.wap.connectivity-wbxml";
+    enumToString[MIME_APPLICATION_VND_WAP_MULTIPART_FORM_DATA] = "application/vnd.wap.multipart.form-data";
+    enumToString[MIME_APPLICATION_VND_WAP_MULTIPART_BYTERANGES] = "application/vnd.wap.multipart.byteranges";
+    enumToString[MIME_APPLICATION_VND_WAP_MULTIPART_MIXED] = "application/vnd.wap.multipart.mixed";
+    enumToString[MIME_APPLICATION_VND_WAP_MULTIPART_RELATED] = "application/vnd.wap.multipart.related";
+    enumToString[MIME_APPLICATION_VND_WAP_MULTIPART_ALTERNATIVE] = "application/vnd.wap.multipart.alternative";
+    enumToString[MIME_APPLICATION_VND_WAP_MULTIPART_ASTERIC] = "application/vnd.wap.multipart.*";
+    enumToString[MIME_APPLICATION_VND_WAP_WBXML] = "application/vnd.wap.wbxml";
+    enumToString[MIME_APPLICATION_VND_OMA_DD_XML] = "application/vnd.oma.dd+xml";
+    enumToString[MIME_APPLICATION_VND_OMA_DRM_MESSAGE] = "application/vnd.oma.drm.message";
+    enumToString[MIME_APPLICATION_VND_OMA_DRM_CONTENT] = "application/vnd.oma.drm.content";
+    enumToString[MIME_APPLICATION_VND_OMA_DRM_RIGHTS_XML] = "application/vnd.oma.drm.rights+xml";
+    enumToString[MIME_APPLICATION_VND_OMA_DRM_RIGHTS_WBXML] = "application/vnd.oma.drm.rights+wbxml";
+    enumToString[MIME_APPLICATION_VND_OMA_DRM_RO_XML] = "application/vnd.oma.drm.ro+xml";
+    enumToString[MIME_APPLICATION_VND_OMA_DRM_DCF] = "application/vnd.oma.drm.dcf";
+    enumToString[MIME_APPLICATION_VND_OMA_ROAPPDU_XML] = "application/vnd.oma.drm.roap-pdu+xml";
+    enumToString[MIME_APPLICATION_VND_OMA_ROAPTRIGGER_XML] = "application/vnd.oma.drm.roap-trigger+xml";
+    enumToString[MIME_APPLICATION_VND_SMAF] = "application/vnd.smaf";
+    enumToString[MIME_APPLICATION_VND_RN_REALMEDIA] = "application/vnd.rn-realmedia";
+    enumToString[MIME_APPLICATION_VND_SUN_J2ME_JAVA_ARCHIVE] = "application/vnd.sun.j2me.java-archive";
+    enumToString[MIME_APPLICATION_VND_SAMSUNG_THEME] = "application/vnd.samsung.theme";
+    enumToString[MIME_APPLICATION_VND_EXCEL] = "application/vnd.ms-excel";
+    enumToString[MIME_APPLICATION_VND_POWERPOINT] = "application/vnd.ms-powerpoint";
+    enumToString[MIME_APPLICATION_VND_MSWORD] = "applcation/vnd.ms-word";
+    //49
+    enumToString[MIME_APPLICATION_X_HDMLC] = "application/x-hdmlc";
+    enumToString[MIME_APPLICATION_X_X968_USERCERT] = "application/x-x968-user-cert";
+    enumToString[MIME_APPLICATION_X_WWW_FORM_URLENCODED] = "application/x-www-form-urlencoded";
+    enumToString[MIME_APPLICATION_X_SMAF] = "application/x-smaf";
+    enumToString[MIME_APPLICATION_X_FLASH] = "application/x-shockwave-flash";
+    enumToString[MIME_APPLICATION_X_EXCEL] = "application/x-msexcel";
+    enumToString[MIME_APPLICATION_X_POWERPOINT] = "application/x-mspowerpoint";
+    //56
+    enumToString[MIME_AUDIO_BASIC] = "audio/basic";
+    enumToString[MIME_AUDIO_MPEG] = "audio/mpeg";
+    enumToString[MIME_AUDIO_MP3] = "audio/mp3";
+    enumToString[MIME_AUDIO_MPG3] = "audio/mpg3";
+    enumToString[MIME_AUDIO_MPEG3] = "audio/mpeg3";
+    enumToString[MIME_AUDIO_MPG] = "audio/mpg";
+    enumToString[MIME_AUDIO_AAC] = "audio/aac";
+    enumToString[MIME_AUDIO_G72] = "audio/g72";
+    enumToString[MIME_AUDIO_AMR] = "audio/amr";
+    enumToString[MIME_AUDIO_AMR_WB] = "audio/amr-wb";
+    enumToString[MIME_AUDIO_MMF] = "audio/mmf";
+    enumToString[MIME_AUDIO_SMAF] = "audio/smaf";
+    enumToString[MIME_AUDIO_IMELODY] = "audio/iMelody";
+    enumToString[MIME_AUDIO_IMELODY2] = "audio/imelody";
+    enumToString[MIME_AUDIO_MELODY] = "audio/melody";
+    enumToString[MIME_AUDIO_MID] = "audio/mid";
+    enumToString[MIME_AUDIO_MIDI] = "audio/midi";
+    enumToString[MIME_AUDIO_SP_MIDI] = "audio/sp-midi";
+    enumToString[MIME_AUDIO_WAVE] = "audio/wave";
+    enumToString[MIME_AUDIO_WAV] = "audio/wav";
+    enumToString[MIME_AUDIO_3GPP] = "audio/3gpp";
+    enumToString[MIME_AUDIO_MP4] = "audio/mp4";
+    enumToString[MIME_AUDIO_MP4A_LATM] = "audio/MP4A-LATM";
+    enumToString[MIME_AUDIO_M4A] = "audio/m4a";
+    enumToString[MIME_AUDIO_MPEG4] = "audio/mpeg4";
+    enumToString[MIME_AUDIO_WMA] = "audio/wma";
+    enumToString[MIME_AUDIO_XMF] = "audio/xmf";
+    enumToString[MIME_AUDIO_IMY] = "audio/imy";
+    enumToString[MIME_AUDIO_MOBILE_XMF] = "audio/mobile-xmf";
+    //85
+    enumToString[MIME_AUDIO_VND_RN_REALAUDIO] = "audio/vnd.rn-realaudio";
+    //86
+    enumToString[MIME_AUDIO_X_MPEG] = "audio/x-mpeg";
+    enumToString[MIME_AUDIO_X_MP3] = "audio/x-mp3";
+    enumToString[MIME_AUDIO_X_MPEG3] = "audio/x-mpeg3";
+    enumToString[MIME_AUDIO_X_MPG] = "audio/x-mpg";
+    enumToString[MIME_AUDIO_X_AMR] = "audio/x-amr";
+    enumToString[MIME_AUDIO_X_MMF] = "audio/x-mmf";
+    enumToString[MIME_AUDIO_X_SMAF] = "audio/x-smaf";
+    enumToString[MIME_AUDIO_X_IMELODY] = "audio/x-iMelody";
+    enumToString[MIME_AUDIO_X_MIDI] = "audio/x-midi";
+    enumToString[MIME_AUDIO_X_MPEGAUDIO] = "audio/x-mpegaudio";
+    enumToString[MIME_AUDIO_X_PN_REALAUDIO] = "audio/x-pn-realaudio";
+    enumToString[MIME_AUDIO_X_PN_MULTIRATE_REALAUDIO] = "audio/x-pn-multirate-realaudio";
+    enumToString[MIME_AUDIO_X_PN_MULTIRATE_REALAUDIO_LIVE] = "audio/x-pn-multirate-realaudio-live";
+    enumToString[MIME_AUDIO_X_WAVE] = "audio/x-wave";
+    enumToString[MIME_AUDIO_X_WAV] = "audio/x-wav";
+    enumToString[MIME_AUDIO_X_MS_WMA] = "audio/x-ms-wma";
+    enumToString[MIME_AUDIO_X_MID] = "audio/x-mid";
+    enumToString[MIME_AUDIO_X_MS_ASF] = "audio/x-ms-asf";
+    enumToString[MIME_AUDIO_X_XMF] = "audio/x-xmf";
+    //105
+    enumToString[MIME_IMAGE_GIF] = "image/gif";
+    enumToString[MIME_IMAGE_JPEG] = "image/jpeg";
+    enumToString[MIME_IMAGE_JPG] = "image/jpg";
+    enumToString[MIME_IMAGE_TIFF] = "image/tiff";
+    enumToString[MIME_IMAGE_TIF] = "image/tif";
+    enumToString[MIME_IMAGE_PNG] = "image/png";
+    enumToString[MIME_IMAGE_WBMP] = "image/wbmp";
+    enumToString[MIME_IMAGE_PJPEG] = "image/pjpeg";
+    enumToString[MIME_IMAGE_BMP] = "image/bmp";
+    enumToString[MIME_IMAGE_SVG] = "image/svg+xml";
+    enumToString[MIME_IMAGE_SVG1] = "image/svg-xml";
+    //116
+    enumToString[MIME_IMAGE_VND_WAP_WBMP] = "image/vnd.wap.wbmp";
+    enumToString[MIME_IMAGE_VND_TMO_GIF] = "image/vnd.tmo.my5-gif";
+    enumToString[MIME_IMAGE_VND_TMO_JPG] = "image/vnd.tmo.my5-jpg";
+    //119
+    enumToString[MIME_IMAGE_X_BMP] = "image/x-bmp";
+    //120
+    enumToString[MIME_MESSAGE_RFC822] = "message/rfc822";
+    //121
+    enumToString[MIME_MULTIPART_MIXED] = "multipart/mixed";
+    enumToString[MIME_MULTIPART_RELATED] = "multipart/related";
+    enumToString[MIME_MULTIPART_ALTERNATIVE] = "multipart/alternative";
+    enumToString[MIME_MULTIPART_FORM_DATA] = "multipart/form-data";
+    enumToString[MIME_MULTIPART_BYTERANGE] = "multipart/byterange";
+    enumToString[MIME_MULTIPART_REPORT] = "multipart/report";
+    enumToString[MIME_MULTIPART_VOICE_MESSAGE] = "multipart/voice-message";
+    //128
+    enumToString[MIME_TEXT_TXT] = "text/txt";
+    enumToString[MIME_TEXT_HTML] = "text/html";
+    enumToString[MIME_TEXT_PLAIN] = "text/plain";
+    enumToString[MIME_TEXT_CSS] = "text/css";
+    enumToString[MIME_TEXT_XML] = "text/xml";
+    enumToString[MIME_TEXT_IMELODY] = "text/iMelody";
+    //134
+    enumToString[MIME_TEXT_VND_WAP_WMLSCRIPT] = "text/vnd.wap.wmlscript";
+    enumToString[MIME_TEXT_VND_WAP_WML] = "text/vnd.wap.wml";
+    enumToString[MIME_TEXT_VND_WAP_WTA_EVENT] = "text/vnd.wap.wta-event";
+    enumToString[MIME_TEXT_VND_WAP_CONNECTIVITY_XML] = "text/vnd.wap.connectivity-xml";
+    enumToString[MIME_TEXT_VND_WAP_SI] = "text/vnd.wap.si";
+    enumToString[MIME_TEXT_VND_WAP_SL] = "text/vnd.wap.sl";
+    enumToString[MIME_TEXT_VND_WAP_CO] = "text/vnd.wap.co";
+    enumToString[MIME_TEXT_VND_SUN_J2ME_APP_DESCRIPTOR] = "text/vnd.sun.j2me.app-descriptor";
+    //142
+    enumToString[MIME_TEXT_X_HDML] = "text/x-hdml";
+    enumToString[MIME_TEXT_X_VCALENDAR] = "text/x-vCalendar";
+    enumToString[MIME_TEXT_X_VCARD] = "text/x-vCard";
+    enumToString[MIME_TEXT_X_IMELODY] = "text/x-iMelody";
+    enumToString[MIME_TEXT_X_IMELODY2] = "text/x-imelody";
+    enumToString[MIME_TEXT_X_VNOTE] = "text/x-vnote";
+    //148
+    enumToString[MIME_VIDEO_MPEG4] = "video/mpeg4";
+    enumToString[MIME_VIDEO_MP4] = "video/mp4";
+    enumToString[MIME_VIDEO_H263] = "video/h263";
+    enumToString[MIME_VIDEO_3GPP] = "video/3gpp";
+    enumToString[MIME_VIDEO_3GP] = "video/3gp";
+    enumToString[MIME_VIDEO_AVI] = "video/avi";
+    enumToString[MIME_VIDEO_SDP] = "video/sdp";
+    enumToString[MIME_VIDEO_MP4_ES] = "video/mp4v-es";
+    enumToString[MIME_VIDEO_MPEG] = "video/mpeg";
+    //157
+    enumToString[MIME_VIDEO_VND_RN_REALVIDEO] = "video/vnd.rn-realvideo";
+    enumToString[MIME_VIDEO_VND_RN_REALMEDIA] = "video/vnd.rn-realmedia";
+    //159
+    enumToString[MIME_VIDEO_X_MP4] = "video/x-mp4";
+    enumToString[MIME_VIDEO_X_PV_MP4] = "video/x-pv-mp4";
+    enumToString[MIME_VIDEO_X_PN_REALVIDEO] = "video/x-pn-realvideo";
+    enumToString[MIME_VIDEO_X_PN_MULTIRATE_REALVIDEO] = "video/x-pn-multirate-realvideo";
+    enumToString[MIME_VIDEO_X_MS_WMV] = "video/x-ms-wmv";
+    enumToString[MIME_VIDEO_X_MS_ASF] = "video/x-ms-asf";
+    enumToString[MIME_VIDEO_X_PV_PVX] = "video/x-pv-pvx";
+
+    return enumToString;
+}
+
+std::map<std::string,unsigned int>& MessageAttachment::initializeMIMETypeStringToEnumMap(){
+    static std::map<std::string,unsigned int> stringToEnum;
+    //0
+    stringToEnum["*/*"] = MIME_ASTERISK;
+    //1
+    stringToEnum["application/xml"] = MIME_APPLICATION_XML;
+    stringToEnum["application/wml+xml"] = MIME_APPLICATION_WML_XML;
+    stringToEnum["application/xhtml+xml"] = MIME_APPLICATION_XHTML_XML;
+    stringToEnum["application/java-vm"] = MIME_APPLICATION_JAVA_VM;
+    stringToEnum["application/smil"] = MIME_APPLICATION_SMIL;
+    stringToEnum["application/java-archive"] = MIME_APPLICATION_JAVA_ARCHIVE;
+    stringToEnum["application"] = MIME_APPLICATION_JAVA;
+    stringToEnum["application/octet-stream"] = MIME_APPLICATION_OCTET_STREAM;
+    stringToEnum["application/studiom"] = MIME_APPLICATION_STUDIOM;
+    stringToEnum["application/funMedia"] = MIME_APPLICATION_FUNMEDIA;
+    stringToEnum["application/msword"] = MIME_APPLICATION_MSWORD;
+    stringToEnum["application/pdf"] = MIME_APPLICATION_PDF;
+    stringToEnum["application/sdp"] = MIME_APPLICATION_SDP;
+    stringToEnum["application/ram"] = MIME_APPLICATION_RAM;
+    stringToEnum["application/*"] = MIME_APPLICATION_ASTERIC;
+    //16
+    stringToEnum["application/vnd.wap.xhtml+xml"] = MIME_APPLICATION_VND_WAP_XHTMLXML;
+    stringToEnum["application/vnd.wap.wmlc"] = MIME_APPLICATION_VND_WAP_WMLC;
+    stringToEnum["application/vnd.wap.wmlscriptc"] = MIME_APPLICATION_VND_WAP_WMLSCRIPTC;
+    stringToEnum["application/vnd.wap.wta-eventc"] = MIME_APPLICATION_VND_WAP_WTA_EVENTC;
+    stringToEnum["application/vnd.wap.uaprof"] = MIME_APPLICATION_VND_WAP_UAPROF;
+    stringToEnum["application/vnd.wap.sic"] = MIME_APPLICATION_VND_WAP_SIC;
+    stringToEnum["application/vnd.wap.slc"] = MIME_APPLICATION_VND_WAP_SLC;
+    stringToEnum["application/vnd.wap.coc"] = MIME_APPLICATION_VND_WAP_COC;
+    stringToEnum["application/vnd.wap.sia"] = MIME_APPLICATION_VND_WAP_SIA;
+    stringToEnum["application/vnd.wap.connectivity-wbxml"] = MIME_APPLICATION_VND_WAP_CONNECTIVITY_WBXML;
+    stringToEnum["application/vnd.wap.multipart.form-data"] = MIME_APPLICATION_VND_WAP_MULTIPART_FORM_DATA;
+    stringToEnum["application/vnd.wap.multipart.byteranges"] = MIME_APPLICATION_VND_WAP_MULTIPART_BYTERANGES;
+    stringToEnum["application/vnd.wap.multipart.mixed"] = MIME_APPLICATION_VND_WAP_MULTIPART_MIXED;
+    stringToEnum["application/vnd.wap.multipart.related"] = MIME_APPLICATION_VND_WAP_MULTIPART_RELATED;
+    stringToEnum["application/vnd.wap.multipart.alternative"] = MIME_APPLICATION_VND_WAP_MULTIPART_ALTERNATIVE;
+    stringToEnum["application/vnd.wap.multipart.*"] = MIME_APPLICATION_VND_WAP_MULTIPART_ASTERIC;
+    stringToEnum["application/vnd.wap.wbxml"] = MIME_APPLICATION_VND_WAP_WBXML;
+    stringToEnum["application/vnd.oma.dd+xml"] = MIME_APPLICATION_VND_OMA_DD_XML;
+    stringToEnum["application/vnd.oma.drm.message"] = MIME_APPLICATION_VND_OMA_DRM_MESSAGE;
+    stringToEnum["application/vnd.oma.drm.content"] = MIME_APPLICATION_VND_OMA_DRM_CONTENT;
+    stringToEnum["application/vnd.oma.drm.rights+xml"] = MIME_APPLICATION_VND_OMA_DRM_RIGHTS_XML;
+    stringToEnum["application/vnd.oma.drm.rights+wbxml"] = MIME_APPLICATION_VND_OMA_DRM_RIGHTS_WBXML;
+    stringToEnum["application/vnd.oma.drm.ro+xml"] = MIME_APPLICATION_VND_OMA_DRM_RO_XML;
+    stringToEnum["application/vnd.oma.drm.dcf"] = MIME_APPLICATION_VND_OMA_DRM_DCF;
+    stringToEnum["application/vnd.oma.drm.roap-pdu+xml"] = MIME_APPLICATION_VND_OMA_ROAPPDU_XML;
+    stringToEnum["application/vnd.oma.drm.roap-trigger+xml"] = MIME_APPLICATION_VND_OMA_ROAPTRIGGER_XML;
+    stringToEnum["application/vnd.smaf"] = MIME_APPLICATION_VND_SMAF;
+    stringToEnum["application/vnd.rn-realmedia"] = MIME_APPLICATION_VND_RN_REALMEDIA;
+    stringToEnum["application/vnd.sun.j2me.java-archive"] = MIME_APPLICATION_VND_SUN_J2ME_JAVA_ARCHIVE;
+    stringToEnum["application/vnd.samsung.theme"] = MIME_APPLICATION_VND_SAMSUNG_THEME;
+    stringToEnum["application/vnd.ms-excel"] = MIME_APPLICATION_VND_EXCEL;
+    stringToEnum["application/vnd.ms-powerpoint"] = MIME_APPLICATION_VND_POWERPOINT;
+    stringToEnum["applcation/vnd.ms-word"] = MIME_APPLICATION_VND_MSWORD;
+    //49
+    stringToEnum["application/x-hdmlc"] = MIME_APPLICATION_X_HDMLC;
+    stringToEnum["application/x-x968-user-cert"] = MIME_APPLICATION_X_X968_USERCERT;
+    stringToEnum["application/x-www-form-urlencoded"] = MIME_APPLICATION_X_WWW_FORM_URLENCODED;
+    stringToEnum["application/x-smaf"] = MIME_APPLICATION_X_SMAF;
+    stringToEnum["application/x-shockwave-flash"] = MIME_APPLICATION_X_FLASH;
+    stringToEnum["application/x-msexcel"] = MIME_APPLICATION_X_EXCEL;
+    stringToEnum["application/x-mspowerpoint"] = MIME_APPLICATION_X_POWERPOINT;
+    //56
+    stringToEnum["audio/basic"] = MIME_AUDIO_BASIC;
+    stringToEnum["audio/mpeg"] = MIME_AUDIO_MPEG;
+    stringToEnum["audio/mp3"] = MIME_AUDIO_MP3;
+    stringToEnum["audio/mpg3"] = MIME_AUDIO_MPG3;
+    stringToEnum["audio/mpeg"] = MIME_AUDIO_MPEG3;
+    stringToEnum["audio/mpg"] = MIME_AUDIO_MPG;
+    stringToEnum["audio/aac"] = MIME_AUDIO_AAC;
+    stringToEnum["audio/g72"] = MIME_AUDIO_G72;
+    stringToEnum["audio/amr"] = MIME_AUDIO_AMR;
+    stringToEnum["audio/amr-wb"] = MIME_AUDIO_AMR_WB;
+    stringToEnum["audio/mmf"] = MIME_AUDIO_MMF;
+    stringToEnum["audio/smaf"] = MIME_AUDIO_SMAF;
+    stringToEnum["audio/iMelody"] = MIME_AUDIO_IMELODY;
+    stringToEnum["audio/imelody"] = MIME_AUDIO_IMELODY2;
+    stringToEnum["audio/melody"] = MIME_AUDIO_MELODY;
+    stringToEnum["audio/mid"] = MIME_AUDIO_MID;
+    stringToEnum["audio/midi"] = MIME_AUDIO_MIDI;
+    stringToEnum["audio/sp-midi"] = MIME_AUDIO_SP_MIDI;
+    stringToEnum["audio/wave"] = MIME_AUDIO_WAVE;
+    stringToEnum["audio/wav"] = MIME_AUDIO_WAV;
+    stringToEnum["audio/3gpp"] = MIME_AUDIO_3GPP;
+    stringToEnum["audio/mp4"] = MIME_AUDIO_MP4;
+    stringToEnum["audio/MP4A-LATM"] = MIME_AUDIO_MP4A_LATM;
+    stringToEnum["audio/m4a"] = MIME_AUDIO_M4A;
+    stringToEnum["audio/mpeg4"] = MIME_AUDIO_MPEG4;
+    stringToEnum["audio/wma"] = MIME_AUDIO_WMA;
+    stringToEnum["audio/xmf"] = MIME_AUDIO_XMF;
+    stringToEnum["audio/imy"] = MIME_AUDIO_IMY;
+    stringToEnum["audio/mobile-xmf"] = MIME_AUDIO_MOBILE_XMF;
+    //85
+    stringToEnum["audio/vnd.rn-realaudio"] = MIME_AUDIO_VND_RN_REALAUDIO;
+    //86
+    stringToEnum["audio/x-mpeg"] = MIME_AUDIO_X_MPEG;
+    stringToEnum["audio/x-mp3"] = MIME_AUDIO_X_MP3;
+    stringToEnum["audio/x-mpeg3"] = MIME_AUDIO_X_MPEG3;
+    stringToEnum["audio/x-mpg"] = MIME_AUDIO_X_MPG;
+    stringToEnum["audio/x-amr"] = MIME_AUDIO_X_AMR;
+    stringToEnum["audio/x-mmf"] = MIME_AUDIO_X_MMF;
+    stringToEnum["audio/x-smaf"] = MIME_AUDIO_X_SMAF;
+    stringToEnum["audio/x-iMelody"] = MIME_AUDIO_X_IMELODY;
+    stringToEnum["audio/x-midi"] = MIME_AUDIO_X_MIDI;
+    stringToEnum["audio/x-mpegaudio"] = MIME_AUDIO_X_MPEGAUDIO;
+    stringToEnum["audio/x-pn-realaudio"] = MIME_AUDIO_X_PN_REALAUDIO;
+    stringToEnum["audio/x-pn-multirate-realaudio"] = MIME_AUDIO_X_PN_MULTIRATE_REALAUDIO;
+    stringToEnum["audio/x-pn-multirate-realaudio-live"] = MIME_AUDIO_X_PN_MULTIRATE_REALAUDIO_LIVE;
+    stringToEnum["audio/x-wave"] = MIME_AUDIO_X_WAVE;
+    stringToEnum["audio/x-wav"] = MIME_AUDIO_X_WAV;
+    stringToEnum["audio/x-ms-wma"] = MIME_AUDIO_X_MS_WMA;
+    stringToEnum["audio/x-mid"] = MIME_AUDIO_X_MID;
+    stringToEnum["audio/x-ms-asf"] = MIME_AUDIO_X_MS_ASF;
+    stringToEnum["audio/x-xmf"] = MIME_AUDIO_X_XMF;
+    //105
+    stringToEnum["image/gif"] = MIME_IMAGE_GIF;
+    stringToEnum["image/jpeg"] = MIME_IMAGE_JPEG;
+    stringToEnum["image/jpga"] = MIME_IMAGE_JPG;
+    stringToEnum["image/tiff"] = MIME_IMAGE_TIFF;
+    stringToEnum["image/tif"] = MIME_IMAGE_TIF;
+    stringToEnum["image/png"] = MIME_IMAGE_PNG;
+    stringToEnum["image/wbmp"] = MIME_IMAGE_WBMP;
+    stringToEnum["image/pjpeg"] = MIME_IMAGE_PJPEG;
+    stringToEnum["image/bmp"] = MIME_IMAGE_BMP;
+    stringToEnum["image/svg+xml"] = MIME_IMAGE_SVG;
+    stringToEnum["image/svg-xml"] = MIME_IMAGE_SVG1;
+    //116
+    stringToEnum["image/vnd.wap.wbmp"] = MIME_IMAGE_VND_WAP_WBMP;
+    stringToEnum["image/vnd.tmo.my5-gif"] = MIME_IMAGE_VND_TMO_GIF;
+    stringToEnum["image/vnd.tmo.my5-jpg"] = MIME_IMAGE_VND_TMO_JPG;
+    //119
+    stringToEnum["image/x-bmp"] = MIME_IMAGE_X_BMP;
+    //120
+    stringToEnum["message/rfc822"] = MIME_MESSAGE_RFC822;
+    //121
+    stringToEnum["multipart/mixed"] = MIME_MULTIPART_MIXED;
+    stringToEnum["multipart/related"] = MIME_MULTIPART_RELATED;
+    stringToEnum["multipart/alternative"] = MIME_MULTIPART_ALTERNATIVE;
+    stringToEnum["multipart/form-data"] = MIME_MULTIPART_FORM_DATA;
+    stringToEnum["multipart/byterange"] = MIME_MULTIPART_BYTERANGE;
+    stringToEnum["multipart/report"] = MIME_MULTIPART_REPORT;
+    stringToEnum["multipart/voice-message"] = MIME_MULTIPART_VOICE_MESSAGE;
+    //128
+    stringToEnum["text/txt"] = MIME_TEXT_TXT;
+    stringToEnum["text/html"] = MIME_TEXT_HTML;
+    stringToEnum["text/plain"] = MIME_TEXT_PLAIN;
+    stringToEnum["text/css"] = MIME_TEXT_CSS;
+    stringToEnum["text/xml"] = MIME_TEXT_XML;
+    stringToEnum["text/iMelody"] = MIME_TEXT_IMELODY;
+    //134
+    stringToEnum["text/vnd.wap.wmlscript"] = MIME_TEXT_VND_WAP_WMLSCRIPT;
+    stringToEnum["text/vnd.wap.wml"] = MIME_TEXT_VND_WAP_WML;
+    stringToEnum["text/vnd.wap.wta-event"] = MIME_TEXT_VND_WAP_WTA_EVENT;
+    stringToEnum["text/vnd.wap.connectivity-xml"] = MIME_TEXT_VND_WAP_CONNECTIVITY_XML;
+    stringToEnum["text/vnd.wap.si"] = MIME_TEXT_VND_WAP_SI;
+    stringToEnum["text/vnd.wap.sl"] = MIME_TEXT_VND_WAP_SL;
+    stringToEnum["text/vnd.wap.co"] = MIME_TEXT_VND_WAP_CO;
+    stringToEnum["text/vnd.sun.j2me.app-descriptor"] = MIME_TEXT_VND_SUN_J2ME_APP_DESCRIPTOR;
+    //142
+    stringToEnum["text/x-hdml"] = MIME_TEXT_X_HDML;
+    stringToEnum["text/x-vCalendar"] = MIME_TEXT_X_VCALENDAR;
+    stringToEnum["text/x-vCard"] = MIME_TEXT_X_VCARD;
+    stringToEnum["text/x-iMelody"] = MIME_TEXT_X_IMELODY;
+    stringToEnum["text/x-imelody"] = MIME_TEXT_X_IMELODY2;
+    stringToEnum["text/x-vnote"] = MIME_TEXT_X_VNOTE;
+    //148
+    stringToEnum["video/mpeg4"] = MIME_VIDEO_MPEG4;
+    stringToEnum["video/mp4"] = MIME_VIDEO_MP4;
+    stringToEnum["video/h263"] = MIME_VIDEO_H263;
+    stringToEnum["video/3gpp"] = MIME_VIDEO_3GPP;
+    stringToEnum["video/3gp"] = MIME_VIDEO_3GP;
+    stringToEnum["video/avi"] = MIME_VIDEO_AVI;
+    stringToEnum["video/sdp"] = MIME_VIDEO_SDP;
+    stringToEnum["video/mp4v-es"] = MIME_VIDEO_MP4_ES;
+    stringToEnum["video/mpeg"] = MIME_VIDEO_MPEG;
+    //157
+    stringToEnum["video/vnd.rn-realvideo"] = MIME_VIDEO_VND_RN_REALVIDEO;
+    stringToEnum["video/vnd.rn-realmedia"] = MIME_VIDEO_VND_RN_REALMEDIA;
+    //159
+    stringToEnum["video/x-mp4"] = MIME_VIDEO_X_MP4;
+    stringToEnum["video/x-pv-mp4"] = MIME_VIDEO_X_PV_MP4;
+    stringToEnum["video/x-pn-realvideo"] = MIME_VIDEO_X_PN_REALVIDEO;
+    stringToEnum["video/x-pn-multirate-realvideo"] = MIME_VIDEO_X_PN_MULTIRATE_REALVIDEO;
+    stringToEnum["video/x-ms-wmv"] = MIME_VIDEO_X_MS_WMV;
+    stringToEnum["video/x-ms-asf"] = MIME_VIDEO_X_MS_ASF;
+    stringToEnum["video/x-pv-pvx"] = MIME_VIDEO_X_PV_PVX;
+    stringToEnum[""] = MIME_UNKNOWN;
+
+    return stringToEnum;
+}
+
+
+unsigned int MessageAttachment::MIMETypeStringToEnum(std::string str){
+    std::map<std::string,unsigned int>::iterator it = MIMETypeStringToEnumMap.find(str);
+    if(it != MIMETypeStringToEnumMap.end()){
+        return it->second;
+    }
+    return MIME_UNKNOWN;
+}
+
+std::string MessageAttachment::MIMETypeEnumToString(unsigned int num){
+    std::map<unsigned int, std::string>::iterator it = MIMETypeEnumToStringMap.find(num);
+    if(it != MIMETypeEnumToStringMap.end()){
+        return it->second;
+    }
+    return std::string();
+}
+
+void MessageAttachment::updateWithAttachmentData(
+        const email_attachment_data_t& attachment_data)
+{
+    setId(attachment_data.attachment_id);
+    setMessageId(attachment_data.mail_id);
+    if(attachment_data.attachment_mime_type) {
+        setMimeType(attachment_data.attachment_mime_type);
+    }
+
+    bool isSaved = false;
+    if (attachment_data.attachment_path) {
+        setFilePath(attachment_data.attachment_path);
+
+        LOGD("save status: %d", attachment_data.save_status);
+        LOGD("attachment_size : %d", attachment_data.attachment_size);
+        isSaved = attachment_data.save_status;
+    }
+
+    setIsSaved(isSaved);
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/MessageAttachment.h b/src/Messaging/MessageAttachment.h
new file mode 100755 (executable)
index 0000000..9ed4cfe
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageAttachment.h
+ */
+
+#ifndef __TIZEN_MESSAGE_ATTACHMENT_H__
+#define __TIZEN_MESSAGE_ATTACHMENT_H__
+
+#include <string>
+#include <memory>
+#include <vector>
+#include <map>
+#include <msg_types.h>
+#include <email-types.h>
+#include "JSVector.h"
+#include "JSMessageAttachment.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageAttachment;
+
+struct MessageAttachmentHolder {
+    std::shared_ptr<MessageAttachment> ptr;
+};
+
+typedef Common::JSObjectVector<std::shared_ptr<MessageAttachment>,
+    JSMessageAttachment> JSAttachmentsVector;
+
+typedef std::vector<std::shared_ptr<MessageAttachment>> AttachmentPtrVector;
+
+class MessageAttachment {
+private:
+    static std::map<std::string,unsigned int>& MIMETypeStringToEnumMap;
+    static std::map<unsigned int, std::string>& MIMETypeEnumToStringMap;
+    static std::map<std::string,unsigned int>& initializeMIMETypeStringToEnumMap();
+    static std::map<unsigned int, std::string>& initializeMIMETypeEnumToStringMap();
+    int m_id;
+    bool m_isIdSet;
+    int m_messageId;
+    bool m_isMessageIdSet;
+    std::string m_mimeType;
+    bool m_isMimeTypeSet;
+    std::string m_filePath;
+    bool m_isFilePathSet;
+    bool m_isSaved;
+public:
+    MessageAttachment();
+    ~MessageAttachment();
+
+    int getId();
+    void setId(int value);
+    bool isIdSet();
+    void unsetId();
+    int getMessageId();
+    void setMessageId(int value);
+    bool isMessageIdSet();
+    void unsetMessageId();
+    std::string getMimeType();
+    void setMimeType(const std::string &value);
+    bool isMimeTypeSet();
+    void unsetMimeType();
+    std::string getFilePath();
+    std::string getShortFileName() const;
+    void setFilePath(const std::string &value);
+    bool isFilePathSet();
+    void unsetFilePath();
+    void setIsSaved(const bool isSaved);
+    bool isSaved() const;
+    static unsigned int MIMETypeStringToEnum(std::string str);
+    static std::string MIMETypeEnumToString(unsigned int num);
+
+    /**
+     * This methods updates:
+     *      setId(attachment_data.attachment_id);
+     *      setMessageId(attachment_data.mail_id);
+     *      setMimeType(attachment_data.attachment_mime_type);
+     *      setFilePath(attachment_data.attachment_path);
+     */
+    void updateWithAttachmentData(const email_attachment_data_t& attachment_data);
+};
+
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_MESSAGE_ATTACHMENT_H__
diff --git a/src/Messaging/MessageBody.cpp b/src/Messaging/MessageBody.cpp
new file mode 100644 (file)
index 0000000..d203ab7
--- /dev/null
@@ -0,0 +1,143 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageBody.cpp
+ */
+
+#include "MessageBody.h"
+#include "MessagingUtil.h"
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageBody::MessageBody() : m_messageId(1),
+                             m_messageId_set(false),
+                             m_loaded(false),
+                             m_plainBody(""),
+                             m_htmlBody("")
+{
+}
+
+MessageBody::~MessageBody()
+{
+}
+
+// messageId
+
+int MessageBody::getMessageId() const
+{
+
+    return m_messageId;
+}
+
+void MessageBody::setMessageId(int value)
+{
+    m_messageId = value;
+    m_messageId_set = true;
+}
+
+// loaded
+
+bool MessageBody::getLoaded() const
+{
+    return m_loaded;
+}
+
+void MessageBody::setLoaded(bool value)
+{
+    m_loaded = value;
+}
+
+// plainBody
+
+std::string MessageBody::getPlainBody() const
+{
+    return m_plainBody;
+}
+
+void MessageBody::setPlainBody(const std::string &value)
+{
+    m_plainBody = value;
+}
+
+// htmlBody
+
+std::string MessageBody::getHtmlBody() const
+{
+    return m_htmlBody;
+}
+
+void MessageBody::setHtmlBody(const std::string &value)
+{
+    m_htmlBody = value;
+}
+
+// inlineAttachments
+
+AttachmentPtrVector MessageBody::getInlineAttachments() const
+{
+    return m_inlineAttachments;
+}
+
+JSObjectRef MessageBody::getJSInlineAttachments(JSContextRef global_ctx)
+{
+    return m_inlineAttachments.getJSArray(global_ctx);
+}
+
+void MessageBody::setInlineAttachments(const AttachmentPtrVector& attachments)
+{
+    m_inlineAttachments = attachments;
+}
+
+// ***  support for optional, nullable (at JS layer) attibutes
+bool MessageBody::is_message_id_set() const
+{
+    return m_messageId_set;
+}
+
+void MessageBody::updateBody(email_mail_data_t& mail)
+{
+    LOGD("Enter");
+    setMessageId(mail.mail_id);
+    setLoaded(mail.body_download_status);
+
+    if (mail.file_path_plain) {
+        try {
+            LOGD("Plain body");
+            setPlainBody(MessagingUtil::loadFileContentToString(mail.file_path_plain));
+        } catch (...) {
+            LOGE("Fail to open plain body.");
+            throw Common::UnknownException("Fail to open plain body.");
+        }
+    }
+
+    if (mail.file_path_html) {
+        try {
+            LOGD("Html body");
+            setHtmlBody(MessagingUtil::loadFileContentToString(mail.file_path_html));
+        } catch (...) {
+            LOGE("Fail to open html body.");
+            throw Common::UnknownException("Fail to open html body.");
+        }
+    }
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/MessageBody.h b/src/Messaging/MessageBody.h
new file mode 100644 (file)
index 0000000..1fb297a
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageBody.h
+ */
+
+#ifndef __TIZEN_MESSAGING_MESSAGE_BODY_H__
+#define __TIZEN_MESSAGING_MESSAGE_BODY_H__
+
+#include <vector>
+#include <string>
+#include "MessageAttachment.h"
+#include <email-types.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageBody;
+
+struct MessageBodyHolder {
+    std::shared_ptr<MessageBody> ptr;
+};
+
+class MessageBody {
+public:
+    explicit MessageBody();
+    ~MessageBody();
+    int getMessageId()  const;
+    void setMessageId(int value);
+    bool getLoaded()  const;
+    void setLoaded(bool value);
+    std::string getPlainBody()  const;
+    void setPlainBody(const std::string &value);
+    std::string getHtmlBody()  const;
+    void setHtmlBody(const std::string &value);
+    AttachmentPtrVector getInlineAttachments()  const;
+    JSObjectRef getJSInlineAttachments(JSContextRef global_ctx);
+    void setInlineAttachments(const AttachmentPtrVector& attachments);
+
+    // support for optional, nullable (at JS layer) attibutes
+    bool is_message_id_set() const;
+    /**
+     * Updates body with data from email_mail_data_t structure.
+     * @param mail
+     */
+    void updateBody(email_mail_data_t& mail);
+
+private:
+    int m_messageId;
+    bool m_messageId_set;
+    bool m_loaded;
+    std::string m_plainBody;
+    std::string m_htmlBody;
+    JSAttachmentsVector m_inlineAttachments;
+    JSContextRef m_context;
+};
+
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_MESSAGING_MESSAGE_BODY_H__
diff --git a/src/Messaging/MessageCallbackUserData.cpp b/src/Messaging/MessageCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..97539b6
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MessageCallbackUserData.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+
+MessageCallbackUserData::MessageCallbackUserData(JSContextRef globalCtx):
+        CallbackUserData(globalCtx),
+        m_is_error(false)
+{
+}
+
+MessageCallbackUserData::~MessageCallbackUserData() {
+}
+
+void MessageCallbackUserData::setMessage(std::shared_ptr<Message> message) {
+    m_message = message;
+}
+
+std::shared_ptr<Message> MessageCallbackUserData::getMessage() const {
+    return m_message;
+}
+
+void MessageCallbackUserData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool MessageCallbackUserData::isError() const
+{
+    return m_is_error;
+}
+
+std::string MessageCallbackUserData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string MessageCallbackUserData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void MessageCallbackUserData::setAccountId(int account_id){
+    m_account_id = account_id;
+}
+
+int MessageCallbackUserData::getAccountId() const
+{
+    return m_account_id;
+}
+
+}//Messaging
+}//DeviceAPI
diff --git a/src/Messaging/MessageCallbackUserData.h b/src/Messaging/MessageCallbackUserData.h
new file mode 100644 (file)
index 0000000..eb11724
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ADD_DRAFT_MESSAGE_CALLBACK_USER_DATA_H
+#define __TIZEN_ADD_DRAFT_MESSAGE_CALLBACK_USER_DATA_H
+
+#include <CallbackUserData.h>
+#include <memory>
+#include <string>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class Message;
+
+class MessageCallbackUserData: public Common::CallbackUserData {
+public:
+    MessageCallbackUserData(JSContextRef globalCtx);
+    virtual ~MessageCallbackUserData();
+
+    void setMessage(std::shared_ptr<Message> message);
+    std::shared_ptr<Message> getMessage() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    void setAccountId(int account_id);
+    int getAccountId() const;
+private:
+    std::shared_ptr<Message> m_message;
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+    int m_account_id;
+};
+
+}//Messaging
+}//DeviceAPI
+
+#endif /* __TIZEN_ADD_DRAFT_MESSAGE_CALLBACK_USER_DATA_H */
+
diff --git a/src/Messaging/MessageConversation.cpp b/src/Messaging/MessageConversation.cpp
new file mode 100644 (file)
index 0000000..7ce8d4f
--- /dev/null
@@ -0,0 +1,600 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageConversation.cpp
+ */
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "Message.h"
+#include "MessageConversation.h"
+#include "MessagingUtil.h"
+#include "JSMessageConversation.h"
+#include "MessagingUtil.h"
+
+#define MAX_THREAD_DATA_LEN 128
+
+namespace DeviceAPI {
+
+using namespace Tizen;
+
+namespace Messaging {
+
+// *** constructor
+MessageConversation::MessageConversation():
+    m_conversation_id(-1),
+    m_conversation_type(UNDEFINED),
+    m_count(0),
+    m_unread_messages(0),
+    m_is_read(false)
+{
+    LOGD("Message Conversation constructor.");
+}
+
+MessageConversation::~MessageConversation()
+{
+    LOGD("Message Conversation destructor.");
+}
+// *** attributes getters
+int MessageConversation::getConversationId() const
+{
+    return m_conversation_id;
+}
+
+MessageType MessageConversation::getType() const
+{
+    return m_conversation_type;
+}
+
+time_t MessageConversation::getTimestamp() const
+{
+    return m_timestamp;
+}
+
+unsigned long MessageConversation::getMessageCount() const
+{
+    return m_count;
+}
+
+unsigned long MessageConversation::getUnreadMessages() const
+{
+    return m_unread_messages;
+}
+
+std::string MessageConversation::getPreview() const
+{
+    return m_preview;
+}
+
+std::string MessageConversation::getSubject() const
+{
+    return m_conversation_subject;
+}
+
+bool MessageConversation::getIsRead() const
+{
+    return m_is_read;
+}
+
+std::string MessageConversation::getFrom() const
+{
+    return m_from;
+}
+
+std::vector<std::string> MessageConversation::getTo() const
+{
+    return m_to;
+}
+
+std::vector<std::string> MessageConversation::getCC() const
+{
+    return m_cc;
+}
+
+std::vector<std::string> MessageConversation::getBCC() const
+{
+    return m_bcc;
+}
+
+int MessageConversation::getLastMessageId() const
+{
+    return m_last_message_id;
+}
+
+std::shared_ptr<MessageConversation> MessageConversation::convertMsgConversationToObject(
+        unsigned int threadId, msg_handle_t handle)
+{
+    std::shared_ptr<MessageConversation> conversation (new MessageConversation());
+
+    msg_struct_t msgInfo = NULL;
+    msg_struct_t sendOpt = NULL;
+
+    msg_struct_t msg_thread = NULL;
+
+    msg_struct_list_s convViewList;
+    msg_list_handle_t addr_list = NULL;
+    msg_struct_t addr_info = NULL;
+
+    msg_error_t err = MSG_SUCCESS;
+
+    int tempInt;
+    bool tempBool;
+    int nToCnt;
+    unsigned int lastMsgIndex = 0;
+    char msgData[MAX_THREAD_DATA_LEN] = {0,};
+
+    try {
+        msgInfo = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+        sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
+
+        conversation->m_conversation_id = threadId;
+
+        msg_thread = msg_create_struct(MSG_STRUCT_THREAD_INFO);
+        err = msg_get_thread(handle, conversation->m_conversation_id, msg_thread);
+        if (err != MSG_SUCCESS)
+        {
+            LOGE("ret: %d", err);
+            MessagingUtil::throwMsgException(err, "msg_get_thread()");
+        }
+        int ret = msg_get_int_value(msg_thread, MSG_THREAD_MSG_TYPE_INT, &tempInt);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+        }
+        switch(tempInt)
+        {
+            case MSG_TYPE_SMS:
+            case MSG_TYPE_SMS_CB:
+            case MSG_TYPE_SMS_JAVACB:
+            case MSG_TYPE_SMS_WAPPUSH:
+            case MSG_TYPE_SMS_MWI:
+            case MSG_TYPE_SMS_SYNCML:
+            case MSG_TYPE_SMS_REJECT:
+                conversation->m_conversation_type = SMS;
+                break;
+            case MSG_TYPE_MMS:
+            case MSG_TYPE_MMS_JAVA:
+            case MSG_TYPE_MMS_NOTI:
+                conversation->m_conversation_type = MMS;
+                break;
+        }
+
+        ret = msg_get_int_value(msg_thread, MSG_THREAD_MSG_TIME_INT, &tempInt);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+        }
+        conversation->m_timestamp = tempInt;
+
+        ret = msg_get_int_value(msg_thread, MSG_THREAD_UNREAD_COUNT_INT, &tempInt);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+        }
+        conversation->m_unread_messages = tempInt;
+
+        ret = msg_get_str_value(msg_thread, MSG_THREAD_MSG_DATA_STR, msgData, MAX_THREAD_DATA_LEN);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+        }
+
+        conversation->m_preview = msgData;
+
+        err = msg_get_conversation_view_list(handle, conversation->m_conversation_id,
+            &convViewList);
+        if (err != MSG_SUCCESS)
+        {
+            LOGE("ret: %d", err);
+            MessagingUtil::throwMsgException(err, "msg_get_conversation_view_list()");
+        }
+
+        lastMsgIndex = convViewList.nCount - 1;
+        conversation->m_count = convViewList.nCount;
+
+        ret = msg_get_bool_value(convViewList.msg_struct_info[lastMsgIndex], MSG_CONV_MSG_READ_BOOL, &tempBool);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_bool_value()").c_str());
+        }
+        conversation->m_is_read = tempBool;
+
+        ret = msg_get_int_value(convViewList.msg_struct_info[lastMsgIndex], MSG_CONV_MSG_ID_INT, &tempInt);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+        }
+        conversation->m_last_message_id = tempInt;
+
+        ret = msg_get_message(handle, conversation->m_last_message_id, msgInfo, sendOpt);
+        if (MSG_SUCCESS != ret)
+        {
+            LOGE("ret: %d", ret);
+            MessagingUtil::throwMsgException(ret, "msg_get_message()");
+        }
+
+        ret = msg_get_int_value(convViewList.msg_struct_info[lastMsgIndex], MSG_CONV_MSG_DIRECTION_INT, &tempInt);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+        }
+
+        ret = msg_get_list_handle(msgInfo, MSG_MESSAGE_ADDR_LIST_HND, (void **)&addr_list);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_list_handle()").c_str());
+        }
+
+        nToCnt = msg_list_length(addr_list);
+
+        if (MSG_DIRECTION_TYPE_MT == tempInt)
+        {
+            if (nToCnt > 0 && nToCnt < MAX_TO_ADDRESS_CNT )
+            {
+                char strNumber[MAX_ADDRESS_VAL_LEN] = {0,};
+                addr_info = (msg_struct_t)msg_list_nth_data(addr_list, nToCnt-1);
+                ret = msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR, strNumber, MAX_ADDRESS_VAL_LEN);
+                if (MSG_SUCCESS != ret) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+                }
+
+                if (strNumber[0] != '\0')
+                {
+                    conversation->m_from = strNumber;
+                }
+                else
+                {
+                    LOGD("address is null ");
+                }
+            }
+            else
+            {
+                LOGD("address count index fail");
+            }
+        }
+        else
+        {
+            if (nToCnt > 0 && nToCnt < MAX_TO_ADDRESS_CNT )
+            {
+                for (int index = 0; index < nToCnt; index++)
+                {
+                    addr_info = (msg_struct_t)msg_list_nth_data(addr_list, index);
+                    char strNumber[MAX_ADDRESS_VAL_LEN] = {0,};
+                    ret = msg_get_str_value(addr_info, MSG_ADDRESS_INFO_ADDRESS_VALUE_STR, strNumber, MAX_ADDRESS_VAL_LEN);
+                    if (MSG_SUCCESS != ret) {
+                        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+                    }
+
+                    conversation->m_to.push_back(strNumber);
+                }
+            }
+            else
+            {
+                LOGD("address fetch fail");
+            }
+        }
+
+        char strTemp[MAX_SUBJECT_LEN] = {0};
+        ret = msg_get_str_value(msgInfo, MSG_MESSAGE_SUBJECT_STR, strTemp, MAX_SUBJECT_LEN);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_str_value()").c_str());
+        }
+        conversation->m_conversation_subject = strTemp;
+        ret = msg_release_list_struct(&convViewList);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_list_struct()").c_str());
+        }
+        ret = msg_release_struct(&msgInfo);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        ret = msg_release_struct(&sendOpt);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        ret = msg_release_struct(&msg_thread);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+    } catch (const Common::BasePlatformException& ex) {
+        int ret = msg_release_list_struct(&convViewList);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_list_struct()").c_str());
+        }
+        ret = msg_release_struct(&msgInfo);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        ret = msg_release_struct(&sendOpt);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        ret = msg_release_struct(&msg_thread);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        LOGE("%s (%s)", (ex.getName()).c_str(), (ex.getMessage()).c_str());
+        throw Common::UnknownException("Unable to convert short message conversation.");
+    } catch (...) {
+        int ret = msg_release_list_struct(&convViewList);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_list_struct()").c_str());
+        }
+        ret = msg_release_struct(&msgInfo);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        ret = msg_release_struct(&sendOpt);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        ret = msg_release_struct(&msg_thread);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        throw Common::UnknownException("Unable to convert short message conversation.");
+    }
+
+    return conversation;
+}
+
+std::shared_ptr<MessageConversation> MessageConversation::convertEmailConversationToObject(
+        unsigned int threadId)
+{
+    std::shared_ptr<MessageConversation> conversation (new MessageConversation());
+
+    email_mail_list_item_t *resultMail = NULL;
+
+    int ret = email_get_thread_information_ex(threadId, &resultMail);
+    if( EMAIL_ERROR_NONE != ret )
+    {
+        LOGE("ret: %d", ret);
+        MessagingUtil::throwEmailException(ret, "email_get_thread_information_ex()");
+    } else {
+        if (!resultMail)
+        {
+            LOGE("Data is null");
+            throw Common::UnknownException("Get email data fail.");
+        }
+
+        email_mail_data_t* mailData = NULL;
+        ret = email_get_mail_data(resultMail->mail_id, &mailData);
+        if ( EMAIL_ERROR_NONE != ret )
+        {
+            free(resultMail);
+            LOGE("ret: %d", ret);
+            MessagingUtil::throwEmailException(ret, "email_get_mail_data()");
+        }
+
+        if (!mailData) {
+            free(resultMail);
+            LOGE("Get email data fail.");
+            throw Common::UnknownException("Get email data fail.");
+        }
+
+        int index = 0;
+        int count = 0;
+        conversation->m_unread_messages = 0;
+        email_mail_list_item_t *mailList = NULL;
+
+        ret = email_get_mail_list(mailData->account_id, 0, threadId, 0,
+                resultMail->thread_item_count, EMAIL_SORT_DATETIME_HIGH, &mailList, &count);
+        if ( EMAIL_ERROR_NONE != ret )
+        {
+            int err = email_free_mail_data(&mailData , 1);
+            if (MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mail_data()").c_str());
+            }
+            free(resultMail);
+            LOGE("ret: %d", ret);
+            MessagingUtil::throwEmailException(ret, "email_get_mail_list()");
+        }
+
+        for (index = 0; index < count; index++)
+        {
+            if (mailList[index].flags_seen_field)
+            {
+                conversation->m_unread_messages++;
+            }
+        }
+        conversation->m_count = resultMail->thread_item_count;
+
+        conversation->m_conversation_id = threadId;
+
+        conversation->m_conversation_type = EMAIL;
+
+        conversation->m_timestamp = resultMail->date_time;
+
+        if (resultMail->preview_text[0] != '\0')
+        {
+            conversation->m_preview = resultMail->preview_text;
+        }
+
+        if (resultMail->subject[0] != '\0')
+        {
+            conversation->m_conversation_subject = resultMail->subject;
+        }
+
+        conversation->m_is_read = (bool)resultMail->flags_seen_field;
+
+        if (resultMail->full_address_from[0] != '\0')
+        {
+            conversation->m_from = MessagingUtil::extractSingleEmailAddress(
+                    resultMail->full_address_from);
+        }
+
+        if (mailData->full_address_to != NULL)
+        {
+            conversation->m_to = Message::getEmailRecipientsFromStruct(
+                mailData->full_address_to);
+        }
+
+        if (mailData->full_address_cc != NULL)
+        {
+            conversation->m_cc = Message::getEmailRecipientsFromStruct(
+                mailData->full_address_cc);
+        }
+
+        if (mailData->full_address_bcc != NULL)
+        {
+            conversation->m_bcc = Message::getEmailRecipientsFromStruct(
+                mailData->full_address_bcc);
+        }
+
+        conversation->m_last_message_id = resultMail->mail_id;
+
+        if (mailData != NULL)
+        {
+            ret = email_free_mail_data(&mailData , 1);
+            if( EMAIL_ERROR_NONE != ret) {
+                LOGW("%s", MessagingUtil::getEmailErrorMessage(ret, "email_free_mail_data()").c_str());
+            }
+        }
+    }
+
+    if (resultMail != NULL)
+    {
+        free(resultMail);
+    }
+
+    return conversation;
+}
+
+std::shared_ptr<MessageConversation> MessageConversation::convertConversationStructToObject(
+        unsigned int threadId, MessageType msgType, msg_handle_t handle)
+{
+    std::shared_ptr<MessageConversation> conversation (new MessageConversation());
+
+    if (EMAIL == msgType) {
+        conversation = convertEmailConversationToObject(threadId);
+    } else {
+        if(handle != NULL) {
+            conversation = convertMsgConversationToObject(threadId, handle);
+        } else {
+            LOGE("Handle has not been sent.");
+            throw Common::UnknownException("Handle has not been sent.");
+        }
+    }
+
+    return conversation;
+}
+
+void MessageConversation::setConversationId(int id)
+{
+    m_conversation_id = id;
+}
+void MessageConversation::setMessageCount(int count)
+{
+    m_count = count;
+}
+
+void MessageConversation::setUnreadMessages(int count)
+{
+    m_unread_messages = count;
+}
+
+/**
+ *
+ *  Attribute      | Attribute filter| Attribute range filter
+ *                 | supported       | supported
+ * ----------------+-----------------+------------------------
+ * id              | Yes             | No
+ * type            | Yes             | No
+ * timestamp       | No              | Yes
+ * messageCount    | Yes             | No
+ * unreadMessages  | Yes             | No
+ * preview         | Yes             | No
+ * subject         | No              | No
+ * isRead          | No              | No
+ * from            | Yes             | No
+ * to              | Yes             | No
+ * cc              | No              | No
+ * bcc             | No              | No
+ * lastMessageId   | No              | No
+ */
+
+namespace CONVERSATION_FILTER_ATTRIBUTE {
+const std::string ID = JSMessageConversationKeys::MESSAGE_CONVERSATION_ID;
+const std::string TYPE = JSMessageConversationKeys::MESSAGE_CONVERSATION_TYPE;
+const std::string TIMESTAMP = JSMessageConversationKeys::MESSAGE_CONVERSATION_TIMESTAMP;
+const std::string MESSAGE_COUNT =
+        JSMessageConversationKeys::MESSAGE_CONVERSATION_MSG_COUNT;
+
+const std::string UNREAD_MESSAGES =
+        JSMessageConversationKeys::MESSAGE_CONVERSATION_UNREAD_MSG;
+
+const std::string PREVIEW = JSMessageConversationKeys::MESSAGE_CONVERSATION_PREVIEW;
+const std::string FROM = JSMessageConversationKeys::MESSAGE_CONVERSATION_FROM;
+const std::string TO = JSMessageConversationKeys::MESSAGE_CONVERSATION_TO;
+} //namespace CONVERSATION_FILTER_ATTRIBUTE
+
+bool MessageConversation::isMatchingAttribute(const std::string& attribute_name,
+            const FilterMatchFlag match_flag,
+            AnyPtr match_value) const
+{
+    LOGD("Entered");
+    auto key = match_value->toString();
+    LOGD("attribute_name: %s match_flag:%d match_value:%s", attribute_name.c_str(),
+            match_flag, key.c_str());
+
+    using namespace CONVERSATION_FILTER_ATTRIBUTE;
+
+    if(ID == attribute_name) {
+        return FilterUtils::isStringMatching(key, std::to_string(getConversationId()),
+                match_flag);
+    }
+    else if(TYPE == attribute_name) {
+        const MessageType msg_type = getType();
+        const std::string msg_type_str = MessagingUtil::messageTypeToString(msg_type);
+        return FilterUtils::isStringMatching(key, msg_type_str, match_flag);
+    }
+    else if(MESSAGE_COUNT == attribute_name) {
+        return FilterUtils::isStringMatching(key, std::to_string(getMessageCount()),
+                match_flag);
+    }
+    else if(UNREAD_MESSAGES == attribute_name) {
+        return FilterUtils::isStringMatching(key, std::to_string(getUnreadMessages()),
+                match_flag);
+    }
+    else if(PREVIEW == attribute_name) {
+        return FilterUtils::isStringMatching(key, getPreview(), match_flag);
+    }
+    else if(FROM == attribute_name) {
+        return FilterUtils::isStringMatching(key, getFrom(), match_flag);
+    }
+    else if(TO == attribute_name) {
+        return FilterUtils::isAnyStringMatching(key, getTo(), match_flag);
+    }
+    else {
+        LOGD("attribute:%s is NOT SUPPORTED", attribute_name.c_str());
+    }
+
+    return false;
+}
+
+bool MessageConversation::isMatchingAttributeRange(const std::string& attribute_name,
+            AnyPtr initial_value,
+            AnyPtr end_value) const
+{
+    LOGD("Entered attribute_name: %s", attribute_name.c_str());
+
+    using namespace CONVERSATION_FILTER_ATTRIBUTE;
+
+    if(TIMESTAMP == attribute_name) {
+        return FilterUtils::isTimeStampInRange(getTimestamp(), initial_value, end_value);
+    }
+    else {
+        LOGD("attribute:%s is NOT SUPPORTED", attribute_name.c_str());
+    }
+    return false;
+}
+
+} //Messaging
+} //DeviceAPI
diff --git a/src/Messaging/MessageConversation.h b/src/Messaging/MessageConversation.h
new file mode 100644 (file)
index 0000000..568c32d
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageConversation.h
+ */
+
+#ifndef __TIZEN_MESSAGE_CONVERSATION_H__
+#define __TIZEN_MESSAGE_CONVERSATION_H__
+
+#include <memory>
+#include <string>
+#include <time.h>
+#include <vector>
+#include <email-api.h>
+#include <msg.h>
+#include <msg_storage.h>
+#include "MessagingUtil.h"
+#include <AbstractFilter.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageConversation;
+
+struct MessageConversationHolder {
+    std::shared_ptr<MessageConversation>ptr;
+};
+
+typedef std::shared_ptr<MessageConversation> ConversationPtr;
+
+typedef std::vector<ConversationPtr> ConversationPtrVector;
+
+class MessageConversation : public Tizen::FilterableObject {
+public:
+    MessageConversation();
+    ~MessageConversation();
+
+    // attributes getters
+    int getConversationId() const;
+    MessageType getType() const;
+    time_t getTimestamp() const;
+    unsigned long getMessageCount() const;
+    unsigned long getUnreadMessages() const;
+    std::string getPreview() const;
+    std::string getSubject() const;
+    bool getIsRead() const;
+    std::string getFrom() const;
+    std::vector<std::string> getTo() const;
+    std::vector<std::string> getCC() const;
+    std::vector<std::string> getBCC() const;
+    int getLastMessageId() const;
+
+    static std::shared_ptr<MessageConversation> convertConversationStructToObject(
+        unsigned int threadId, MessageType msgType, msg_handle_t handle = NULL);
+    static std::shared_ptr<MessageConversation> convertEmailConversationToObject(
+        unsigned int threadId);
+    /**
+     *
+     * @param threadId Id of Message (not Conversation)
+     * @param handle
+     * @return
+     */
+    static std::shared_ptr<MessageConversation> convertMsgConversationToObject(
+        unsigned int threadId, msg_handle_t handle);
+
+    virtual void setConversationId(int id);
+    virtual void setMessageCount(int count);
+    virtual void setUnreadMessages(int count);
+
+    // Tizen::FilterableObject
+    virtual bool isMatchingAttribute(const std::string& attribute_name,
+            const Tizen::FilterMatchFlag match_flag,
+            Tizen::AnyPtr match_value) const;
+
+    virtual bool isMatchingAttributeRange(const std::string& attribute_name,
+            Tizen::AnyPtr initial_value,
+            Tizen::AnyPtr end_value) const;
+
+private:
+    int m_conversation_id;
+    MessageType m_conversation_type;
+    time_t m_timestamp;
+    unsigned long m_count;
+    unsigned long m_unread_messages;
+    std::string m_preview;
+    std::string m_conversation_subject;
+    bool m_is_read;
+    std::string m_from;
+    std::vector<std::string> m_to;
+    std::vector<std::string> m_cc;
+    std::vector<std::string> m_bcc;
+    int m_last_message_id;
+};
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_MESSAGE_CONVERSATION_H__
diff --git a/src/Messaging/MessageEmail.cpp b/src/Messaging/MessageEmail.cpp
new file mode 100644 (file)
index 0000000..fd6699f
--- /dev/null
@@ -0,0 +1,166 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageEmail.cpp
+ */
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "MessageEmail.h"
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageEmail::MessageEmail():
+    Message()
+{
+    LOGD("MessageEmail constructor.");
+    this->m_type = MessageType(EMAIL);
+}
+
+MessageEmail::~MessageEmail()
+{
+    LOGD("MessageEmail destructor.");
+}
+
+// *** overrided methods
+void MessageEmail::setCC(std::vector<std::string> &cc)
+{
+    // CC recipient's format validation should be done by email service
+    m_cc = cc;
+
+    if(m_cc.empty()) {
+        LOGD("Recipient's list cleared");
+        return;
+    }
+}
+
+void MessageEmail::setBCC(std::vector<std::string> &bcc)
+{
+    // BCC recipient's format validation should be done by email service
+    m_bcc = bcc;
+
+    if(m_bcc.empty()) {
+        LOGD("Recipient's list cleared");
+        return;
+    }
+}
+
+void MessageEmail::setSubject(std::string subject)
+{
+    m_subject = subject;
+}
+
+void MessageEmail::setIsHighPriority(bool highpriority)
+{
+    m_high_priority = highpriority;
+}
+
+void MessageEmail::setMessageAttachments(AttachmentPtrVector &attachments)
+{
+    m_attachments = attachments;
+
+    m_has_attachment = true;
+    if(m_attachments.empty()) {
+        LOGD("Recipient's list cleared");
+        m_has_attachment = false;
+    }
+}
+
+bool MessageEmail::getHasAttachment() const
+{
+    LOGD("MessageEmail::getHasAttachment()");
+    return m_has_attachment || !m_body->getInlineAttachments().empty();
+}
+
+void MessageEmail::updateEmailMessage(email_mail_data_t& mail)
+{
+    LOGD("Enter");
+    std::vector<std::string> recp_list;
+
+    setId(mail.mail_id);
+
+    setFolderId(mail.mailbox_id);
+
+    setConversationId(mail.thread_id);
+
+    if(mail.full_address_from) {
+        setFrom(MessagingUtil::extractSingleEmailAddress(mail.full_address_from));
+    }
+
+    if(mail.full_address_to) {
+        recp_list = Message::getEmailRecipientsFromStruct(mail.full_address_to);
+        setTO(recp_list);
+    }
+
+    if(mail.full_address_cc) {
+        recp_list = Message::getEmailRecipientsFromStruct(mail.full_address_cc);
+        setCC(recp_list);
+    }
+
+    if(mail.full_address_bcc) {
+        recp_list = Message::getEmailRecipientsFromStruct(mail.full_address_bcc);
+        setBCC(recp_list);
+    }
+
+    setTimeStamp(mail.date_time);
+
+    setIsRead(mail.flags_seen_field);
+
+    setIsHighPriority((EMAIL_MAIL_PRIORITY_HIGH == mail.priority) ? true : false);
+
+    if (mail.subject == NULL) {
+        LOGW("Subject is null");
+    } else {
+        LOGD("Subject: %s", mail.subject);
+        setSubject(mail.subject);
+    }
+
+    getBody()->updateBody(mail);
+
+    if (mail.mail_id != mail.thread_id) {
+        setInResponseTo(mail.thread_id);
+    }
+
+    switch(mail.save_status)
+    {
+        case EMAIL_MAIL_STATUS_SENT:
+            setMessageStatus(MessageStatus::STATUS_SENT);
+        break;
+        case EMAIL_MAIL_STATUS_SENDING:
+            setMessageStatus(MessageStatus::STATUS_SENDING);
+        break;
+        case EMAIL_MAIL_STATUS_SAVED:
+            setMessageStatus(MessageStatus::STATUS_DRAFT);
+        break;
+        case EMAIL_MAIL_STATUS_SEND_FAILURE:
+            setMessageStatus(MessageStatus::STATUS_FAILED);
+        break;
+        default:
+            setMessageStatus(MessageStatus::STATUS_UNDEFINED);
+        break;
+    }
+
+    AttachmentPtrVector att = convertEmailToMessageAttachment(mail);
+
+    setMessageAttachments(att);
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/MessageEmail.h b/src/Messaging/MessageEmail.h
new file mode 100644 (file)
index 0000000..aacf1b0
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageEmail.h
+ */
+
+
+#ifndef __TIZEN_MESSAGE_EMAIL_H__
+#define __TIZEN_MESSAGE_EMAIL_H__
+
+#include "Message.h"
+#include "MessageAttachment.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageEmail: public Message {
+public:
+// constructor
+    MessageEmail();
+    ~MessageEmail();
+
+//overrided base class functions
+    void setCC(std::vector<std::string> &cc);
+    void setBCC(std::vector<std::string> &bcc);
+    void setSubject(std::string subject);
+    void setIsHighPriority(bool highpriority);
+    void setMessageAttachments(AttachmentPtrVector &attachments);
+
+    bool getHasAttachment() const;
+    /**
+     * Updates message with data from email_mail_data_t structure.
+     * @param mail
+     */
+    virtual void updateEmailMessage(email_mail_data_t& mail);
+
+private:
+    // function that verifies recipient's list validity
+    bool isValidRecpientsVector(std::vector<std::string> &recipients);
+};
+
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_MESSAGE_EMAIL_H__
diff --git a/src/Messaging/MessageFolder.cpp b/src/Messaging/MessageFolder.cpp
new file mode 100644 (file)
index 0000000..420006f
--- /dev/null
@@ -0,0 +1,200 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageFolder.cpp
+ */
+
+#include "MessageFolder.h"
+#include "MessagingUtil.h"
+
+namespace DeviceAPI {
+
+using namespace Tizen;
+
+namespace Messaging {
+
+MessageFolder::MessageFolder(
+        std::string id,
+        std::string parent_id,
+        std::string service_id,
+        std::string content_type,
+        std::string name,
+        std::string path,
+        MessageFolderType type,
+        bool synchronizable):
+    m_id(id),
+    m_parent_id(parent_id),
+    m_parent_id_set(true),
+    m_service_id(service_id),
+    m_content_type(content_type),
+    m_name(name),
+    m_path(path),
+    m_type(type),
+    m_synchronizable(synchronizable)
+{
+}
+
+MessageFolder::MessageFolder(email_mailbox_t mailbox)
+{
+    m_id = std::to_string(mailbox.mailbox_id);
+    m_parent_id_set = false;
+    m_service_id = std::to_string(mailbox.account_id);
+    m_content_type = MessagingUtil::messageTypeToString(EMAIL);
+    m_name = mailbox.alias;
+    m_path = mailbox.mailbox_name;
+    m_type = convertPlatformFolderType(mailbox.mailbox_type);
+    if (0 == mailbox.local) {
+        m_synchronizable = true;
+    }
+    else {
+        m_synchronizable = false;
+    }
+}
+
+std::string MessageFolder::getId() const
+{
+    return m_id;
+}
+
+std::string MessageFolder::getParentId() const
+{
+    return m_parent_id;
+}
+
+bool MessageFolder::isParentIdSet() const
+{
+    return m_parent_id_set;
+}
+
+void MessageFolder::setParentId(const std::string& parentId)
+{
+    m_parent_id = parentId;
+    m_parent_id_set = true;
+}
+
+std::string MessageFolder::getServiceId() const
+{
+    return m_service_id;
+}
+
+std::string MessageFolder::getContentType() const
+{
+    return m_content_type;
+}
+
+std::string MessageFolder::getName() const
+{
+    return m_name;
+}
+
+std::string MessageFolder::getPath() const
+{
+    return m_path;
+}
+
+MessageFolderType MessageFolder::getType() const
+{
+    return m_type;
+}
+
+bool MessageFolder::getSynchronizable() const
+{
+    return m_synchronizable;
+}
+
+void MessageFolder::setName(const std::string &value)
+{
+    m_name = value;
+}
+
+void MessageFolder::setSynchronizable(const bool &value)
+{
+    m_synchronizable = value;
+}
+
+MessageFolderType MessageFolder::convertPlatformFolderType(
+        email_mailbox_type_e folderType)
+{
+    switch (folderType) {
+        case email_mailbox_type_e::EMAIL_MAILBOX_TYPE_INBOX:
+            return MessageFolderType::MESSAGE_FOLDER_TYPE_INBOX;
+        case email_mailbox_type_e::EMAIL_MAILBOX_TYPE_SENTBOX:
+            return MessageFolderType::MESSAGE_FOLDER_TYPE_SENTBOX;
+        case email_mailbox_type_e::EMAIL_MAILBOX_TYPE_DRAFT:
+            return MessageFolderType::MESSAGE_FOLDER_TYPE_DRAFTS;
+        case email_mailbox_type_e::EMAIL_MAILBOX_TYPE_OUTBOX:
+            return MessageFolderType::MESSAGE_FOLDER_TYPE_OUTBOX;
+        case email_mailbox_type_e::EMAIL_MAILBOX_TYPE_ALL_EMAILS:
+            return MessageFolderType::MESSAGE_FOLDER_TYPE_NOTSTANDARD;
+        default:
+            return MessageFolderType::MESSAGE_FOLDER_TYPE_NOTSTANDARD;
+    }
+}
+
+/**
+ *
+ *  Attribute      | Attribute filter| Attribute range filter
+ *                 | supported       | supported
+ * ----------------+-----------------+------------------------
+ *  id             | No              | No
+ *  parentId       | No              | No
+ *  serviceId      | Yes             | No
+ *  contentType    | No              | No
+ *  name           | No              | No
+ *  path           | No              | No
+ *  type           | No              | No
+ *  synchronizable | No              | No
+ */
+
+namespace FOLDER_FILTER_ATTRIBUTE {
+const std::string SERVICE_ID = "serviceId";
+} //namespace FOLDER_FILTER_ATTRIBUTE
+
+bool MessageFolder::isMatchingAttribute(const std::string& attribute_name,
+            const FilterMatchFlag match_flag,
+            AnyPtr match_value) const
+{
+    LOGD("Entered");
+    auto key = match_value->toString();
+    LOGD("attribute_name: %s match_flag:%d match_value:%s", attribute_name.c_str(),
+            match_flag, key.c_str());
+
+    using namespace FOLDER_FILTER_ATTRIBUTE;
+
+    if (SERVICE_ID == attribute_name) {
+        return FilterUtils::isStringMatching(key, getServiceId() , match_flag);
+    }
+    else {
+        LOGD("attribute:%s is NOT SUPPORTED", attribute_name.c_str());
+    }
+
+    return false;
+}
+
+
+bool MessageFolder::isMatchingAttributeRange(const std::string& attribute_name,
+            AnyPtr initial_value,
+            AnyPtr end_value) const
+{
+    LOGD("Entered");
+    LOGD("attribute_name: %s NOT SUPPORTED", attribute_name.c_str());
+    return false;
+}
+
+} //Messaging
+} //DeviceAPI
diff --git a/src/Messaging/MessageFolder.h b/src/Messaging/MessageFolder.h
new file mode 100644 (file)
index 0000000..dfb02f7
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageFolder.h
+ */
+
+#ifndef __TIZEN_MESSAGING_MESSAGE_FOLDER_H__
+#define __TIZEN_MESSAGING_MESSAGE_FOLDER_H__
+
+#include <string>
+#include <memory>
+#include <vector>
+
+#include <email-types.h>
+#include <AbstractFilter.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+enum MessageFolderType {
+    MESSAGE_FOLDER_TYPE_INBOX,
+    MESSAGE_FOLDER_TYPE_OUTBOX,
+    MESSAGE_FOLDER_TYPE_DRAFTS,
+    MESSAGE_FOLDER_TYPE_SENTBOX,
+    MESSAGE_FOLDER_TYPE_NOTSTANDARD
+};
+
+class MessageFolder;
+
+struct MessageFolderHolder {
+    std::shared_ptr<MessageFolder> ptr;
+};
+
+typedef std::shared_ptr<MessageFolder> FolderPtr;
+
+typedef std::vector<FolderPtr> FolderPtrVector;
+
+class MessageFolder : public Tizen::FilterableObject{
+
+public:
+    MessageFolder(
+            std::string id,
+            std::string parent_id,
+            std::string service_id,
+            std::string content_type,
+            std::string name,
+            std::string path,
+            MessageFolderType type,
+            bool synchronizable);
+    MessageFolder(email_mailbox_t mailbox);
+
+    std::string getId() const;
+    std::string getParentId() const;
+    bool isParentIdSet() const;
+    void setParentId(const std::string& parentId);
+    std::string getServiceId() const;
+    std::string getContentType() const;
+    std::string getName() const;
+    void setName(const std::string &value);
+    std::string getPath() const;
+    MessageFolderType getType() const;
+    bool getSynchronizable() const;
+    void setSynchronizable(const bool &value);
+
+    // Tizen::FilterableObject
+    virtual bool isMatchingAttribute(const std::string& attribute_name,
+            const Tizen::FilterMatchFlag match_flag,
+            Tizen::AnyPtr match_value) const;
+
+    virtual bool isMatchingAttributeRange(const std::string& attribute_name,
+            Tizen::AnyPtr initial_value,
+            Tizen::AnyPtr end_value) const;
+private:
+    MessageFolderType convertPlatformFolderType(
+            email_mailbox_type_e folderType);
+
+    std::string m_id;
+    std::string m_parent_id;
+    bool m_parent_id_set;
+    std::string m_service_id;
+    std::string m_content_type;
+    std::string m_name;
+    std::string m_path;
+    MessageFolderType m_type;
+    bool m_synchronizable;
+};
+
+} //Messaging
+} //DeviceAPI
+
+#endif // __TIZEN_MESSAGING_MESSAGE_FOLDER_H__
diff --git a/src/Messaging/MessageMMS.cpp b/src/Messaging/MessageMMS.cpp
new file mode 100644 (file)
index 0000000..c6dfa13
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageMMS.cpp
+ */
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "MessageMMS.h"
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageMMS::MessageMMS():
+    Message()
+{
+    LOGD("MessageMMS constructor.");
+    this->m_type = MessageType(MessageType(MMS));
+}
+
+MessageMMS::~MessageMMS()
+{
+    LOGD("MessageMMS destructor.");
+}
+
+// *** overrided methods
+void MessageMMS::setCC(std::vector<std::string> &cc)
+{
+    // CC recipient's format validation should be done by email service
+    m_cc = cc;
+
+    if(m_cc.empty()) {
+        LOGD("Recipient's list cleared");
+        return;
+    }
+}
+
+void MessageMMS::setBCC(std::vector<std::string> &bcc)
+{
+    // BCC recipient's format validation should be done by email service
+    m_bcc = bcc;
+
+    if(m_bcc.empty()) {
+        LOGD("Recipient's list cleared");
+        return;
+    }
+}
+
+void MessageMMS::setSubject(std::string subject)
+{
+    m_subject = subject;
+}
+
+void MessageMMS::setMessageAttachments(AttachmentPtrVector &attachments)
+{
+    m_attachments = attachments;
+
+    m_has_attachment = true;
+    if(m_attachments.empty()) {
+        LOGD("Recipient's list cleared");
+        m_has_attachment = false;
+    }
+}
+
+bool MessageMMS::getHasAttachment() const
+{
+    LOGD("MessageMMS::getHasAttachment()");
+    // TODO: Analyze relation between hasAttachment flag and inlineAttachments
+    return m_has_attachment;
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/MessageMMS.h b/src/Messaging/MessageMMS.h
new file mode 100644 (file)
index 0000000..799f309
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageMMS.h
+ */
+
+#ifndef __TIZEN_MESSAGE_MMS_H__
+#define __TIZEN_MESSAGE_MMS_H__
+
+// Header with core msg-service declarations
+#include <msg.h>
+
+#include "Message.h"
+#include "MessageAttachment.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageMMS: public Message {
+public:
+// constructor
+    MessageMMS();
+    ~MessageMMS();
+
+//overrided base class functions
+    void setCC(std::vector<std::string> &cc);
+    void setBCC(std::vector<std::string> &bcc);
+    void setSubject(std::string subject);
+    void setMessageAttachments(AttachmentPtrVector &attachments);
+
+    bool getHasAttachment() const;
+};
+
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_MESSAGE_MMS_H__
diff --git a/src/Messaging/MessageSMS.cpp b/src/Messaging/MessageSMS.cpp
new file mode 100644 (file)
index 0000000..4204035
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageSMS.cpp
+ */
+
+#include <iterator>
+#include <PlatformException.h>
+#include <Logger.h>
+#include "MessageSMS.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageSMS::MessageSMS():
+    Message()
+{
+    LOGD("MessageSMS constructor.");
+    this->m_type = MessageType(MessageType(SMS));
+}
+
+MessageSMS::~MessageSMS()
+{
+    LOGD("MessageSMS destructor.");
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/MessageSMS.h b/src/Messaging/MessageSMS.h
new file mode 100644 (file)
index 0000000..e2afcc0
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessageSMS.h
+ */
+
+#ifndef __TIZEN_MESSAGE_SMS_H__
+#define __TIZEN_MESSAGE_SMS_H__
+
+// Header with core msg-service declarations
+#include <msg.h>
+
+#include "Message.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageSMS: public Message {
+public:
+// constructor
+    MessageSMS();
+    ~MessageSMS();
+
+};
+
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_MESSAGE_SMS_H__
diff --git a/src/Messaging/MessageService.cpp b/src/Messaging/MessageService.cpp
new file mode 100644 (file)
index 0000000..00c5460
--- /dev/null
@@ -0,0 +1,442 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIError.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+#include "MessageService.h"
+#include "MessageStorageShortMsg.h"
+#include "MessageStorageEmail.h"
+
+using namespace std;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+//#################### MessageRecipientsCallbackData ####################
+
+MessageRecipientsCallbackData::MessageRecipientsCallbackData(JSContextRef globalCtx):
+        CallbackUserData(globalCtx),
+        m_is_error(false),
+        m_sim_index(TAPI_NETWORK_DEFAULT_DATA_SUBS_UNKNOWN),
+        m_default_sim_index(TAPI_NETWORK_DEFAULT_DATA_SUBS_UNKNOWN)
+{
+    LOGD("Entered");
+}
+
+MessageRecipientsCallbackData::~MessageRecipientsCallbackData()
+{
+    LOGD("Entered");
+}
+
+void MessageRecipientsCallbackData::setMessage(std::shared_ptr<Message> message)
+{
+    m_message = message;
+}
+
+std::shared_ptr<Message> MessageRecipientsCallbackData::getMessage() const
+{
+    return m_message;
+}
+
+void MessageRecipientsCallbackData::setMessageRecipients(
+        const std::vector<std::string>& msgRecipients)
+{
+    m_msg_recipients = msgRecipients;
+}
+
+const std::vector<std::string>& MessageRecipientsCallbackData::getMessageRecipients() const
+{
+    return m_msg_recipients;
+}
+
+void MessageRecipientsCallbackData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+        if (m_message) {
+            m_err_message += " for: ";
+            // platform issue: we cannot get error per recipient
+            // so all recipients are added to error message
+            std::vector<std::string> recp_list = m_message->getTO();
+            unsigned int count = recp_list.size();
+            for (unsigned int i = 0; i < count; ++i) {
+                m_err_message += recp_list.at(i) + ", ";
+            }
+            recp_list = m_message->getCC();
+            count = recp_list.size();
+            for (unsigned int i = 0; i < count; ++i) {
+                m_err_message += recp_list.at(i) + ", ";
+            }
+            recp_list = m_message->getBCC();
+            count = recp_list.size();
+            for (unsigned int i = 0; i < count; ++i) {
+                m_err_message += recp_list.at(i) + ", ";
+            }
+
+        }
+    }
+}
+
+bool MessageRecipientsCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+std::string MessageRecipientsCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string MessageRecipientsCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void MessageRecipientsCallbackData::setAccountId(int account_id){
+    m_account_id = account_id;
+}
+
+int MessageRecipientsCallbackData::getAccountId() const
+{
+    return m_account_id;
+}
+
+void MessageRecipientsCallbackData::setSimIndex(
+    TelNetworkDefaultDataSubs_t sim_index)
+{
+    m_sim_index = sim_index;
+}
+
+TelNetworkDefaultDataSubs_t MessageRecipientsCallbackData::getSimIndex() const
+{
+    return m_sim_index;
+}
+
+bool MessageRecipientsCallbackData::isSetSimIndex() const
+{
+    return m_sim_index != TAPI_NETWORK_DEFAULT_DATA_SUBS_UNKNOWN;
+}
+
+void MessageRecipientsCallbackData::setDefaultSimIndex(
+    TelNetworkDefaultDataSubs_t sim_index)
+{
+    m_default_sim_index = sim_index;
+}
+
+TelNetworkDefaultDataSubs_t MessageRecipientsCallbackData::getDefaultSimIndex() const
+{
+    return m_default_sim_index;
+}
+
+//#################### BaseMessageServiceCallbackData ####################
+
+BaseMessageServiceCallbackData::BaseMessageServiceCallbackData(JSContextRef globalCtx):
+        CallbackUserData(globalCtx),
+        m_is_error(false),
+        m_op_handle(-1)
+{
+    LOGD("Entered");
+}
+
+BaseMessageServiceCallbackData::~BaseMessageServiceCallbackData()
+{
+    LOGD("Entered");
+}
+
+void BaseMessageServiceCallbackData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool BaseMessageServiceCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+std::string BaseMessageServiceCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string BaseMessageServiceCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void BaseMessageServiceCallbackData::setOperationHandle(const int op_handle)
+{
+    m_op_handle = op_handle;
+}
+
+int BaseMessageServiceCallbackData::getOperationHandle() const
+{
+    return m_op_handle;
+}
+
+//#################### MessageBodyCallbackData ####################
+
+MessageBodyCallbackData::MessageBodyCallbackData(JSContextRef globalCtx):
+        BaseMessageServiceCallbackData(globalCtx)
+{
+    LOGD("Entered");
+}
+
+MessageBodyCallbackData::~MessageBodyCallbackData()
+{
+    LOGD("Entered");
+}
+
+void MessageBodyCallbackData::setMessage(std::shared_ptr<Message> message)
+{
+    m_message = message;
+}
+
+std::shared_ptr<Message> MessageBodyCallbackData::getMessage() const
+{
+    return m_message;
+}
+
+//#################### MessageAttachmentCallbackData ####################
+
+MessageAttachmentCallbackData::MessageAttachmentCallbackData(JSContextRef globalCtx):
+        BaseMessageServiceCallbackData(globalCtx),
+        m_nth(0)
+{
+    LOGD("Entered");
+}
+
+
+MessageAttachmentCallbackData::~MessageAttachmentCallbackData()
+{
+    LOGD("Entered");
+}
+
+void MessageAttachmentCallbackData::setMessageAttachment(
+        std::shared_ptr<MessageAttachment> messageAttachment)
+{
+    m_message_attachment = messageAttachment;
+}
+
+std::shared_ptr<MessageAttachment> MessageAttachmentCallbackData::
+    getMessageAttachment() const
+{
+    return m_message_attachment;
+}
+
+void MessageAttachmentCallbackData::setNth(const int nth)
+{
+    m_nth = nth;
+}
+
+int MessageAttachmentCallbackData::getNth() const
+{
+    return m_nth;
+}
+
+//#################### SyncCallbackData ####################
+
+SyncCallbackData::SyncCallbackData(JSContextRef globalCtx):
+        BaseMessageServiceCallbackData(globalCtx),
+        m_is_limit(false),
+        m_limit(0),
+        m_account_id(-1)
+{
+    LOGD("Entered");
+}
+
+SyncCallbackData::~SyncCallbackData()
+{
+    LOGD("Entered");
+}
+
+void SyncCallbackData::setLimit(const unsigned long limit)
+{
+    m_is_limit = true;
+    m_limit = limit;
+}
+
+bool SyncCallbackData::isLimit() const
+{
+    return m_is_limit;
+}
+
+unsigned long SyncCallbackData::getLimit() const
+{
+    return m_limit;
+}
+
+void SyncCallbackData::setOpId(long op_id)
+{
+    m_op_id = op_id;
+}
+
+long SyncCallbackData::getOpId()
+{
+    return m_op_id;
+}
+
+void SyncCallbackData::setAccountId(int account_id)
+{
+    m_account_id = account_id;
+}
+
+int SyncCallbackData::getAccountId() const
+{
+    return m_account_id;
+}
+
+//#################### SyncFolderCallbackData ####################
+
+SyncFolderCallbackData::SyncFolderCallbackData(JSContextRef globalCtx):
+        SyncCallbackData(globalCtx)
+{
+    LOGD("Entered");
+}
+
+SyncFolderCallbackData::~SyncFolderCallbackData()
+{
+    LOGD("Entered");
+}
+
+void SyncFolderCallbackData::setMessageFolder(
+        std::shared_ptr<MessageFolder> message_folder)
+{
+    m_message_folder = message_folder;
+}
+
+std::shared_ptr<MessageFolder> SyncFolderCallbackData::getMessageFolder() const
+{
+    return m_message_folder;
+}
+
+//#################### MessageService ####################
+
+MessageService::MessageService(int id,
+                    MessageType msgType,
+                    string name):
+        SecurityAccessor(),
+        m_id(id),
+        m_msg_type(msgType),
+        m_name(name)
+{
+    LOGD("Entered");
+    switch (msgType) {
+        case MessageType::SMS:
+        case MessageType::MMS:
+            m_storage.reset(new MessageStorageShortMsg(id, msgType));
+            break;
+        case MessageType::EMAIL:
+            m_storage.reset(new MessageStorageEmail(id));
+            break;
+        default:
+            LOGE("Undefined message type");
+            throw InvalidValuesException("Undefined message type");
+    }
+}
+
+MessageService::~MessageService()
+{
+    LOGD("Entered");
+}
+
+int MessageService::getMsgServiceId() const
+{
+    return m_id;
+}
+
+string MessageService::getMsgServiceIdStr() const
+{
+    return to_string(m_id);
+}
+
+MessageType MessageService::getMsgServiceType() const
+{
+    return m_msg_type;
+}
+
+std::string MessageService::getMsgServiceName() const
+{
+    return m_name;
+}
+
+std::shared_ptr<MessageStorage> MessageService::getMsgStorage() const
+{
+    return m_storage;
+}
+
+void MessageService::sendMessage(MessageRecipientsCallbackData *callback)
+{
+    // this method should be overwritten be specific services
+    LOGE("Cannot send message");
+    throw NotSupportedException("Cannot send message");
+}
+
+void MessageService::loadMessageBody(MessageBodyCallbackData *callback)
+{
+    // this method should be overwritten by specific services
+    LOGE("Cannot load message body");
+    throw NotSupportedException("Cannot load message body");
+}
+
+void MessageService::loadMessageAttachment(MessageAttachmentCallbackData *callback)
+{
+    // this method should be overwritten by email service
+    // for MMS and SMS this function is not supported
+    LOGE("Cannot load message attachment");
+    throw NotSupportedException("Cannot load message attachment");
+}
+
+long MessageService::sync(SyncCallbackData *callback)
+{
+    // this method should be overwritten by email service
+    // for MMS and SMS this function is not supported
+    LOGE("Cannot sync with external server");
+    throw NotSupportedException("Cannot sync with external server");
+}
+
+long MessageService::syncFolder(SyncFolderCallbackData *callback)
+{
+    // this method should be overwritten by email service
+    // for MMS and SMS this function is not supported
+    LOGE("Cannot sync folder with external server");
+    throw NotSupportedException("Cannot sync folder with external server");
+}
+
+void MessageService::stopSync(long op_id)
+{
+    // this method should be overwritten by email service
+    // for MMS and SMS this function is not supported
+    LOGE("Cannot stop sync with external server");
+    throw NotSupportedException("Cannot stop sync with external server");
+}
+
+} // Messaging
+} // DeviceAPI
+
diff --git a/src/Messaging/MessageService.h b/src/Messaging/MessageService.h
new file mode 100755 (executable)
index 0000000..e710792
--- /dev/null
@@ -0,0 +1,229 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGE_SERVICE_H__
+#define __TIZEN_MESSAGE_SERVICE_H__
+
+#include <msg.h>
+#include <msg_transport.h>
+#include <msg_storage.h>
+#include <memory>
+#include <ITapiNetwork.h>
+
+#include <CallbackUserData.h>
+#include <PlatformException.h>
+#include <Security.h>
+
+#include "MessagingUtil.h"
+#include "Message.h"
+#include "MessageStorage.h"
+#include "MessageFolder.h"
+
+#include "DBus/Connection.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+enum MessageServiceAccountId
+{
+    UNKNOWN_ACCOUNT_ID = 0,
+    SMS_ACCOUNT_ID = 101,
+    MMS_ACCOUNT_ID = 102
+};
+
+class MessageRecipientsCallbackData : public Common::CallbackUserData {
+public:
+    MessageRecipientsCallbackData(JSContextRef globalCtx);
+    virtual ~MessageRecipientsCallbackData();
+
+    void setMessage(std::shared_ptr<Message> message);
+    std::shared_ptr<Message> getMessage() const;
+
+    void setMessageRecipients(const std::vector<std::string>& msgRecipients);
+    const std::vector<std::string>& getMessageRecipients() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    void setAccountId(int account_id);
+    int getAccountId() const;
+
+    void setSimIndex(TelNetworkDefaultDataSubs_t sim_index);
+    TelNetworkDefaultDataSubs_t getSimIndex() const;
+    void setDefaultSimIndex(TelNetworkDefaultDataSubs_t sim_index);
+    TelNetworkDefaultDataSubs_t getDefaultSimIndex() const;
+    bool isSetSimIndex() const;
+
+private:
+    std::shared_ptr<Message> m_message;
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+    std::vector<std::string> m_msg_recipients;
+    int m_account_id;
+    TelNetworkDefaultDataSubs_t m_sim_index;
+    TelNetworkDefaultDataSubs_t m_default_sim_index;
+};
+
+
+class BaseMessageServiceCallbackData : public Common::CallbackUserData {
+public:
+    BaseMessageServiceCallbackData(JSContextRef globalCtx);
+    virtual ~BaseMessageServiceCallbackData();
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    /**
+     * This handle is returned from various native API functions:
+     *   int email_sync_header(..., int *handle);
+     *   int email_download_body(..., int *handle);
+     *   int email_download_attachment(..., int *handle);
+     *
+     * It is used to stop and identify request.
+     */
+    void setOperationHandle(const int op_handle);
+    int getOperationHandle() const;
+
+protected:
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+
+    int m_op_handle;
+};
+
+class MessageBodyCallbackData : public BaseMessageServiceCallbackData {
+public:
+    MessageBodyCallbackData(JSContextRef globalCtx);
+    virtual ~MessageBodyCallbackData();
+
+    void setMessage(std::shared_ptr<Message> message);
+    std::shared_ptr<Message> getMessage() const;
+
+private:
+    std::shared_ptr<Message> m_message;
+};
+
+class MessageAttachmentCallbackData : public BaseMessageServiceCallbackData {
+public:
+    MessageAttachmentCallbackData(JSContextRef globalCtx);
+    virtual ~MessageAttachmentCallbackData();
+
+    void setMessageAttachment(std::shared_ptr<MessageAttachment> messageAttachment);
+    std::shared_ptr<MessageAttachment> getMessageAttachment() const;
+
+    /**
+     * nth is used in native api call:
+     * int email_download_attachment(int mail_id, int nth, int *handle);
+     *
+     * nth is equal to attachment index+1 (starts from 1 not 0) see
+     * email-api-network.h for details.
+     * */
+    void setNth(const int nth);
+    int getNth() const;
+
+private:
+    std::shared_ptr<MessageAttachment> m_message_attachment;
+    int m_nth;
+};
+
+class SyncCallbackData : public BaseMessageServiceCallbackData {
+public:
+    SyncCallbackData(JSContextRef globalCtx);
+    virtual ~SyncCallbackData();
+
+    void setLimit(const unsigned long limit);
+    bool isLimit() const;
+    unsigned long getLimit() const;
+
+    void setOpId(long op_id);
+    long getOpId();
+    void setAccountId(int account_id);
+    int getAccountId() const;
+
+protected:
+    bool m_is_limit;
+    unsigned long m_limit;
+
+    long m_op_id;
+    int m_account_id;
+};
+
+class SyncFolderCallbackData : public SyncCallbackData {
+public:
+    SyncFolderCallbackData(JSContextRef globalCtx);
+    virtual ~SyncFolderCallbackData();
+
+    void setMessageFolder(std::shared_ptr<MessageFolder> message_folder);
+    std::shared_ptr<MessageFolder> getMessageFolder() const;
+
+private:
+    std::shared_ptr<MessageFolder> m_message_folder;
+};
+
+
+class MessageService : public Common::SecurityAccessor
+{
+public:
+    virtual ~MessageService();
+
+    virtual int getMsgServiceId() const;
+    virtual std::string getMsgServiceIdStr() const;
+    virtual MessageType getMsgServiceType() const;
+    virtual std::string getMsgServiceName() const;
+    virtual std::shared_ptr<MessageStorage> getMsgStorage() const;
+
+    virtual void sendMessage(MessageRecipientsCallbackData *callback);
+    virtual void loadMessageBody(MessageBodyCallbackData *callback);
+    virtual void loadMessageAttachment(MessageAttachmentCallbackData *callback);
+    virtual long sync(SyncCallbackData *callback);
+
+    /**
+     * @param callback - owned by this method unless exception is thrown
+     * @return opId - "long Identifier which can be used to stop this service operation"
+     *                (form JS documentation)
+     *
+     */
+    virtual long syncFolder(SyncFolderCallbackData *callback);
+
+    virtual void stopSync(long op_id);
+
+protected:
+    /**
+     * We have child classes MessageServiceEmail and MessageServiceShortMsg which
+     * should provide specialized implementation.
+     */
+    MessageService(int id,
+            MessageType msgType,
+            std::string name);
+
+    int m_id;
+    MessageType m_msg_type;
+    std::string m_name;
+    std::shared_ptr<MessageStorage> m_storage;
+};
+
+} // Messaging
+} // DeviceAPI
+#endif // __TIZEN_MESSAGE_SERVICE_H__
diff --git a/src/Messaging/MessageServiceEmail.cpp b/src/Messaging/MessageServiceEmail.cpp
new file mode 100644 (file)
index 0000000..ca45652
--- /dev/null
@@ -0,0 +1,288 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIError.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <PlatformException.h>
+
+#include "MessageServiceEmail.h"
+#include "EmailManager.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageServiceEmail::MessageServiceEmail(int id, std::string name)
+        : MessageService(id,
+                MessageType::EMAIL,
+                name)
+{
+    LOGD("Entered");
+}
+
+MessageServiceEmail::~MessageServiceEmail()
+{
+    LOGD("Entered");
+}
+
+static gboolean sendMessageTask(void* data)
+{
+    LOGD("Entered");
+
+    try {
+        EmailManager::getInstance().sendMessage(
+                static_cast<MessageRecipientsCallbackData*>(data));
+
+    } catch(const Common::BasePlatformException& exception) {
+        LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(),
+             (exception.getMessage()).c_str());
+    } catch(...) {
+        LOGE("Unhandled exception!");
+    }
+
+    return FALSE;
+}
+
+void MessageServiceEmail::sendMessage(MessageRecipientsCallbackData *callback)
+{
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    if (m_msg_type != callback->getMessage()->getType()) {
+
+        LOGE("Incorrect message type");
+        throw Common::TypeMismatchException("Incorrect message type");
+    }
+
+    callback->setAccountId(m_id);
+
+    guint id = g_idle_add(sendMessageTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+        throw Common::UnknownException("Could not add task");
+    }
+}
+
+static gboolean loadMessageBodyTask(void* data)
+{
+    LOGD("Entered");
+
+    try {
+        EmailManager::getInstance().loadMessageBody(
+                static_cast<MessageBodyCallbackData*>(data));
+
+    } catch(const Common::BasePlatformException& exception) {
+        LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(),
+             (exception.getMessage()).c_str());
+    } catch(...) {
+        LOGE("Unhandled exception!");
+    }
+
+    return FALSE;
+}
+
+void MessageServiceEmail::loadMessageBody(MessageBodyCallbackData *callback)
+{
+    LOGD("Entered");
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    guint id = g_idle_add(loadMessageBodyTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        throw Common::UnknownException("Could not add task");
+    }
+}
+
+static gboolean loadMessageAttachmentTask(void* data)
+{
+    LOGD("Entered");
+
+    try {
+        MessageAttachmentCallbackData *callback =
+                static_cast<MessageAttachmentCallbackData *>(data);
+        if (!callback) {
+            LOGE("Callback is null");
+            throw Common::UnknownException("Callback is null");
+        }
+
+        std::shared_ptr<MessageAttachment> att =  callback->getMessageAttachment();
+
+        // if the attachment is already saved, then it doesn't need to load again.
+        if (att->isFilePathSet() && att->isSaved()){
+            JSContextRef context = callback->getContext();
+            JSObjectRef jsMessageAtt = JSMessageAttachment::makeJSObject(context, att);
+            callback->callSuccessCallback(jsMessageAtt);
+
+            delete callback;
+            callback = NULL;
+            return FALSE;
+        }
+
+        EmailManager::getInstance().loadMessageAttachment(
+                static_cast<MessageAttachmentCallbackData*>(data));
+    } catch(const Common::BasePlatformException& exception) {
+        LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(),
+                (exception.getMessage()).c_str());
+    } catch(...) {
+        LOGE("Unhandled exception!");
+    }
+    return FALSE;
+}
+
+void MessageServiceEmail::loadMessageAttachment(MessageAttachmentCallbackData *callback)
+{
+    LOGD("Entered");
+    guint id = g_idle_add(loadMessageAttachmentTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        throw Common::UnknownException("Could not add task");
+    }
+}
+
+static gboolean syncTask(void* data)
+{
+    LOGD("Entered");
+
+    try {
+        EmailManager::getInstance().sync(data);
+
+    } catch(const Common::BasePlatformException& exception) {
+        LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(),
+             (exception.getMessage()).c_str());
+    } catch(...) {
+        LOGE("Unhandled exception!");
+    }
+
+    return FALSE;
+}
+
+long MessageServiceEmail::sync(SyncCallbackData *callback)
+{
+    LOGD("Entered");
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    long op_id = EmailManager::getInstance().getUniqueOpId();
+    callback->setOpId(op_id);
+    callback->setAccountId(m_id);
+
+    guint id = g_idle_add(syncTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        throw Common::UnknownException("Could not add task");
+    }
+    return op_id;
+}
+
+static gboolean syncFolderTask(void* data)
+{
+    LOGD("Entered");
+
+    try {
+        EmailManager::getInstance().syncFolder(
+                static_cast<SyncFolderCallbackData*>(data));
+
+    } catch(const Common::BasePlatformException& exception) {
+        LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(),
+             (exception.getMessage()).c_str());
+    } catch(...) {
+        LOGE("Unhandled exception!");
+    }
+
+    return FALSE;
+}
+
+long MessageServiceEmail::syncFolder(SyncFolderCallbackData *callback)
+{
+    LOGD("Entered");
+    if(!callback){
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    if(!callback->getMessageFolder()) {
+        LOGE("Message folder is null");
+        throw Common::TypeMismatchException("Message folder is null");
+    }
+
+    long op_id = EmailManager::getInstance().getUniqueOpId();
+    callback->setOpId(op_id);
+    callback->setAccountId(m_id);
+
+    guint id = g_idle_add(syncFolderTask, callback);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+
+    return op_id;
+}
+
+static gboolean stopSyncTask(void* data)
+{
+    LOGD("Entered");
+
+    try {
+        if (!data) {
+            LOGE("opId is null");
+            return FALSE;
+        }
+
+        const long op_id = *(static_cast<long*>(data));
+        delete static_cast<long*>(data);
+        data = NULL;
+        EmailManager::getInstance().stopSync(op_id);
+
+    } catch(const Common::BasePlatformException& exception) {
+        LOGE("Unhandled exception: %s (%s)!", (exception.getName()).c_str(),
+             (exception.getMessage()).c_str());
+    } catch(...) {
+        LOGE("Unhandled exception!");
+    }
+
+    return FALSE;
+}
+
+void MessageServiceEmail::stopSync(long data)
+{
+    LOGD("Entered");
+    long* op_id = new long();
+    *op_id = data;
+    guint id = g_idle_add(stopSyncTask, static_cast<void*>(op_id));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete op_id;
+        op_id = NULL;
+        throw Common::UnknownException("Could not add task");
+    }
+}
+
+
+} // Messaging
+} // DeviceAPI
+
diff --git a/src/Messaging/MessageServiceEmail.h b/src/Messaging/MessageServiceEmail.h
new file mode 100755 (executable)
index 0000000..f8dfd9b
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGE_SERVICE_EMAIL_H__
+#define __TIZEN_MESSAGE_SERVICE_EMAIL_H__
+
+#include "MessageService.h"
+#include "MessagingUtil.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageServiceEmail : public MessageService {
+public:
+    MessageServiceEmail(int id, std::string name);
+    virtual ~MessageServiceEmail();
+
+    virtual void sendMessage(MessageRecipientsCallbackData *callback);
+    virtual void loadMessageBody(MessageBodyCallbackData *callback);
+    virtual void loadMessageAttachment(MessageAttachmentCallbackData *callback);
+    virtual long sync(SyncCallbackData *callback);
+
+   /**
+     * @param callback - owned by this method unless exception is thrown
+     * @return opId - "long Identifier which can be used to stop this service operation"
+     *                (form JS documentation)
+     *
+     */
+    virtual long syncFolder(SyncFolderCallbackData *callback);
+
+    virtual void stopSync(long op_id);
+};
+
+} // Messaging
+} // DeviceAPI
+#endif // __TIZEN_MESSAGE_SERVICE_EMAIL_H__
diff --git a/src/Messaging/MessageServiceShortMsg.cpp b/src/Messaging/MessageServiceShortMsg.cpp
new file mode 100755 (executable)
index 0000000..cb7574b
--- /dev/null
@@ -0,0 +1,171 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <JSWebAPIError.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <tapi_common.h>
+#include <ITapiSim.h>
+#include <ITapiNetwork.h>
+#include "MessageServiceShortMsg.h"
+#include "ShortMsgManager.h"
+#include "JSMessage.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageServiceShortMsg::MessageServiceShortMsg(int id, MessageType msgType)
+        : MessageService(id,
+                msgType,
+                MessagingUtil::messageTypeToString(msgType))
+{
+    LOGD("Entered");
+}
+
+MessageServiceShortMsg::~MessageServiceShortMsg()
+{
+    LOGD("Entered");
+}
+
+static gboolean sendMessageThread(void* data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<MessageRecipientsCallbackData *>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    ShortMsgManager::getInstance().sendMessage(callback);
+    return FALSE;
+}
+
+void MessageServiceShortMsg::sendMessage(MessageRecipientsCallbackData *callback)
+{
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    if (m_msg_type != callback->getMessage()->getType()) {
+        LOGE("Incorrect message type");
+        throw Common::TypeMismatchException("Incorrect message type");
+    }
+
+    /*
+     * Set sim index.
+     * If user has set sim index manually, check sim index is valid.
+     * Otherwise, use default sim which is already set.
+     */
+    TelNetworkDefaultDataSubs_t default_sim =
+        TAPI_NETWORK_DEFAULT_DATA_SUBS_UNKNOWN;
+    TapiHandle *handle = tel_init(NULL);
+    if (NULL == handle) {
+        LOGE("Cannot initialize TAPI handle");
+        throw UnknownException("Cannot initialize TAPI handle");
+    }
+
+    int ret = tel_get_network_default_data_subscription(handle, &default_sim);
+    if (ret != TAPI_API_SUCCESS) {
+        LOGW("%s", MessagingUtil::getTApiErrorMessage(
+                    ret, "tel_get_network_default_data_subscription()").c_str());
+    }
+
+    LOGD("Default sim index: %d", default_sim);
+    callback->setDefaultSimIndex(default_sim);
+    tel_deinit(handle);
+
+    // simIndex parameter is only available for sms message.
+    // In case of mms, the parameter is silently ignored.
+    if (callback->isSetSimIndex() &&
+        callback->getMessage()->getType() == MessageType::SMS) {
+        char **cp_list = tel_get_cp_name_list();
+        TelNetworkDefaultDataSubs_t sim_index = callback->getSimIndex();
+        int sim_count = 0;
+
+        if (cp_list) {
+            while (cp_list[sim_count]) {
+                sim_count++;
+            }
+            g_strfreev(cp_list);
+        } else {
+            LOGD("Empty cp name list");
+        }
+
+        if (sim_index >= sim_count) {
+            LOGE("Sim index out of count %d : %d", sim_index, sim_count);
+            throw InvalidValuesException("The index of sim is out of bound");
+        }
+
+        callback->getMessage()->setSimIndex(sim_index);
+    } else {
+        callback->getMessage()->setSimIndex(default_sim);
+    }
+
+    if(!g_idle_add(sendMessageThread, static_cast<void*>(callback))) {
+        LOGE("g_idle_add fails");
+        throw UnknownException("Could not add task");
+    }
+}
+
+static gboolean loadMessageBodyTask(void* data)
+{
+    LOGD("Entered");
+    MessageBodyCallbackData* callback = static_cast<MessageBodyCallbackData*>(data);
+    if(!callback) {
+        LOGE("callback is NULL");
+        return FALSE;
+    }
+
+    try {
+        JSContextRef context = callback->getContext();
+        JSObjectRef jsMessage = JSMessage::makeJSObject(context, callback->getMessage());
+        callback->callSuccessCallback(jsMessage);
+    } catch (...) {
+        LOGE("Couldn't create JSMessage object!");
+        callback->callErrorCallback();
+    }
+
+    return FALSE;
+}
+
+void MessageServiceShortMsg::loadMessageBody(MessageBodyCallbackData *callback)
+{
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    if (m_msg_type != callback->getMessage()->getType()) {
+        LOGE("Incorrect message type");
+        throw Common::TypeMismatchException("Incorrect message type");
+    }
+
+    guint id = g_idle_add(loadMessageBodyTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add fails");
+        throw Common::UnknownException("Could not add task");
+    }
+}
+
+} // Messaging
+} // DeviceAPI
+
diff --git a/src/Messaging/MessageServiceShortMsg.h b/src/Messaging/MessageServiceShortMsg.h
new file mode 100755 (executable)
index 0000000..54dd4e1
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGE_SERVICE_SHORT_MSG_H__
+#define __TIZEN_MESSAGE_SERVICE_SHORT_MSG_H__
+
+#include "MessageService.h"
+#include "MessagingUtil.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageServiceShortMsg : public MessageService {
+public:
+    MessageServiceShortMsg(int id, MessageType msgType);
+    virtual ~MessageServiceShortMsg();
+
+    void sendMessage(MessageRecipientsCallbackData *callback);
+
+    virtual void loadMessageBody(MessageBodyCallbackData *callback);
+};
+
+} // Messaging
+} // DeviceAPI
+#endif // __TIZEN_MESSAGE_SERVICE_SHORT_MSG_H__
diff --git a/src/Messaging/MessageStorage.cpp b/src/Messaging/MessageStorage.cpp
new file mode 100644 (file)
index 0000000..10eb8b8
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MessageStorage.h"
+#include "ChangeListenerContainer.h"
+#include "MessagesChangeCallback.h"
+#include "ConversationsChangeCallback.h"
+#include "FoldersChangeCallback.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageStorage::MessageStorage(int id, MessageType msgType):
+        SecurityAccessor(),
+        m_id(id),
+        m_msg_type(msgType)
+{
+    LOGD("Entered");
+}
+
+MessageStorage::~MessageStorage()
+{
+    LOGD("Entered");
+}
+
+int MessageStorage::getMsgServiceId() const {
+    return m_id;
+}
+
+MessageType MessageStorage::getMsgServiceType() const {
+    return m_msg_type;
+}
+
+long MessageStorage::addMessagesChangeListener(
+            std::shared_ptr<MessagesChangeCallback> callback)
+{
+    LOGD("Entered");
+    return ChangeListenerContainer::getInstance().addMessageChangeListener(callback);
+}
+
+long MessageStorage::addConversationsChangeListener(
+            std::shared_ptr<ConversationsChangeCallback> callback)
+{
+    LOGD("Entered");
+    return ChangeListenerContainer::getInstance().addConversationChangeListener(callback);
+}
+
+long MessageStorage::addFoldersChangeListener(
+            std::shared_ptr<FoldersChangeCallback> callback)
+{
+    LOGD("Entered");
+    return ChangeListenerContainer::getInstance().addFolderChangeListener(callback);
+}
+
+void MessageStorage::removeChangeListener(JSContextRef context, long watchId)
+{
+    LOGD("Entered");
+    return ChangeListenerContainer::getInstance().removeChangeListener(context, watchId);
+}
+
+}//Messaging
+}//DeviceAPI
diff --git a/src/Messaging/MessageStorage.h b/src/Messaging/MessageStorage.h
new file mode 100644 (file)
index 0000000..82dbc19
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGE_STORAGE_H
+#define __TIZEN_MESSAGE_STORAGE_H
+
+#include "MessageCallbackUserData.h"
+#include "MessagesCallbackUserData.h"
+#include "FindMsgCallbackUserData.h"
+#include "ConversationCallbackData.h"
+#include "FoldersCallbackData.h"
+#include "MessagingUtil.h"
+#include <memory>
+// headers for ChangeListeners support
+#include "MessagesChangeCallback.h"
+#include "FoldersChangeCallback.h"
+#include "ConversationsChangeCallback.h"
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessagesChangeCallback;
+
+class MessageStorage : public Common::SecurityAccessor
+{
+public:
+    MessageStorage(int id, MessageType msgType);
+    virtual ~MessageStorage();
+
+    virtual int getMsgServiceId() const;
+    virtual MessageType getMsgServiceType() const;
+
+    virtual void addDraftMessage(MessageCallbackUserData* callback) = 0;
+    virtual void removeMessages(MessagesCallbackUserData* callback) = 0;
+    virtual void updateMessages(MessagesCallbackUserData* callback) = 0;
+    virtual void findMessages(FindMsgCallbackUserData* callback) = 0;
+    virtual void findConversations(ConversationCallbackData* callback) = 0;
+    virtual void removeConversations(ConversationCallbackData* callback) = 0;
+    virtual void findFolders(FoldersCallbackData* callback) = 0;
+
+    // Listeners registration/removal is common for all types of storage
+    // and does not have to be overwritten in derived classes.
+    long addMessagesChangeListener(
+            std::shared_ptr<MessagesChangeCallback> callback);
+    long addConversationsChangeListener(
+            std::shared_ptr<ConversationsChangeCallback> callback);
+    long addFoldersChangeListener(
+            std::shared_ptr<FoldersChangeCallback> callback);
+    void removeChangeListener(JSContextRef context, long watchId);
+
+protected:
+    int m_id;
+    MessageType m_msg_type;
+};
+
+struct MessageStorageHolder {
+    std::shared_ptr<MessageStorage> ptr;
+};
+
+}//Messaging
+}//DeviceAPI
+
+#endif /* __TIZEN_MESSAGE_STORAGE_H */
+
diff --git a/src/Messaging/MessageStorageEmail.cpp b/src/Messaging/MessageStorageEmail.cpp
new file mode 100644 (file)
index 0000000..c906eb3
--- /dev/null
@@ -0,0 +1,267 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MessageStorageEmail.h"
+#include "EmailManager.h"
+#include "Message.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageStorageEmail::MessageStorageEmail(int id):
+        MessageStorage(id, MessageType::EMAIL) {
+    LOGD("Entered");
+}
+
+MessageStorageEmail::~MessageStorageEmail() {
+    LOGD("Entered");
+}
+
+static gboolean callError(void* data)
+{
+    LOGD("Entered");
+    MessageCallbackUserData* callback =
+           static_cast<MessageCallbackUserData*>(data);
+    if (!callback) {
+       LOGE("Callback is null");
+       return FALSE;
+    }
+    JSContextRef context = callback->getContext();
+    JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+            callback->getErrorName(), callback->getErrorMessage());
+    callback->callErrorCallback(errobj);
+
+    return FALSE;
+}
+
+static gboolean addDraftMessageTask(void* data)
+{
+    LOGD("Entered");
+
+    MessageCallbackUserData *callback = static_cast<MessageCallbackUserData*>(data);
+    EmailManager::getInstance().addDraftMessage(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::addDraftMessage(MessageCallbackUserData* callback) {
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    if (m_msg_type != callback->getMessage()->getType()) {
+       LOGE("Incorrect message type");
+       callback->setError(JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+               "Incorrect message type");
+       guint id = g_idle_add(callError, static_cast<void*>(callback));
+       if (!id) {
+           LOGE("g_idle_add failed");
+           delete callback;
+           callback = NULL;
+       }
+       return;
+    }
+
+    callback->setAccountId(m_id);
+
+    guint id = g_idle_add(addDraftMessageTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean removeMessagesTask(void* data)
+{
+    LOGD("Entered");
+
+    MessagesCallbackUserData *callback = static_cast<MessagesCallbackUserData*>(data);
+    EmailManager::getInstance().removeMessages(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::removeMessages(MessagesCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(removeMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean updateMessagesTask(void* data)
+{
+    LOGD("Entered");
+
+    MessagesCallbackUserData *callback = static_cast<MessagesCallbackUserData*>(data);
+    EmailManager::getInstance().updateMessages(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::updateMessages(MessagesCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+    guint id = g_idle_add(updateMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean findMessagesTask(void* data)
+{
+    LOGD("Entered");
+
+    FindMsgCallbackUserData *callback = static_cast<FindMsgCallbackUserData*>(data);
+    EmailManager::getInstance().findMessages(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::findMessages(FindMsgCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    callback->setAccountId(m_id);
+    callback->setMessageServiceType(m_msg_type);
+    guint id = g_idle_add(findMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean findConversationsTask(void* data)
+{
+    LOGD("Entered");
+
+    ConversationCallbackData *callback = static_cast<ConversationCallbackData*>(data);
+    EmailManager::getInstance().findConversations(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::findConversations(ConversationCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    callback->setAccountId(m_id);
+    callback->setMessageServiceType(m_msg_type);
+    guint id = g_idle_add(findConversationsTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+static gboolean removeConversationsTask(void* data)
+{
+    LOGD("Entered");
+
+    ConversationCallbackData *callback = static_cast<ConversationCallbackData*>(data);
+    EmailManager::getInstance().removeConversations(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::removeConversations(ConversationCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+    guint id = g_idle_add(removeConversationsTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean findFoldersTask(void* data)
+{
+    LOGD("Entered");
+
+    FoldersCallbackData *callback = static_cast<FoldersCallbackData*>(data);
+    EmailManager::getInstance().findFolders(callback);
+
+    return FALSE;
+}
+
+void MessageStorageEmail::findFolders(FoldersCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    guint id = g_idle_add(findFoldersTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+}//Messaging
+}//DeviceAPI
diff --git a/src/Messaging/MessageStorageEmail.h b/src/Messaging/MessageStorageEmail.h
new file mode 100644 (file)
index 0000000..49f1aac
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGE_STORAGE_EMAIL_H
+#define __TIZEN_MESSAGE_STORAGE_EMAIL_H
+
+#include "MessageStorage.h"
+#include <JSWebAPIErrorFactory.h>
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageStorageEmail: public MessageStorage {
+public:
+    MessageStorageEmail(int id);
+    virtual ~MessageStorageEmail();
+
+    virtual void addDraftMessage(MessageCallbackUserData* callback);
+    virtual void removeMessages(MessagesCallbackUserData* callback);
+    virtual void updateMessages(MessagesCallbackUserData* callback);
+    virtual void findMessages(FindMsgCallbackUserData* callback);
+    virtual void findConversations(ConversationCallbackData* callback);
+    virtual void removeConversations(ConversationCallbackData* callback);
+    virtual void findFolders(FoldersCallbackData* callback);
+};
+
+}//Messaging
+}//DeviceAPI
+
+#endif /* __TIZEN_MESSAGE_STORAGE_EMAIL_H */
+
diff --git a/src/Messaging/MessageStorageShortMsg.cpp b/src/Messaging/MessageStorageShortMsg.cpp
new file mode 100755 (executable)
index 0000000..da28f16
--- /dev/null
@@ -0,0 +1,272 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "JSMessageFolder.h"
+#include <JSUtil.h>
+#include "MessageStorageShortMsg.h"
+#include "ShortMsgManager.h"
+#include <Logger.h>
+#include <PlatformException.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageStorageShortMsg::MessageStorageShortMsg(int id, MessageType msgType):
+        MessageStorage(id, msgType) {
+    LOGD("Entered");
+}
+
+MessageStorageShortMsg::~MessageStorageShortMsg() {
+    LOGD("Entered");
+}
+
+static gboolean addDraftMessageTask(void* data) {
+    LOGD("Entered");
+
+    MessageCallbackUserData *callback = static_cast<MessageCallbackUserData*>(data);
+    ShortMsgManager::getInstance().addDraftMessage(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::addDraftMessage(MessageCallbackUserData* callback) {
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw UnknownException("Callback is null");
+    }
+
+    if (m_msg_type != callback->getMessage()->getType()) {
+        LOGE("Incorrect message type");
+        throw TypeMismatchException("Incorrect message type");
+    }
+
+    guint id = g_idle_add(addDraftMessageTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        throw UnknownException("g_idle_add failed");
+    }
+}
+
+static gboolean removeMessagesTask(void* data) {
+    LOGD("Entered");
+
+    MessagesCallbackUserData *callback = static_cast<MessagesCallbackUserData*>(data);
+    ShortMsgManager::getInstance().removeMessages(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::removeMessages(MessagesCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw UnknownException("Callback is null");
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(removeMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        throw UnknownException("g_idle_add failed");
+    }
+}
+
+static gboolean updateMessagesTask(void* data) {
+    LOGD("Entered");
+
+    MessagesCallbackUserData *callback = static_cast<MessagesCallbackUserData*>(data);
+    ShortMsgManager::getInstance().updateMessages(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::updateMessages(MessagesCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw UnknownException("Callback is null");
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(updateMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        throw UnknownException("g_idle_add failed");
+    }
+}
+
+static gboolean findMessagesTask(void* data) {
+    LOGD("Entered");
+
+    FindMsgCallbackUserData *callback = static_cast<FindMsgCallbackUserData*>(data);
+    ShortMsgManager::getInstance().findMessages(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::findMessages(FindMsgCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw UnknownException("Callback is null");
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(findMessagesTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        throw UnknownException("g_idle_add failed");
+    }
+}
+
+static gboolean findConversationsTask(void* data) {
+    LOGD("Entered");
+
+    ConversationCallbackData *callback = static_cast<ConversationCallbackData*>(data);
+    ShortMsgManager::getInstance().findConversations(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::findConversations(ConversationCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw UnknownException("Callback is null");
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(findConversationsTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        throw UnknownException("g_idle_add failed");
+    }
+}
+
+static gboolean removeConversationsTask(void* data) {
+    LOGD("Entered");
+
+    ConversationCallbackData *callback = static_cast<ConversationCallbackData*>(data);
+    ShortMsgManager::getInstance().removeConversations(callback);
+
+    return false;
+}
+
+void MessageStorageShortMsg::removeConversations(ConversationCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback) {
+        LOGE("Callback is null");
+        throw UnknownException("Callback is null");
+    }
+
+    callback->setMessageServiceType(m_msg_type);
+
+    guint id = g_idle_add(removeConversationsTask, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        throw UnknownException("g_idle_add failed");
+    }
+}
+
+static gboolean findFoldersCB(void* data)
+{
+    LOGD("Entered");
+
+    FoldersCallbackData *callback = static_cast<FoldersCallbackData*>(data);
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return FALSE;
+    }
+
+    JSObjectRef js_obj = MessagingUtil::vectorToJSObjectArray<FolderPtr,
+                JSMessageFolder>(context, callback->getFolders());
+
+    callback->callSuccessCallback(js_obj);
+
+    delete callback;
+    callback = NULL;
+
+    return FALSE;
+}
+
+
+void MessageStorageShortMsg::findFolders(FoldersCallbackData* callback)
+{
+    LOGD("Entered");
+    if (!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    std::string content_type = MessagingUtil::messageTypeToString(m_msg_type);
+    std::string empty = "";
+    std::shared_ptr<MessageFolder> folder;
+
+    /* For SMS and MMS, folderId can be one of these values:
+     *
+     *  INBOX = 1,
+     *  OUTBOX = 2,
+     *  DRAFTS = 3,
+     *  SENTBOX = 4
+     */
+
+    for(int i = 1;i < 5;i++)
+    {
+        folder = std::make_shared<MessageFolder>(
+                std::to_string(i),
+                empty,
+                std::to_string(m_id),
+                content_type,
+                MessagingUtil::messageFolderTypeToString((MessageFolderType)i),
+                empty,
+                (MessageFolderType)i,
+                false);
+
+        callback->addFolder(folder);
+    }
+
+    guint id = g_idle_add(findFoldersCB, static_cast<void*>(callback));
+    if (!id) {
+        LOGE("g_idle_add failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+}//Messaging
+}//DeviceAPI
diff --git a/src/Messaging/MessageStorageShortMsg.h b/src/Messaging/MessageStorageShortMsg.h
new file mode 100644 (file)
index 0000000..ac1d77f
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGE_STORAGE_SMS_H
+#define __TIZEN_MESSAGE_STORAGE_SMS_H
+
+#include "MessageStorage.h"
+
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageStorageShortMsg: public MessageStorage {
+public:
+    MessageStorageShortMsg(int id, MessageType msgType);
+    virtual ~MessageStorageShortMsg();
+
+    virtual void addDraftMessage(MessageCallbackUserData* callback);
+    virtual void removeMessages(MessagesCallbackUserData* callback);
+    virtual void updateMessages(MessagesCallbackUserData* callback);
+    virtual void findMessages(FindMsgCallbackUserData* callback);
+    virtual void findConversations(ConversationCallbackData* callback);
+    virtual void removeConversations(ConversationCallbackData* callback);
+    virtual void findFolders(FoldersCallbackData* callback);
+};
+
+}//Messaging
+}//DeviceAPI
+
+#endif /* __TIZEN_MESSAGE_STORAGE_SMS_H */
+
diff --git a/src/Messaging/MessagesCallbackUserData.cpp b/src/Messaging/MessagesCallbackUserData.cpp
new file mode 100644 (file)
index 0000000..1e436de
--- /dev/null
@@ -0,0 +1,98 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "MessagesCallbackUserData.h"
+#include "JSMessage.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+
+MessagesCallbackUserData::MessagesCallbackUserData(JSContextRef globalCtx):
+        CallbackUserData(globalCtx),
+        m_is_error(false),
+        m_service_type(MessageType::UNDEFINED)
+{
+}
+
+MessagesCallbackUserData::~MessagesCallbackUserData() {
+}
+
+void MessagesCallbackUserData::addMessage(std::shared_ptr<Message> msg)
+{
+    m_messages.push_back(msg);
+}
+
+std::vector<std::shared_ptr<Message>> MessagesCallbackUserData::getMessages() const
+{
+    return m_messages;
+}
+
+void MessagesCallbackUserData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool MessagesCallbackUserData::isError() const
+{
+    return m_is_error;
+}
+
+std::string MessagesCallbackUserData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string MessagesCallbackUserData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void MessagesCallbackUserData::setMessageServiceType(MessageType m_msg_type)
+{
+    m_service_type = m_msg_type;
+}
+
+MessageType MessagesCallbackUserData::getMessageServiceType() const
+{
+    return m_service_type;
+}
+
+void MessagesCallbackUserData::addMessages(JSContextRef context,
+            const std::vector<JSValueRef>& jsobject_messages)
+{
+    const size_t new_messages_count = jsobject_messages.size();
+    if(0 == new_messages_count) {
+        return;
+    }
+
+    m_messages.reserve(m_messages.size() + new_messages_count);
+    for (auto it = jsobject_messages.begin() ; it != jsobject_messages.end(); ++it) {
+        m_messages.push_back(JSMessage::getPrivateObject(context, *it));
+    }
+}
+
+}//Messaging
+}//DeviceAPI
diff --git a/src/Messaging/MessagesCallbackUserData.h b/src/Messaging/MessagesCallbackUserData.h
new file mode 100644 (file)
index 0000000..39b7797
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGES_CALLBACK_USER_DATA_H
+#define __TIZEN_MESSAGES_CALLBACK_USER_DATA_H
+
+#include <CallbackUserData.h>
+#include <memory>
+#include <vector>
+#include <string>
+#include "MessagingUtil.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class Message;
+
+class MessagesCallbackUserData: public Common::CallbackUserData {
+public:
+    MessagesCallbackUserData(JSContextRef globalCtx);
+    virtual ~MessagesCallbackUserData();
+
+    void addMessages(JSContextRef context,
+            const std::vector<JSValueRef>& jsobject_messages);
+
+    void addMessage(std::shared_ptr<Message> msg);
+    std::vector<std::shared_ptr<Message>> getMessages() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    void setMessageServiceType(MessageType m_msg_type);
+    MessageType getMessageServiceType() const;
+
+private:
+    std::vector<std::shared_ptr<Message>> m_messages;
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+    MessageType m_service_type;
+};
+
+}//Messaging
+}//DeviceAPI
+
+#endif /* __TIZEN_MESSAGES_CALLBACK_USER_DATA_H */
diff --git a/src/Messaging/MessagesChangeCallback.cpp b/src/Messaging/MessagesChangeCallback.cpp
new file mode 100644 (file)
index 0000000..b10c6bf
--- /dev/null
@@ -0,0 +1,234 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+#include "MessagesChangeCallback.h"
+#include "JSMessage.h"
+#include "AbstractFilter.h"
+#include "MessagingUtil.h"
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+
+std::string limitedString(const std::string& src,
+                          const size_t max_len = 40)
+{
+    if(src.length() > max_len) {
+        return src.substr(0,max_len);
+    } else {
+        return src;
+    }
+}
+
+} //Anonymous namespace
+
+const char* MESSAGESADDED = "messagesadded";
+const char* MESSAGESUPDATED = "messagesupdated";
+const char* MESSAGESREMOVED = "messagesremoved";
+
+MessagesChangeCallback::MessagesChangeCallback(JSContextRef global_ctx,
+        JSObjectRef on_added_obj,
+        JSObjectRef on_updated_obj,
+        JSObjectRef on_removed_obj,
+        int service_id,
+        MessageType service_type) :
+        m_callback_data(global_ctx),
+        m_service_id(service_id),
+        m_msg_type(service_type),
+        m_is_act(true)
+{
+    LOGD("Entered");
+
+    m_callback_data.setCallback(MESSAGESADDED, on_added_obj);
+    m_callback_data.setCallback(MESSAGESUPDATED, on_updated_obj);
+    m_callback_data.setCallback(MESSAGESREMOVED, on_removed_obj);
+}
+
+MessagesChangeCallback::~MessagesChangeCallback()
+{
+    LOGD("Entered");
+}
+
+MessagePtrVector MessagesChangeCallback::filterMessages(
+        AbstractFilterPtr filter,
+        const MessagePtrVector& source_messages,
+        const int service_id)
+{
+    LOGD("Entered sourceMessages.size():%d filter:%s", source_messages.size(),
+            (filter ? "PRESENT" : "NULL"));
+
+    if (filter) {
+        MessagePtrVector filtered_messages;
+        MessagePtrVector::const_iterator it = source_messages.begin();
+        MessagePtrVector::const_iterator end_it = source_messages.end();
+
+        for(int i = 0; it != end_it ; ++i, ++it) {
+            const MessagePtr& message = *it;
+            message->setServiceId(service_id);
+
+            const bool matched = filter->isMatching(message.get());
+            if(matched) {
+                filtered_messages.push_back(message);
+            }
+
+            LOGD("[%d] is Message(%p) {", i, message.get());
+            LOGD("[%d] messageId: %d", i, message->getId());
+            LOGD("[%d] message subject: %s", i, message->getSubject().c_str());
+            LOGD("[%d] from: %s", i, message->getFrom().c_str());
+
+            if(message->getBody()) {
+                const std::string& pBody = message->getBody()->getPlainBody();
+                LOGD("[%d] message plainBody: %s", i, limitedString(pBody).c_str());
+            }
+
+            LOGD("[%d] matched filter: %s", i, matched ? "YES" : "NO");
+            LOGD("[%d] }");
+        }
+
+        LOGD("returning matching %d of %d messages", filtered_messages.size(),
+                source_messages.size());
+        return filtered_messages;
+    }
+    else {
+        return source_messages;
+    }
+}
+
+void MessagesChangeCallback::added(const MessagePtrVector& msgs)
+{
+    LOGD("Entered num messages: %d", msgs.size());
+    if (!m_is_act) {
+        return;
+    }
+    JSContextRef ctx = m_callback_data.getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+    MessagePtrVector filtered_msgs = filterMessages(m_filter, msgs, m_service_id);
+    //cancel callback only if filter did remove all messages
+    //if callback was called with empty msgs list, call it
+    if (msgs.size() > 0 && filtered_msgs.size() == 0) {
+        LOGD("All messages were filtered out, not calling callback");
+        return;
+    }
+    JSObjectRef js_obj = JSMessage::messageVectorToJSObjectArray(
+            ctx, filtered_msgs);
+
+    LOGD("Calling:%s with:%d added messages", MESSAGESADDED,
+        filtered_msgs.size());
+    m_callback_data.invokeCallback(MESSAGESADDED, js_obj);
+}
+
+void MessagesChangeCallback::updated(const MessagePtrVector& msgs)
+{
+    LOGD("Entered num messages: %d", msgs.size());
+    if (!m_is_act) {
+        return;
+    }
+    JSContextRef ctx = m_callback_data.getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+    MessagePtrVector filtered_msgs = filterMessages(m_filter, msgs, m_service_id);
+    //cancel callback only if filter did remove all messages
+    //if callback was called with empty msgs list, call it
+    if (msgs.size() > 0 && filtered_msgs.size() == 0) {
+        LOGD("All messages were filtered out, not calling callback");
+        return;
+    }
+    JSObjectRef js_obj = JSMessage::messageVectorToJSObjectArray(
+            ctx, filtered_msgs);
+
+    LOGD("Calling:%s with:%d updated messages", MESSAGESUPDATED,
+        filtered_msgs.size());
+    m_callback_data.invokeCallback(MESSAGESUPDATED, js_obj);
+}
+
+void MessagesChangeCallback::removed(const MessagePtrVector& msgs)
+{
+    LOGD("Enter event: msgs.size() = %d", msgs.size());
+    if (!m_is_act) {
+        return;
+    }
+
+    JSContextRef ctx = m_callback_data.getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(ctx)
+    MessagePtrVector filtered_msgs = filterMessages(m_filter, msgs, m_service_id);
+    //cancel callback only if filter did remove all messages
+    //if callback was called with empty msgs list, call it
+    if (msgs.size() > 0 && filtered_msgs.size() == 0) {
+        LOGD("All messages were filtered out, not calling callback");
+        return;
+    }
+    JSObjectRef js_obj = JSMessage::messageVectorToJSObjectArray(
+            ctx, filtered_msgs);
+
+    LOGD("Calling:%s with:%d removed messages", MESSAGESREMOVED,
+        filtered_msgs.size());
+    m_callback_data.invokeCallback(MESSAGESREMOVED, js_obj);
+}
+
+void MessagesChangeCallback::setFilter(AbstractFilterPtr filter)
+{
+    m_filter = filter;
+}
+
+AbstractFilterPtr MessagesChangeCallback::getFilter() const
+{
+    return m_filter;
+}
+
+int MessagesChangeCallback::getServiceId() const
+{
+    return m_service_id;
+}
+
+MessageType MessagesChangeCallback::getServiceType() const
+{
+    return m_msg_type;
+}
+
+void MessagesChangeCallback::setActive(bool act) {
+    m_is_act = act;
+}
+
+bool MessagesChangeCallback::isActive() {
+    return m_is_act;
+}
+
+void MessagesChangeCallback::setItems(MessagePtrVector& items)
+{
+    m_items = items;
+}
+MessagePtrVector MessagesChangeCallback::getItems()
+{
+    return m_items;
+}
+
+JSContextRef MessagesChangeCallback::getContext() const
+{
+    return m_callback_data.getContext();
+}
+
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/MessagesChangeCallback.h b/src/Messaging/MessagesChangeCallback.h
new file mode 100644 (file)
index 0000000..6f5c571
--- /dev/null
@@ -0,0 +1,80 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGES_CHANGE_CALLBACK_H__
+#define __TIZEN_MESSAGES_CHANGE_CALLBACK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include <MultiCallbackUserData.h>
+
+#include <AbstractFilter.h>
+
+#include "Message.h"
+#include "MessagingUtil.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+extern const char* MESSAGESADDED;
+extern const char* MESSAGESUPDATED;
+extern const char* MESSAGESREMOVED;
+
+class MessagesChangeCallback {
+public:
+    MessagesChangeCallback(JSContextRef globalCtx,
+            JSObjectRef on_added_obj,
+            JSObjectRef on_updated_obj,
+            JSObjectRef on_removed_obj,
+            int service_id,
+            MessageType service_type);
+    virtual ~MessagesChangeCallback();
+
+    void added(const MessagePtrVector& messages);
+    void updated(const MessagePtrVector& messages);
+    void removed(const MessagePtrVector& messages);
+
+    void setFilter(DeviceAPI::Tizen::AbstractFilterPtr filter);
+    DeviceAPI::Tizen::AbstractFilterPtr getFilter() const;
+
+    int getServiceId() const;
+    MessageType getServiceType() const;
+    static MessagePtrVector filterMessages(
+            DeviceAPI::Tizen::AbstractFilterPtr a_filter,
+            const MessagePtrVector& a_sourceMessages,
+            const int service_id);
+
+    void setActive(bool act);
+    bool isActive();
+
+    void setItems(MessagePtrVector& items);
+    MessagePtrVector getItems();
+    JSContextRef getContext() const;
+private:
+    Common::MultiCallbackUserData m_callback_data;
+    DeviceAPI::Tizen::AbstractFilterPtr m_filter;
+    int m_service_id;
+    MessageType m_msg_type;
+    bool m_is_act;
+    MessagePtrVector m_items;
+};
+
+} // Messaging
+} // DeviceAPI
+
+
+#endif // __TIZEN_MESSAGES_CHANGE_CALLBACK_H__
diff --git a/src/Messaging/MessagingDatabaseManager.cpp b/src/Messaging/MessagingDatabaseManager.cpp
new file mode 100755 (executable)
index 0000000..8555430
--- /dev/null
@@ -0,0 +1,879 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagingDatabaseManager.cpp
+ */
+
+#include <sstream>
+#include <stdio.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <msg_storage.h>
+#include <email-api.h>
+
+#include <Logger.h>
+
+#include "MessagingDatabaseManager.h"
+#include "MessagingManager.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Tizen;
+
+AttributeInfo::AttributeInfo() :
+        sql_name(),
+        sql_type(UNDEFINED_TYPE),
+        any_type(PrimitiveType_NoType)
+{
+}
+
+AttributeInfo::AttributeInfo(const std::string& in_sql_name,
+        const SQLAttributeType in_sql_type,
+        const Tizen::PrimitiveType in_any_type) :
+        sql_name(in_sql_name),
+        sql_type(in_sql_type),
+        any_type(in_any_type)
+{
+}
+
+AttributeInfo::AttributeInfo(const AttributeInfo& other) :
+        sql_name(other.sql_name),
+        sql_type(other.sql_type),
+        any_type(other.any_type)
+{
+}
+
+AttributeInfo& AttributeInfo::operator=(const AttributeInfo& other)
+{
+    sql_name = other.any_type;
+    sql_type = other.sql_type;
+    any_type = other.any_type;
+    return *this;
+}
+
+MessagingDatabaseManager::MessagingDatabaseManager()
+{
+// Attributes map for short messages ==========================================
+    m_msg_attr_map.insert(std::make_pair("id",
+            AttributeInfo("A.MSG_ID", INTEGER, PrimitiveType_String)));
+    m_msg_attr_map.insert(std::make_pair("serviceId",
+            AttributeInfo("A.MAIN_TYPE", INTEGER, PrimitiveType_String)));
+    m_msg_attr_map.insert(std::make_pair("folderId",
+            AttributeInfo("A.FOLDER_ID", INTEGER, PrimitiveType_String)));
+    m_msg_attr_map.insert(std::make_pair("type",
+            AttributeInfo("A.MAIN_TYPE", INTEGER, PrimitiveType_String)));
+    m_msg_attr_map.insert(std::make_pair("timestamp",
+            AttributeInfo("A.DISPLAY_TIME", DATETIME, PrimitiveType_Time)));
+    m_msg_attr_map.insert(std::make_pair("from",
+            AttributeInfo("B.ADDRESS_VAL", TEXT, PrimitiveType_String)));
+    m_msg_attr_map.insert(std::make_pair("to",
+            AttributeInfo("B.ADDRESS_VAL", TEXT, PrimitiveType_String)));
+    m_msg_attr_map.insert(std::make_pair("body.plainBody",
+            AttributeInfo("A.MSG_TEXT", TEXT, PrimitiveType_String)));
+    m_msg_attr_map.insert(std::make_pair("isRead",
+            AttributeInfo("A.READ_STATUS", INTEGER, PrimitiveType_Boolean)));
+    m_msg_attr_map.insert(std::make_pair("hasAttachment",
+            AttributeInfo("A.ATTACHMENT_COUNT", INTEGER, PrimitiveType_Boolean)));
+    m_msg_attr_map.insert(std::make_pair("isHighPriority",
+            AttributeInfo("A.PRIORITY", INTEGER, PrimitiveType_Boolean)));
+    m_msg_attr_map.insert(std::make_pair("subject",
+            AttributeInfo("A.SUBJECT", TEXT, PrimitiveType_String)));
+    m_msg_attr_map.insert(std::make_pair("direction",
+            AttributeInfo("A.MSG_DIRECTION", INTEGER, PrimitiveType_String)));
+
+// Attributes map for emails ==================================================
+    m_email_attr_map.insert(std::make_pair("id",
+            AttributeInfo("mail_id", INTEGER, PrimitiveType_String)));
+    m_email_attr_map.insert(std::make_pair("serviceId",
+            AttributeInfo("account_id", INTEGER, PrimitiveType_String)));
+    m_email_attr_map.insert(std::make_pair("folderId",
+            AttributeInfo("mailbox_id", INTEGER, PrimitiveType_String)));
+    m_email_attr_map.insert(std::make_pair("type",
+            AttributeInfo("account_id", INTEGER, PrimitiveType_String)));
+    m_email_attr_map.insert(std::make_pair("timestamp",
+            AttributeInfo("date_time", DATETIME, PrimitiveType_Time)));
+    m_email_attr_map.insert(std::make_pair("from",
+            AttributeInfo("full_address_from", TEXT, PrimitiveType_String)));
+    m_email_attr_map.insert(std::make_pair("to",
+            AttributeInfo("full_address_to", TEXT, PrimitiveType_String)));
+    m_email_attr_map.insert(std::make_pair("cc",
+            AttributeInfo("full_address_cc", TEXT, PrimitiveType_String)));
+    m_email_attr_map.insert(std::make_pair("bcc",
+            AttributeInfo("full_address_bcc", TEXT, PrimitiveType_String)));
+    m_email_attr_map.insert(std::make_pair("body.plainBody",
+            AttributeInfo("preview_text", TEXT, PrimitiveType_String)));
+    m_email_attr_map.insert(std::make_pair("isRead",
+            AttributeInfo("flags_seen_field", BOOLEAN, PrimitiveType_Boolean)));
+    m_email_attr_map.insert(std::make_pair("hasAttachment",
+            AttributeInfo("attachment_count", INTEGER, PrimitiveType_Boolean)));
+    m_email_attr_map.insert(std::make_pair("isHighPriority",
+            AttributeInfo("priority", INTEGER, PrimitiveType_Boolean)));
+    m_email_attr_map.insert(std::make_pair("subject",
+            AttributeInfo("subject", TEXT, PrimitiveType_String)));
+
+// Attributes map for short message conversations =============================
+    m_msg_conv_attr_map.insert(std::make_pair("id",
+            AttributeInfo("A.CONV_ID", INTEGER, PrimitiveType_String)));
+    m_msg_conv_attr_map.insert(std::make_pair("type",
+            AttributeInfo("B.MAIN_TYPE", INTEGER, PrimitiveType_String)));
+    m_msg_conv_attr_map.insert(std::make_pair("timestamp",
+            AttributeInfo("A.DISPLAY_TIME", DATETIME, PrimitiveType_Time)));
+    m_msg_conv_attr_map.insert(std::make_pair("messageCount",
+            AttributeInfo("(A.SMS_CNT + A.MMS_CNT)", INTEGER, PrimitiveType_ULong)));
+    m_msg_conv_attr_map.insert(std::make_pair("unreadMessages",
+            AttributeInfo("A.UNREAD_CNT", INTEGER, PrimitiveType_ULong)));
+    m_msg_conv_attr_map.insert(std::make_pair("preview",
+            AttributeInfo("A.MSG_TEXT", TEXT, PrimitiveType_String)));
+    m_msg_conv_attr_map.insert(std::make_pair("from",
+            AttributeInfo("C.ADDRESS_VAL", TEXT, PrimitiveType_String)));
+    m_msg_conv_attr_map.insert(std::make_pair("to",
+            AttributeInfo("C.ADDRESS_VAL", TEXT, PrimitiveType_String)));
+    m_msg_conv_attr_map.insert(std::make_pair("msgId",
+            AttributeInfo("B.MSG_ID", INTEGER, PrimitiveType_String)));
+    m_msg_conv_attr_map.insert(std::make_pair("direction",
+            AttributeInfo("B.MSG_DIRECTION", INTEGER, PrimitiveType_String)));
+
+// Attributes map for email conversations =====================================
+    m_email_conv_attr_map.insert(std::make_pair("id",
+            AttributeInfo("thread_id", INTEGER, PrimitiveType_String)));
+    m_email_conv_attr_map.insert(std::make_pair("serviceId",
+            AttributeInfo("account_id", INTEGER, PrimitiveType_String)));
+    m_email_conv_attr_map.insert(std::make_pair("type",
+            AttributeInfo("account_id", INTEGER, PrimitiveType_String)));
+    m_email_conv_attr_map.insert(std::make_pair("timestamp",
+            AttributeInfo("date_time", DATETIME, PrimitiveType_Time)));
+    m_email_conv_attr_map.insert(std::make_pair("messageCount",
+            AttributeInfo("thread_item_count", INTEGER, PrimitiveType_ULong)));
+    m_email_conv_attr_map.insert(std::make_pair("unreadMessages",
+            AttributeInfo(std::string("thread_id IN (SELECT thread_id ")
+                    + std::string("FROM mail_tbl WHERE flags_seen_field = 0 ")
+                    + std::string("GROUP BY thread_id HAVING COUNT(thread_id)"),
+                    INTEGER,
+                    PrimitiveType_ULong)));
+    m_email_conv_attr_map.insert(std::make_pair("preview",
+            AttributeInfo("preview_text", TEXT, PrimitiveType_String)));
+    m_email_conv_attr_map.insert(std::make_pair("subject",
+            AttributeInfo("subject", TEXT, PrimitiveType_String)));
+    m_email_conv_attr_map.insert(std::make_pair("from",
+            AttributeInfo("full_address_from", TEXT, PrimitiveType_String)));
+    m_email_conv_attr_map.insert(std::make_pair("to",
+            AttributeInfo("full_address_to", TEXT, PrimitiveType_String)));
+}
+
+MessagingDatabaseManager::~MessagingDatabaseManager()
+{
+
+}
+
+MessagingDatabaseManager& MessagingDatabaseManager::getInstance()
+{
+    static MessagingDatabaseManager instance;
+    return instance;
+}
+
+__thread sqlite3* sqlHandle = NULL;
+__thread sqlite3_stmt* stmt = NULL;
+
+msg_error_t MessagingDatabaseManager::connect()
+{
+    LOGD("Entered");
+    int err = 0;
+    if (NULL == sqlHandle) {
+        char strDBName[64];
+
+        memset(strDBName, 0x00, sizeof(strDBName));
+        snprintf(strDBName, sizeof(strDBName), "%s", MSG_DB_NAME);
+
+        err = db_util_open(strDBName, &sqlHandle, DB_UTIL_REGISTER_HOOK_METHOD);
+
+        if (SQLITE_OK != err) {
+            LOGW("%s", MessagingUtil::getDbUtilErrorMessage(err, "db_util_open()").c_str());
+            return MSG_ERR_DB_CONNECT;
+        }
+
+        LOGD("DB connecting success: [%d]", sqlHandle);
+    } else {
+        LOGD("DB connection exists: [%d]", sqlHandle);
+    }
+
+    return MSG_SUCCESS;
+}
+
+msg_error_t MessagingDatabaseManager::disconnect()
+{
+    LOGD("Entered");
+    msg_error_t err = 0;
+    if (NULL != sqlHandle) {
+        err = db_util_close(sqlHandle);
+
+        if (SQLITE_OK != err) {
+            LOGW("%s", MessagingUtil::getDbUtilErrorMessage(err, "db_util_close()").c_str());
+            return MSG_ERR_DB_DISCONNECT;
+        }
+
+        sqlHandle = NULL;
+        LOGD("DB disconnecting success");
+    }
+
+    return MSG_SUCCESS;
+}
+
+msg_error_t MessagingDatabaseManager::getTable(std::string sqlQuery,
+        char*** results,
+        int* resultsCount)
+{
+    LOGD("Entered");
+    msg_error_t err = 0;
+    *resultsCount = 0;
+
+    freeTable(results);
+    connect();
+
+
+    char* error_msg = NULL;
+    err = sqlite3_get_table(sqlHandle, sqlQuery.c_str(), results,
+            resultsCount, 0, &error_msg);
+
+    if (SQLITE_OK != err) {
+        LOGW("%s", MessagingUtil::getDbUtilErrorMessage(err, "sqlite3_get_table()").c_str());
+        freeTable(results);
+        return MSG_ERR_DB_GETTABLE;
+    }
+
+    LOGD("Getting table success");
+    if (0 == *resultsCount) {
+        LOGD("No results");
+    }
+
+    disconnect();
+    return MSG_SUCCESS;
+}
+
+void MessagingDatabaseManager::freeTable(char*** results)
+{
+    LOGD("Entered");
+    if (*results) {
+        sqlite3_free_table(*results);
+        *results = NULL;
+    }
+}
+
+int MessagingDatabaseManager::cellToInt(char** array, int cellId)
+{
+    LOGD("Entered");
+    if (NULL == array) {
+        LOGD("Array is NULL");
+        return 0;
+    }
+
+    char* tmp = *(array + cellId);
+    if (NULL == tmp) {
+        LOGD("Cell is NULL");
+        return 0;
+    }
+
+    return static_cast<int>(strtol(tmp, (char**) NULL, 10));
+}
+
+std::string MessagingDatabaseManager::getMatchString(Tizen::AnyPtr match_value,
+        const PrimitiveType type) const
+{
+    if(!match_value) {
+        LOGD("Warning: match value is NULL");
+        return std::string();
+    }
+
+    std::ostringstream converter;
+    switch(type) {
+        case PrimitiveType_NoType: {
+            LOGD("Warning: match value is no type");
+            return std::string();
+        }
+        case PrimitiveType_Null: {
+            LOGD("Warning: match value is null");
+            return std::string();
+        }
+        case PrimitiveType_Boolean: {
+            converter << match_value->toBool();
+            return converter.str();
+        }
+        case PrimitiveType_Long: {
+            converter << match_value->toLong();
+            return converter.str();
+        }
+        case PrimitiveType_ULong: {
+            converter << match_value->toULong();
+            return converter.str();
+        }
+        case PrimitiveType_LongLong: {
+            converter << match_value->toLongLong();
+            return converter.str();
+        }
+        case PrimitiveType_ULongLong: {
+            converter << match_value->toULongLong();
+            return converter.str();
+        }
+        case PrimitiveType_Double: {
+            converter << match_value->toDouble();
+            return converter.str();
+        }
+        case PrimitiveType_String: {
+            return match_value->toString();
+        }
+        case PrimitiveType_Time: {
+            converter << match_value->toTimeT();
+            return converter.str();
+        }
+        default: {
+            LOGD("Warning: match value is not specified");
+            return std::string();
+        }
+    }
+}
+
+std::string MessagingDatabaseManager::getAttributeFilterQuery(AbstractFilterPtr filter,
+        AttributeInfoMap& attribute_map, MessageType msgType)
+{
+    LOGD("Entered");
+
+    std::ostringstream sqlQuery;
+    AttributeFilterPtr attr_filter = castToAttributeFilter(filter);
+    if(!attr_filter) {
+        LOGE("passed filter is not valid AttributeFilter!");
+        throw UnknownException("Wrong filter type - not attribute filter");
+    }
+
+    const std::string attribute_name = attr_filter->getAttributeName();
+
+    AttributeInfoMap::iterator it = attribute_map.find(attribute_name);
+    if (it != attribute_map.end()) {
+        sqlQuery << "(" << attribute_map[attribute_name].sql_name << " ";
+    } else {
+        LOGE("The attribute: %s does not exist.", attribute_name.c_str());
+        throw InvalidValuesException("The attribute does not exist.");
+    }
+
+    AnyPtr match_value_any_ptr = attr_filter->getMatchValue();
+    const AttributeInfo& attr_info = it->second;
+    std::string match_value = getMatchString(match_value_any_ptr, attr_info.any_type);
+    const FilterMatchFlag match_flag = attr_filter->getMatchFlag();
+
+    LOGD("match_value_any_ptr:%p any_type:%d attr_name:%s match_value:%s",
+            match_value_any_ptr.get(), attr_info.any_type, attribute_name.c_str(),
+            match_value.c_str());
+
+    if ("serviceId" == attribute_name) {
+
+        int i_matchValue;
+        std::istringstream iss(match_value);
+        iss >> i_matchValue;
+
+        switch(i_matchValue) {
+        case MessageServiceAccountId::SMS_ACCOUNT_ID: {
+            sqlQuery << "= " << MessageType::SMS;
+            break;
+        }
+        case MessageServiceAccountId::MMS_ACCOUNT_ID: {
+            sqlQuery << "= " << MessageType::MMS;
+            break;
+        }
+        default:
+            sqlQuery << "= " << match_value;
+        }
+    }
+    else if ("type" == attribute_name) {
+        if ("messaging.sms" == match_value && MessageType::SMS == msgType) {
+            sqlQuery << "= " << msgType;
+        } else if ("messaging.mms" == match_value && MessageType::MMS == msgType) {
+            sqlQuery << "= " << msgType;
+        } else if ("messaging.email" == match_value && MessageType::EMAIL == msgType) {
+            sqlQuery << "= " << attr_info.sql_name;
+        } else {
+            LOGE("attribute \"type\" matchValue:%s "
+                    "does not match messaging.sms/mms/email\n"
+                    "msgType:%d does not match SMS(%d), MMS(%d) nor EMAIL(%d)!",
+                    match_value.c_str(), msgType, MessageType::SMS, MessageType::MMS,
+                    MessageType::EMAIL);
+            throw UnknownException("The value does not match service type.");
+        }
+    }
+    else if ("isRead" == attribute_name || "hasAttachment" == attribute_name) {
+        if (attr_filter->getMatchValue()->toBool()) {
+            sqlQuery << "> 0";
+        } else {
+            sqlQuery << "= 0";
+        }
+    }
+    else if ("isHighPriority" == attribute_name) {
+        if (attr_filter->getMatchValue()->toBool()) {
+            sqlQuery << "= ";
+        } else {
+            sqlQuery << "<> ";
+        }
+
+        if (MessageType::SMS == msgType || MessageType::MMS == msgType) {
+            sqlQuery << MSG_MESSAGE_PRIORITY_HIGH;
+        } else if (MessageType::EMAIL == msgType) {
+            sqlQuery << EMAIL_MAIL_PRIORITY_HIGH;
+        }
+    }
+    else {
+        // Addresses which are stored in database can have different form than in filters
+        if (MessageType::EMAIL == msgType && ("from" == attribute_name ||
+                "to" == attribute_name || "cc" == attribute_name ||
+                "bcc" == attribute_name)) {
+            std::size_t foundPos;
+            while ((foundPos = match_value.find('<')) != std::string::npos) {
+                match_value.erase(foundPos, 1);
+            }
+
+            while ((foundPos = match_value.find('>')) != std::string::npos) {
+                match_value.erase(foundPos, 1);
+            }
+
+            if (EXACTLY == match_flag) {
+                match_value = "%<" + match_value + ">%";
+            } else if (CONTAINS == match_flag) {
+                match_value = "%<%" + match_value + "%>%";
+            } else if (STARTSWITH == match_flag) {
+                match_value = "%<" + match_value + "%>%";
+            } else if (ENDSWITH == match_flag) {
+                match_value = "%<%" + match_value + ">%";
+            }
+        }
+
+        switch (match_flag) {
+            /*
+            case NONE: {
+                // Determines if the apostrophes have to be added over match value
+                if (TEXT == attribute_map[attribute_name].sql_type) {
+                    sqlQuery << "NOT LIKE '" << match_value << "'";
+                } else {
+                    sqlQuery << "<> " << match_value;
+                }
+                break;
+            }*/
+            case EXACTLY: {
+                // Determines if the apostrophes have to be added over match value
+                if (TEXT == attribute_map[attribute_name].sql_type) {
+                    sqlQuery << "LIKE '" << match_value << "'";
+                } else {
+                    sqlQuery << "= " << match_value;
+                }
+                break;
+            }
+            case CONTAINS: {
+                sqlQuery << "LIKE '%" << match_value << "%'";
+                break;
+            }
+            case STARTSWITH: {
+                sqlQuery << "LIKE '" << match_value << "%'";
+                break;
+            }
+            case ENDSWITH: {
+                sqlQuery << "LIKE '%" << match_value << "'";
+                break;
+            }
+            case EXISTS: {
+                if ("unreadMessages" != attribute_name) {
+                    sqlQuery << "IS NOT NULL";
+                } else {
+                    sqlQuery << "!= 0";
+                }
+                break;
+            }
+            default:
+                throw UnknownException("The match flag is incorrect.");
+        }
+
+        if (MessageType::SMS == msgType || MessageType::MMS == msgType) {
+            if ("from" == attribute_name) {
+                // "From" and "to" attributes require message direction value
+                sqlQuery << " AND " << attribute_map["direction"].sql_name << " = 1";
+            } else if ("to" == attribute_name) {
+                sqlQuery << " AND " << attribute_map["direction"].sql_name << " <> 1";
+            }
+        } else if (MessageType::EMAIL == msgType) {
+            if("unreadMessages" == attribute_name) {
+                sqlQuery << ")";
+            }
+        }
+    }
+    sqlQuery << ") ";
+    return sqlQuery.str();
+}
+
+std::string MessagingDatabaseManager::getAttributeRangeFilterQuery(AbstractFilterPtr filter,
+        AttributeInfoMap& attribute_map, MessageType msg_type)
+{
+    LOGD("Entered");
+
+    std::ostringstream sql_query, converter;
+    std::string initial_value, end_value;
+
+    AttributeRangeFilterPtr attr_range_filter = castToAttributeRangeFilter(filter);
+    if(!attr_range_filter) {
+        LOGE("passed filter is not valid AttributeRangeFilter!");
+        throw UnknownException("Wrong filter type - not attribute range filter");
+    }
+
+    converter << attr_range_filter->getInitialValue()->toTimeT();
+    initial_value = converter.str();
+    converter.str("");
+    converter << attr_range_filter->getEndValue()->toTimeT();
+    end_value = converter.str();
+
+    sql_query << "(" << attribute_map[attr_range_filter->getAttributeName()].sql_name << " ";
+    sql_query << "BETWEEN " << initial_value << " AND " << end_value << ") ";
+    return sql_query.str();
+}
+
+std::string MessagingDatabaseManager::getCompositeFilterQuery(AbstractFilterPtr filter,
+        AttributeInfoMap& attribute_map, MessageType msg_type)
+{
+    LOGD("Entered");
+    std::ostringstream sql_query;
+
+    CompositeFilterPtr comp_filter = castToCompositeFilter(filter);
+    if(!comp_filter) {
+        LOGE("passed filter is not valid CompositeFilter!");
+        throw UnknownException("Wrong filter type - not composite filter");
+    }
+
+    AbstractFilterPtrVector filters_arr = comp_filter->getFilters();
+
+    std::string logical_operator;
+    if (UNION == comp_filter->getType()) {
+        logical_operator = "OR ";
+    } else {
+        logical_operator = "AND ";
+    }
+
+    sql_query << "(";
+    const unsigned int size = filters_arr.size();
+    for (unsigned int i = 0; i < size; ++i) {
+
+        const FilterType filter_type = filters_arr[i]->getFilterType();
+        switch (filter_type) {
+            case ATTRIBUTE_FILTER: {
+                sql_query << getAttributeFilterQuery(filters_arr[i], attribute_map, msg_type);
+                break;
+            }
+            case ATTRIBUTE_RANGE_FILTER: {
+                sql_query << getAttributeRangeFilterQuery(filters_arr[i], attribute_map, msg_type);
+                break;
+            }
+            case COMPOSITE_FILTER: {
+                sql_query << getCompositeFilterQuery(filters_arr[i], attribute_map, msg_type);
+                break;
+            }
+            default:
+                LOGE("Error while querying message - unsupported filter type: %d",
+                        filter_type);
+                throw UnknownException("Error while querying message.");
+        }
+
+        if (i != (size - 1)) {
+            sql_query << logical_operator;
+        }
+    }
+    sql_query << ") ";
+
+    return sql_query.str();
+}
+
+std::string MessagingDatabaseManager::addFilters(AbstractFilterPtr filter,
+        SortModePtr sort_mode, long limit, long offset, AttributeInfoMap& attribute_map,
+        MessageType msg_type)
+{
+    LOGD("Entered");
+    std::ostringstream sql_query;
+
+    // Service type query
+    if (MessageType::SMS == msg_type || MessageType::MMS == msg_type) {
+        if (UNDEFINED != msg_type) {
+            sql_query << attribute_map["type"].sql_name << " = " << msg_type << " AND ";
+        } else {
+            LOGE("The service type is incorrect - msg_type is UNDEFINED");
+            throw UnknownException("The service type is incorrect.");
+        }
+    }
+
+    if(filter) {
+        // Filter query
+        switch (filter->getFilterType()) {
+            case ATTRIBUTE_FILTER: {
+                sql_query << getAttributeFilterQuery(filter, attribute_map, msg_type);
+            } break;
+
+            case ATTRIBUTE_RANGE_FILTER: {
+                sql_query << getAttributeRangeFilterQuery(filter, attribute_map, msg_type);
+            } break;
+
+            case COMPOSITE_FILTER : {
+                sql_query << getCompositeFilterQuery(filter, attribute_map, msg_type);
+            } break;
+
+            default:
+                LOGE("The filter type is incorrect: %d", filter->getFilterType());
+                throw UnknownException("The filter type is incorrect.");
+        }
+    }
+
+    // SortMode query
+    if (sort_mode) {
+        if (attribute_map.find(sort_mode->getAttributeName()) != attribute_map.end()) {
+            sql_query << "ORDER BY "
+                    << attribute_map[sort_mode->getAttributeName()].sql_name << " ";
+        } else {
+            LOGE("The attribute does not exist.");
+            throw UnknownException("The attribute does not exist.");
+        }
+
+        if (ASC == sort_mode->getOrder()) {
+            sql_query << "ASC ";
+        } else {
+            sql_query << "DESC ";
+        }
+    }
+
+    // Limit query
+    if (0 != limit) {
+        sql_query << "LIMIT " << limit << " ";
+    }
+
+    // Offset query
+    if (0 != offset) {
+        if( 0 == limit ) {
+            //Ugly fix proposed by mySQL team:
+            //http://dev.mysql.com/doc/refman/5.0/en/select.html
+            //To retrieve all rows from a certain offset up to the end of the result set,
+            //you can use some large number for the second parameter.
+            //
+            //Reason: to use OFFSET you need to have LIMIT statement
+            //18446744073709551615 is 2^64-1 - max value of big int
+            //However we will use -1 since it will work fine for various int sizes (this
+            //trick have been used in old implementation).
+
+            sql_query << "LIMIT -1 ";
+        }
+        sql_query << "OFFSET " << offset << " ";
+    }
+
+    return sql_query.str();
+}
+
+std::vector<int> MessagingDatabaseManager::findShortMessages(
+        FindMsgCallbackUserData* callback)
+{
+    LOGD("Entered");
+    std::ostringstream sqlQuery;
+    int attributesCount = 1; // It has to be set manually each time when the query is changed
+    int cellId = attributesCount;
+    char** results = NULL;
+    int resultsCount;
+    std::vector<int> messagesIds;
+
+    sqlQuery << "SELECT " << "DISTINCT(" << m_msg_attr_map["id"].sql_name << ") "
+            << "FROM " << MSG_MESSAGE_TABLE_NAME << " A "
+            << "JOIN " << MSG_ADDRESS_TABLE_NAME << " B "
+            << "ON A.CONV_ID = B.CONV_ID " << "WHERE B.ADDRESS_ID <> 0 AND ";
+
+    // Adding filters query
+    AbstractFilterPtr filter = callback->getFilter();
+    SortModePtr sortMode = callback->getSortMode();
+    long limit = callback->getLimit();
+    long offset = callback->getOffset();
+    MessageType msgType = callback->getMessageServiceType();
+
+    sqlQuery << addFilters(filter, sortMode, limit, offset, m_msg_attr_map, msgType);
+    LOGD("%s", sqlQuery.str().c_str());
+
+    // Getting results from database
+    msg_error_t err = getTable(sqlQuery.str(), &results, &resultsCount);
+    if (MSG_SUCCESS != err) {
+        freeTable(&results);
+        LOGE("ret: %d", err);
+        MessagingUtil::throwMsgException<UnknownException>(err, "getTable()");
+    }
+
+    for (int i = 0; i < resultsCount; ++i) {
+        messagesIds.push_back(cellToInt(results, cellId++));
+        LOGD("id: %d", messagesIds.at(messagesIds.size() - 1));
+    }
+
+    freeTable(&results);
+    return messagesIds;
+}
+
+std::pair<int, email_mail_data_t*> MessagingDatabaseManager::findEmails(
+        FindMsgCallbackUserData* callback)
+{
+    LOGD("Entered");
+    std::ostringstream sqlWhereClause;
+    int resultsCount;
+    email_mail_data_t* results;
+
+    // Adding filters query
+    AbstractFilterPtr filter = callback->getFilter();
+    SortModePtr sortMode = callback->getSortMode();
+    long limit = callback->getLimit();
+    long offset = callback->getOffset();
+    MessageType msgType = callback->getMessageServiceType();
+    int accountId = callback->getAccountId();
+
+    sqlWhereClause << "WHERE "
+            << m_email_attr_map["serviceId"].sql_name << " = " << accountId << " AND "
+            << addFilters(filter, sortMode, limit, offset, m_email_attr_map, msgType);
+    LOGD("%s", sqlWhereClause.str().c_str());
+
+    // Getting results from database
+    msg_error_t err = email_query_mails(const_cast<char*>(sqlWhereClause.str().c_str()),
+                &results, &resultsCount);
+    if (EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_query_mails()").c_str());
+
+        if (EMAIL_ERROR_MAIL_NOT_FOUND == err) {
+            resultsCount = 0;
+        } else {
+            LOGE("ret: %d", err);
+            MessagingUtil::throwEmailException<UnknownException>(err, "email_query_mails()");
+        }
+    }
+
+    return std::make_pair(resultsCount, results);
+}
+
+std::vector<int> MessagingDatabaseManager::findShortMessageConversations(
+        ConversationCallbackData* callback)
+{
+    LOGD("Entered");
+    std::ostringstream sqlQuery;
+    int attributesCount = 1; // It has to be set manually each time when the query is changed
+    int cellId = attributesCount;
+    char** results = NULL;
+    int resultsCount;
+    std::vector<int> conversationsIds;
+
+    sqlQuery << "SELECT " << "DISTINCT(" << m_msg_conv_attr_map["id"].sql_name << ") "
+            << "FROM " << MSG_CONVERSATION_TABLE_NAME << " A "
+            << "JOIN " << MSG_MESSAGE_TABLE_NAME << " B "
+            << "ON A.CONV_ID = B.CONV_ID "
+            << "JOIN " << MSG_ADDRESS_TABLE_NAME << " C "
+            << "ON A.CONV_ID = C.CONV_ID "
+            << "WHERE (A.SMS_CNT > 0 OR A.MMS_CNT > 0) AND ";
+
+    // Adding filters query
+    AbstractFilterPtr filter = callback->getFilter();
+    SortModePtr sortMode = callback->getSortMode();
+    long limit = callback->getLimit();
+    long offset = callback->getOffset();
+    MessageType msgType = callback->getMessageServiceType();
+
+    sqlQuery << addFilters(filter, sortMode, limit, offset, m_msg_conv_attr_map, msgType);
+    LOGD("%s", sqlQuery.str().c_str());
+
+    // Getting results from database
+    msg_error_t err = getTable(sqlQuery.str(), &results, &resultsCount);
+    if (MSG_SUCCESS != err) {
+        freeTable(&results);
+        LOGE("ret: %d", err);
+        MessagingUtil::throwMsgException<UnknownException>(err, "getTable()");
+    }
+
+    for (int i = 0; i < resultsCount; ++i) {
+        conversationsIds.push_back(cellToInt(results, cellId++));
+        LOGD("id: %d", conversationsIds.at(conversationsIds.size() - 1));
+    }
+
+    freeTable(&results);
+    return conversationsIds;
+}
+
+std::vector<EmailConversationInfo> MessagingDatabaseManager::findEmailConversations(
+        ConversationCallbackData* callback)
+{
+    LOGD("Entered");
+    std::ostringstream sqlWhereClause;
+    int resultsCount;
+    email_mail_data_t* results;
+    std::map<int, int> conversationsBag;
+    std::vector<EmailConversationInfo> conversationsInfo;
+    msg_error_t err;
+
+    // Adding filters query
+    AbstractFilterPtr filter = callback->getFilter();
+    SortModePtr sortMode = callback->getSortMode();
+    long limit = callback->getLimit();
+    long offset = callback->getOffset();
+    MessageType msgType = callback->getMessageServiceType();
+    int accountId = callback->getAccountId();
+
+    sqlWhereClause << "WHERE "
+            << m_email_conv_attr_map["serviceId"].sql_name << " = " << accountId << " AND "
+            << addFilters(filter, sortMode, limit, offset, m_email_conv_attr_map, msgType);
+    LOGD("%s", sqlWhereClause.str().c_str());
+
+    // Getting results from database
+    err = email_query_mails(const_cast<char*>(sqlWhereClause.str().c_str()),
+                &results, &resultsCount);
+    if (EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_query_mails()").c_str());
+
+        if (EMAIL_ERROR_MAIL_NOT_FOUND == err) {
+            resultsCount = 0;
+        } else {
+            LOGE("ret: %d", err);
+            MessagingUtil::throwEmailException<UnknownException>(err, "email_query_mails()");
+        }
+    }
+
+    // Assigning found emails to conversation
+    for (int i = 0; i < resultsCount; ++i) {
+        if (conversationsBag.find(results[i].thread_id) == conversationsBag.end()) {
+            EmailConversationInfo info;
+            info.id = results[i].thread_id;
+            conversationsInfo.push_back(info);
+            conversationsBag.insert(std::make_pair(results[i].thread_id, 0));
+        }
+
+        if (!(static_cast<bool>(results[i].flags_seen_field))) {
+            ++conversationsBag[results[i].thread_id];
+        }
+    }
+
+    for (std::vector<EmailConversationInfo>::iterator it = conversationsInfo.begin();
+            it != conversationsInfo.end(); ++it) {
+        (*it).unreadMessages = conversationsBag[(*it).id];
+    }
+
+    err = email_free_mail_data(&results, resultsCount);
+    if (EMAIL_ERROR_NONE != err) {
+        LOGW("%s", MessagingUtil::getEmailErrorMessage(err, "email_free_mail_data()").c_str());
+    }
+    return conversationsInfo;
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/MessagingDatabaseManager.h b/src/Messaging/MessagingDatabaseManager.h
new file mode 100755 (executable)
index 0000000..6c0286a
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagingDatabaseManager.h
+ */
+
+#ifndef __TIZEN_MSG_DATABASE_MANAGER_H__
+#define __TIZEN_MSG_DATABASE_MANAGER_H__
+
+#include <iostream>
+#include <map>
+
+#include <msg.h>
+#include <db-util.h>
+#include <AbstractFilter.h>
+
+#include "FindMsgCallbackUserData.h"
+#include "ConversationCallbackData.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+// =================================================================
+#define MSG_DB_NAME                     "/opt/usr/dbspace/.msg_service.db"
+#define MSG_MESSAGE_TABLE_NAME          "MSG_MESSAGE_TABLE"
+#define MSG_FOLDER_TABLE_NAME           "MSG_FOLDER_TABLE"
+#define MSG_ADDRESS_TABLE_NAME          "MSG_ADDRESS_TABLE"
+#define MSG_CONVERSATION_TABLE_NAME     "MSG_CONVERSATION_TABLE"
+#define MSG_SIM_MSG_TABLE_NAME          "MSG_SIM_TABLE"
+#define MSG_FILTER_TABLE_NAME           "MSG_FILTER_TABLE"
+#define MSG_PUSH_MSG_TABLE_NAME         "MSG_PUSH_TABLE"
+#define MSG_CB_MSG_TABLE_NAME           "MSG_CBMSG_TABLE"
+#define MMS_PLUGIN_MESSAGE_TABLE_NAME   "MSG_MMS_MESSAGE_TABLE"
+#define MSG_SYNCML_MSG_TABLE_NAME       "MSG_SYNCML_TABLE"
+#define MSG_SCHEDULED_MSG_TABLE_NAME    "MSG_SCHEDULED_TABLE"
+#define MSG_SMS_SENDOPT_TABLE_NAME      "MSG_SMS_SENDOPT_TABLE"
+// =================================================================
+enum SQLAttributeType {
+    UNDEFINED_TYPE,
+    BOOLEAN,
+    INTEGER,
+    DATETIME,
+    TEXT,
+};
+
+struct AttributeInfo {
+    AttributeInfo();
+    AttributeInfo(const std::string& in_sql_name,
+            const SQLAttributeType in_sql_type,
+            const Tizen::PrimitiveType in_any_type);
+    AttributeInfo(const AttributeInfo& other);
+    AttributeInfo& operator=(const AttributeInfo& other);
+
+    std::string sql_name;
+    SQLAttributeType sql_type;
+    Tizen::PrimitiveType any_type;
+};
+
+typedef std::map<std::string, AttributeInfo> AttributeInfoMap;
+
+struct EmailConversationInfo {
+    int id, unreadMessages;
+};
+// =================================================================
+
+class MessagingDatabaseManager {
+public:
+    static MessagingDatabaseManager& getInstance();
+    std::vector<int> findShortMessages(FindMsgCallbackUserData* callback);
+    std::pair<int, email_mail_data_t*> findEmails(FindMsgCallbackUserData* callback);
+    std::vector<int> findShortMessageConversations(ConversationCallbackData* callback);
+    std::vector<EmailConversationInfo> findEmailConversations(ConversationCallbackData* callback);
+
+private:
+    MessagingDatabaseManager();
+    MessagingDatabaseManager(const MessagingDatabaseManager &);
+    void operator=(const MessagingDatabaseManager &);
+    virtual ~MessagingDatabaseManager();
+
+    msg_error_t connect();
+    msg_error_t disconnect();
+    msg_error_t getTable(std::string query, char*** results, int* resultsCount);
+    void freeTable(char*** array);
+    int cellToInt(char** array, int cellId);
+    std::string getMatchString(Tizen::AnyPtr matchValue,
+            const Tizen::PrimitiveType type) const;
+    std::string getAttributeFilterQuery(Tizen::AbstractFilterPtr filter,
+            AttributeInfoMap& attributeMap, MessageType msgType);
+    std::string getAttributeRangeFilterQuery(Tizen::AbstractFilterPtr filter,
+            AttributeInfoMap& attributeMap, MessageType msgType);
+    std::string getCompositeFilterQuery(Tizen::AbstractFilterPtr filter,
+            AttributeInfoMap& attributeMap, MessageType msgType);
+    std::string addFilters(Tizen::AbstractFilterPtr filter, Tizen::SortModePtr sortMode,
+            long limit, long offset, AttributeInfoMap& attributeMap, MessageType msgType);
+
+    AttributeInfoMap m_msg_attr_map;
+    AttributeInfoMap m_email_attr_map;
+
+    AttributeInfoMap m_msg_conv_attr_map;
+    AttributeInfoMap m_email_conv_attr_map;
+};
+
+} // Messaging
+} // DeviceAPI
+
+#endif // __TIZEN_MSG_DATABASE_MANAGER_H__
diff --git a/src/Messaging/MessagingManager.cpp b/src/Messaging/MessagingManager.cpp
new file mode 100755 (executable)
index 0000000..b5b9531
--- /dev/null
@@ -0,0 +1,351 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <JSWebAPIError.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+#include <system_info.h>
+
+#include <email-types.h>
+#include <email-api.h>
+
+#include "MessagingManager.h"
+#include "MessagingUtil.h"
+#include "JSMessageService.h"
+#include "MessageService.h"
+#include "MessageServiceShortMsg.h"
+#include "MessageServiceEmail.h"
+#include "ShortMsgManager.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+MessageServiceCallbackData::MessageServiceCallbackData(JSContextRef globalCtx):
+    CallbackUserData(globalCtx),
+    m_msg_type(MessageType::UNDEFINED),
+    m_is_error(false)
+{
+    LOGD("Entered");
+}
+
+MessageServiceCallbackData::~MessageServiceCallbackData()
+{
+    LOGD("Entered");
+}
+
+void MessageServiceCallbackData::setMessageType(MessageType msgType)
+{
+    m_msg_type = msgType;
+}
+
+MessageType MessageServiceCallbackData::getMessageType() const
+{
+    return m_msg_type;
+}
+
+void MessageServiceCallbackData::setMessageServices(
+        const std::vector<MessageService*>& msgServices)
+{
+    m_msg_services = msgServices;
+}
+
+const std::vector<MessageService*>& MessageServiceCallbackData::getMessageServices() const
+{
+    return m_msg_services;
+}
+
+void MessageServiceCallbackData::setError(const std::string& err_name,
+        const std::string& err_message)
+{
+    // keep only first error in chain
+    if (!m_is_error) {
+        m_is_error = true;
+        m_err_name = err_name;
+        m_err_message = err_message;
+    }
+}
+
+bool MessageServiceCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+std::string MessageServiceCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string MessageServiceCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void MessageServiceCallbackData::clearServices()
+{
+    unsigned int count = m_msg_services.size();
+    for (unsigned int i = 0; i < count; ++i) {
+        delete m_msg_services.at(i);
+    }
+    m_msg_services.clear();
+}
+
+
+static gboolean getMsgServicesCompleteCB(void* data)
+{
+    LOGD("Entered");
+
+    MessageServiceCallbackData* callback = static_cast<MessageServiceCallbackData*>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+        else {
+            std::vector<MessageService*> msgServices = callback->getMessageServices();
+            unsigned int count = msgServices.size();
+            JSValueRef result = NULL;
+
+            JSObjectRef jsMsgServicesObject[count];
+            for (unsigned int i = 0; i < count; ++i) {
+                jsMsgServicesObject[i] = JSMessageService::createJSObject(context,
+                        msgServices.at(i));
+                if (NULL == jsMsgServicesObject[i]) {
+                    LOGE("Message service object creation failed");
+                    throw Common::UnknownException(
+                            "Message service object creation failed");
+                }
+            }
+            result = JSObjectMakeArray(context, count,
+                    count > 0 ? jsMsgServicesObject : NULL, NULL);
+
+            if (!result) {
+                JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                        "Could not create JS array object");
+                callback->clearServices();
+                callback->callErrorCallback(errobj);
+            }
+            else {
+                callback->callSuccessCallback(result);
+            }
+        }
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context, err);
+        callback->clearServices();
+        callback->callErrorCallback(errobj);
+    }
+    catch (...) {
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Cannot retrieve JS message services");
+        callback->clearServices();
+        callback->callErrorCallback(errobj);
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+static void* getMsgServicesThread(void* data)
+{
+    LOGD("Entered");
+
+    MessageServiceCallbackData* callback = static_cast<MessageServiceCallbackData*>(data);
+    if(!callback){
+        LOGE("Callback is null");
+        return NULL;
+    }
+
+    MessageType msgType = callback->getMessageType();
+    std::vector<MessageService*> msgServices;
+    MessageService* messageService = NULL;
+    email_account_t* email_accounts = NULL;
+    int count = 0;
+    bool isSupported = false;
+    int err;
+
+    try {
+        switch (msgType) {
+        case MessageType::SMS:
+            messageService = new(std::nothrow) MessageServiceShortMsg(
+                    MessageServiceAccountId::SMS_ACCOUNT_ID,
+                    MessageType::SMS);
+            if (!messageService) {
+                callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                        "MessageService for SMS creation failed");
+            } else {
+                msgServices.push_back(messageService);
+            }
+            callback->setMessageServices(msgServices);
+            break;
+        case MessageType::MMS:
+            messageService = new(std::nothrow) MessageServiceShortMsg(
+                    MessageServiceAccountId::MMS_ACCOUNT_ID,
+                    MessageType::MMS);
+            if (!messageService) {
+                callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                        "MessageService for MMS creation failed");
+            } else {
+                msgServices.push_back(messageService);
+            }
+            callback->setMessageServices(msgServices);
+            break;
+        case MessageType::EMAIL:
+            err = email_get_account_list(&email_accounts, &count);
+            if (EMAIL_ERROR_NONE != err) {
+                LOGW("%s", MessagingUtil::getEmailErrorMessage(
+                            err, "email_get_account_list()").c_str());
+                callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                        "Cannot get email accounts");
+            } else {
+                std::stringstream stream_name;
+                for (int i = 0; i < count; ++i) {
+                    stream_name << "[" << email_accounts[i].account_name << "] "
+                            << email_accounts[i].incoming_server_user_name;
+                    SLOGD("Account[%d/%d] id: %d, name: %s", i, count,
+                            email_accounts[i].account_id, stream_name.str().c_str());
+
+                    messageService = new(std::nothrow) MessageServiceEmail(
+                            email_accounts[i].account_id, stream_name.str());
+                    if (!messageService) {
+                        LOGE("message service[%d] is NULL", i);
+                        unsigned int count_srvcs = msgServices.size();
+                        for (unsigned int j = 0; j < count_srvcs; ++j) {
+                            delete msgServices.at(j);
+                        }
+                        msgServices.clear();
+                        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                                "MessageService for email creation failed");
+                        break;
+                    }
+                    else {
+                        msgServices.push_back(messageService);
+                    }
+
+                    messageService = NULL;
+                    stream_name.str("");
+                }
+                callback->setMessageServices(msgServices);
+            }
+
+            if (email_accounts != NULL) {
+                err = email_free_account(&email_accounts, count);
+                if (EMAIL_ERROR_NONE != err) {
+                    LOGW("%s", MessagingUtil::getEmailErrorMessage(
+                                err, "email_free_account()").c_str());
+                }
+                email_accounts = NULL;
+            }
+            break;
+        default:
+            callback->clearServices();
+            callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                    "Invalid message service tag");
+            break;
+        }
+    }
+    catch (...) {
+        unsigned int count_srvcs = msgServices.size();
+        for (unsigned int j = 0; j < count_srvcs; ++j) {
+            delete msgServices.at(j);
+        }
+        msgServices.clear();
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Cannot retrieve message services");
+    }
+
+    if (!g_idle_add(getMsgServicesCompleteCB, static_cast<void*>(callback))) {
+        LOGE("g_idle addition failed");
+        callback->clearServices();
+        delete callback;
+        callback = NULL;
+    }
+
+    return NULL;
+}
+
+MessagingManager& MessagingManager::getInstance()
+{
+    LOGD("Entered");
+
+    static MessagingManager instance;
+    return instance;
+}
+
+void MessagingManager::getMessageServices(MessageServiceCallbackData* callback)
+{
+    LOGD("Entered");
+
+    pthread_t thread;
+    if (pthread_create(&thread, NULL, getMsgServicesThread, static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw Common::UnknownException("Thread creation failed");
+    }
+    if (pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+MessagingManager::MessagingManager():
+        SecurityAccessor()
+{
+    LOGD("Entered");
+
+    int ret = msg_open_msg_handle(&m_msg_handle);
+    if (ret != MSG_SUCCESS) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_open_msg_handle()").c_str());
+    }
+    else {
+        ShortMsgManager::getInstance().registerStatusCallback(m_msg_handle);
+    }
+}
+
+MessagingManager::~MessagingManager()
+{
+    LOGD("Entered");
+    int ret = msg_close_msg_handle(&m_msg_handle);
+    if (ret != MSG_SUCCESS) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_close_msg_handle()").c_str());
+    }
+}
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/MessagingManager.h b/src/Messaging/MessagingManager.h
new file mode 100755 (executable)
index 0000000..8af9399
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_MESSAGING_MANAGER_H__
+#define __TIZEN_MESSAGING_MANAGER_H__
+
+#include <CallbackUserData.h>
+#include <PlatformException.h>
+#include <Security.h>
+
+#include "MessagingUtil.h"
+#include "MessageService.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class MessageServiceCallbackData : public Common::CallbackUserData {
+public:
+    MessageServiceCallbackData(JSContextRef globalCtx);
+    ~MessageServiceCallbackData();
+
+    void setMessageType(MessageType msgType);
+    MessageType getMessageType() const;
+
+    void setMessageServices(const std::vector<MessageService*>& msgServices);
+    const std::vector<MessageService*>& getMessageServices() const;
+
+    void setError(const std::string& err_name,
+            const std::string& err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    void clearServices();
+
+private:
+    MessageType m_msg_type;
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+    std::vector<MessageService*> m_msg_services;
+};
+
+class MessagingManager : public Common::SecurityAccessor
+{
+public:
+    static MessagingManager& getInstance();
+
+    void getMessageServices(MessageServiceCallbackData *callback);
+
+private:
+    MessagingManager();
+    MessagingManager(const MessagingManager &);
+    void operator=(const MessagingManager &);
+    virtual ~MessagingManager();
+
+    msg_handle_t m_msg_handle;
+
+};
+
+} // Messaging
+} // DeviceAPI
+#endif // __TIZEN_MESSAGING_MANAGER_H__
diff --git a/src/Messaging/MessagingUtil.cpp b/src/Messaging/MessagingUtil.cpp
new file mode 100644 (file)
index 0000000..546e7c0
--- /dev/null
@@ -0,0 +1,715 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagingUtil.cpp
+ */
+
+#include <PlatformException.h>
+#include <string>
+#include "MessagingUtil.h"
+#include <Logger.h>
+#include <fstream>
+#include <streambuf>
+#include <msg.h>
+#include <db-util.h>
+#include <TapiUtility.h>
+
+using namespace std;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+namespace {
+const string TYPE_SMS = "messaging.sms";
+const string TYPE_MMS = "messaging.mms";
+const string TYPE_EMAIL = "messaging.email";
+const string SENT = "SENT";
+const string SENDING = "SENDING";
+const string FAILED = "FAILED";
+const string DRAFT = "DRAFT";
+
+const string FOLDER_TYPE_INBOX = "INBOX";
+const string FOLDER_TYPE_OUTBOX = "OUTBOX";
+const string FOLDER_TYPE_DRAFTS = "DRAFTS";
+const string FOLDER_TYPE_SENTBOX = "SENTBOX";
+}
+
+string MessagingUtil::messageFolderTypeToString(MessageFolderType type)
+{
+    switch(type) {
+        case MessageFolderType::MESSAGE_FOLDER_TYPE_INBOX:
+            return FOLDER_TYPE_INBOX;
+        case MessageFolderType::MESSAGE_FOLDER_TYPE_OUTBOX:
+            return FOLDER_TYPE_OUTBOX;
+        case MessageFolderType::MESSAGE_FOLDER_TYPE_DRAFTS:
+            return FOLDER_TYPE_DRAFTS;
+        case MessageFolderType::MESSAGE_FOLDER_TYPE_SENTBOX:
+            return FOLDER_TYPE_SENTBOX;
+        default:
+            return "";
+    }
+}
+
+MessageType MessagingUtil::stringToMessageType(string type)
+{
+    if (TYPE_SMS == type) {
+        return MessageType(SMS);
+    }
+    if (TYPE_MMS == type) {
+        return MessageType(MMS);
+    }
+    if (TYPE_EMAIL == type) {
+        return MessageType(EMAIL);
+    }
+    std::string exceptionMsg = "Not supported type: ";
+    exceptionMsg += type;
+    throw TypeMismatchException(exceptionMsg.c_str());
+}
+
+string MessagingUtil::messageTypeToString(MessageType type)
+{
+    if (type == MessageType(SMS)) {
+        return TYPE_SMS;
+    }
+    if (type == MessageType(MMS)) {
+        return TYPE_MMS;
+    }
+    if (type == MessageType(EMAIL)) {
+        return TYPE_EMAIL;
+    }
+    throw TypeMismatchException("Invalid MessageType");
+}
+
+MessageStatus MessagingUtil::stringToMessageStatus(std::string status)
+{
+    LOGD("Converting string %s to MessageStatus.", status.c_str());
+    if(status == SENT) {
+        return STATUS_SENT;
+    }
+    if(status == SENDING) {
+        return STATUS_SENDING;
+    }
+    if(status == FAILED) {
+        return STATUS_FAILED;
+    }
+    if(status == DRAFT) {
+        return STATUS_DRAFT;
+    }
+    LOGE("Invalid MessageStatus");
+    throw TypeMismatchException("Invalid MessageStatus");
+}
+
+std::string MessagingUtil::messageStatusToString(MessageStatus status) {
+    LOGD("Converting MessageStatus %d to string.", (int)status);
+    switch(status) {
+        case STATUS_SENT:
+            return SENT;
+        case STATUS_SENDING:
+            return SENDING;
+        case STATUS_FAILED:
+            return FAILED;
+        case STATUS_DRAFT:
+            return DRAFT;
+        default:
+        // According to Web API documentation: If the status of the current
+        // message does not correspond to any item from the list, an empty
+        // value is returned.
+            LOGD("Unsupported or undefined MessageStatus");
+            return "";
+    }
+}
+
+std::string MessagingUtil::ltrim(const std::string& input)
+{
+    std::string str = input;
+    std::string::iterator i;
+    for (i = str.begin(); i != str.end(); i++) {
+        if (!isspace(*i)) {
+            break;
+        }
+    }
+    if (i == str.end()) {
+        str.clear();
+    } else {
+        str.erase(str.begin(), i);
+    }
+    return str;
+}
+
+std::string MessagingUtil::extractSingleEmailAddress(const std::string& address)
+{
+    std::size_t found_begin = address.rfind('<');
+    std::size_t found_end = address.rfind('>');
+    // if both '<' and '>' bracket found and '<' is before '>'
+    // then extract email address from the inside
+    if(found_begin != std::string::npos &&
+            found_end != std::string::npos &&
+            found_begin < found_end) {
+        return address.substr(found_begin+1, found_end-found_begin-1);
+    }
+    else {
+        // return unmodified source string
+        return address;
+    }
+}
+
+std::vector<std::string> MessagingUtil::extractEmailAddresses(
+        const std::vector<std::string>& addresses)
+{
+    std::vector<std::string> extractedAddresses;
+    for(auto it = addresses.begin(); it != addresses.end(); ++it) {
+        extractedAddresses.push_back(MessagingUtil::extractSingleEmailAddress(*it));
+    }
+
+    return extractedAddresses;
+}
+
+std::string MessagingUtil::loadFileContentToString(const std::string& file_path)
+{
+    std::ifstream input_file;
+    input_file.open(file_path, std::ios::in);
+
+    if (input_file.is_open()) {
+        std::string outString;
+        input_file.seekg(0, std::ios::end);
+        outString.reserve(input_file.tellg());
+        input_file.seekg(0, std::ios::beg);
+
+        outString.assign((std::istreambuf_iterator<char>(input_file)),
+                std::istreambuf_iterator<char>());
+        input_file.close();
+        return outString;
+    } else {
+        std::stringstream ss_error_msg;
+        ss_error_msg << "Failed to open file: " << file_path;
+        throw Common::IOException(ss_error_msg.str().c_str());
+    }
+}
+
+std::string MessagingUtil::getEmailErrorMessage(const int errorCode, const std::string& hint) {
+    std::stringstream ss;
+    ss << "Failed " << hint << ": ";
+
+    switch (errorCode) {
+        case EMAIL_ERROR_INVALID_PARAM:
+            ss << "Invalid parameter was given. - Invalid input parameter";
+            break;
+        case EMAIL_ERROR_INVALID_SERVER:
+            ss << "Invalid server information was given. - Server unavailable";
+            break;
+        case EMAIL_ERROR_INVALID_ADDRESS:
+            ss << "Invalid address information was given. - Incorrect address";
+            break;
+        case EMAIL_ERROR_INVALID_MAILBOX:
+            ss << "Invalid mailbox information was given";
+            break;
+        case EMAIL_ERROR_INVALID_DATA:
+            ss << "Invalid data";
+            break;
+        case EMAIL_ERROR_NO_RECIPIENT:
+            ss << "No recipients information was found";
+            break;
+        case EMAIL_ERROR_INVALID_REFERENCE_MAIL:
+            ss << "Invalid reference mail was given";
+            break;
+        case EMAIL_ERROR_ACCOUNT_NOT_FOUND:
+            ss << "No matched account was found";
+            break;
+        case EMAIL_ERROR_MAILBOX_NOT_FOUND:
+            ss << "No matched mailbox was found";
+            break;
+        case EMAIL_ERROR_FILTER_NOT_FOUND:
+            ss << "No matched filter was found";
+            break;
+        case EMAIL_ERROR_FILE_NOT_FOUND:
+            ss << "No matched file was found";
+            break;
+        case EMAIL_ERROR_TASK_BINDER_NOT_FOUND:
+            ss << "No matched task binder was found";
+            break;
+        case EMAIL_ERROR_HANDLE_NOT_FOUND:
+            ss << "No matched handle was found";
+            break;
+        case EMAIL_ERROR_NO_MORE_DATA:
+            ss << "No more data available";
+            break;
+        case EMAIL_ERROR_OUT_OF_MEMORY:
+            ss << "There is not enough memory";
+            break;
+        case EMAIL_ERROR_MAIL_MEMORY_FULL:
+            ss << "There is no more storage";
+            break;
+        case EMAIL_ERROR_MAXIMUM_DEVICES_LIMIT_REACHED:
+            ss << "EAS - Maximum devices limit reached";
+            break;
+        case EMAIL_ERROR_DB_FAILURE:
+            ss << "Database operation failed";
+            break;
+        case EMAIL_ERROR_GCONF_FAILURE:
+            ss << "The error occurred on accessing Gconf";
+            break;
+        case EMAIL_ERROR_SOCKET_FAILURE:
+            ss << "Socket operation failed";
+            break;
+        case EMAIL_ERROR_CONNECTION_BROKEN:
+            ss << "Network connection was broken";
+            break;
+        case EMAIL_ERROR_NETWORK_NOT_AVAILABLE:
+            ss << "Network not available";
+            break;
+        case EMAIL_ERROR_FLIGHT_MODE_ENABLE:
+            ss << "Flight mode enable : network not available";
+            break;
+        case EMAIL_ERROR_STARTLS:
+            ss << "STARTLS";
+            break;
+        case EMAIL_ERROR_TLS_SSL_FAILURE:
+            ss << "The agent failed TLS/SSL";
+            break;
+        case EMAIL_ERROR_NO_RESPONSE:
+            ss << "There is no server response";
+            break;
+        case EMAIL_ERROR_AUTH_NOT_SUPPORTED:
+            ss << "The server does not support authentication";
+            break;
+        case EMAIL_ERROR_AUTH_REQUIRED:
+            ss << "SMTP Authentication needed";
+            break;
+        case EMAIL_ERROR_LOGIN_ALLOWED_EVERY_15_MINS:
+            ss << "Login allowed only every 15 minutes";
+            break;
+        case EMAIL_ERROR_XOAUTH_BAD_REQUEST:
+            ss << "Bad request";
+            break;
+        case EMAIL_ERROR_XOAUTH_INVALID_GRANT:
+            ss << "Invalid grant";
+            break;
+        case EMAIL_ERROR_NOT_IMPLEMENTED:
+            ss << "The function is not implemented yet";
+            break;
+        case EMAIL_ERROR_SERVER_NOT_SUPPORT_FUNCTION:
+            ss << "The function is not supported in server";
+            break;
+        case EMAIL_ERROR_NO_SIM_INSERTED:
+            ss << "The SIM card did not insert";
+            break;
+        case EMAIL_ERROR_EVENT_QUEUE_FULL:
+            ss << "Event queue is full";
+            break;
+        case EMAIL_ERROR_SESSION_NOT_FOUND:
+            ss << "No matched session was found";
+            break;
+        case EMAIL_ERROR_CANCELLED:
+            ss << "The job was canceled by user";
+            break;
+        case EMAIL_ERROR_IPC_CRASH:
+            ss << "The IPC connection is broken";
+            break;
+        case EMAIL_ERROR_IPC_SOCKET_FAILURE:
+            ss << "The IPC socket failed read and write";
+            break;
+        case EMAIL_ERROR_IPC_ALREADY_INITIALIZED:
+            ss << "The IPC already is initialized";
+            break;
+        case EMAIL_ERROR_COMMAND_NOT_SUPPORTED:
+            ss << "The server does not support this command";
+            break;
+        case EMAIL_ERROR_SCAN_NOT_SUPPORTED:
+            ss << "The server does not support 'scan mailbox'";
+            break;
+        case EMAIL_ERROR_SMTP_SEND_FAILURE:
+            ss << "SMTP send failed";
+            break;
+        case EMAIL_ERROR_POP3_DELE_FAILURE:
+            ss << "Failed to run the command 'Dele' on POP server";
+            break;
+        case EMAIL_ERROR_POP3_UIDL_FAILURE:
+            ss << "Failed to run the command 'Uidl' on POP server";
+            break;
+        case EMAIL_ERROR_POP3_LIST_FAILURE:
+            ss << "Failed to run the command 'List' on POP server";
+            break;
+        case EMAIL_ERROR_POP3_NOOP_FAILURE:
+            ss << "Failed to run the command 'NOOP' on POP server";
+            break;
+        case EMAIL_ERROR_IMAP4_APPEND_FAILURE:
+            ss << "Failed to run the command 'Append' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_STORE_FAILURE:
+            ss << "Failed to run the command 'Storage' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_EXPUNGE_FAILURE:
+            ss << "Failed to run the command 'Expunge' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_FETCH_UID_FAILURE:
+            ss << "Failed to run the command 'Fetch UID' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_FETCH_SIZE_FAILURE:
+            ss << "Failed to run the command 'Fetch SIZE' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_IDLE_FAILURE:
+            ss << "Failed to run the command 'Idle' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_CREATE_FAILURE:
+            ss << "Failed to run the command 'Create' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_DELETE_FAILURE:
+            ss << "Failed to run the command 'Delete' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_RENAME_FAILURE:
+            ss << "Failed to run the command 'Rename' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_COPY_FAILURE:
+            ss << "Failed to run the command 'Copy' on IMAP server";
+            break;
+        case EMAIL_ERROR_IMAP4_NOOP_FAILURE:
+            ss << "Failed to run the command 'Noop' on IMAP server";
+            break;
+        case EMAIL_ERROR_INVALID_ATTACHMENT_SAVE_NAME:
+            ss << "Invalid attachment save name";
+            break;
+        case EMAIL_ERROR_DOMAIN_LOOKUP_FAILED:
+            ss << "The domain name provided was not found";
+            break;
+        case EMAIL_ERROR_LOAD_CERTIFICATE_FAILURE:
+            ss << "Cannot load the certificate";
+            break;
+        case EMAIL_ERROR_DECRYPT_FAILED:
+            ss << "Cannot decipher the encrypt mail";
+            break;
+        case EMAIL_ERROR_ACCOUNT_IS_QUARANTINED:
+            ss << "Account is quarantined";
+            break;
+        case EMAIL_ERROR_ACCOUNT_SYNC_IS_DISALBED:
+            ss << "Account sync is disabled";
+            break;
+        case EMAIL_ERROR_MAIL_NOT_FOUND_ON_SERVER:
+            ss << "The expected mail is not found in server";
+            break;
+        case EMAIL_ERROR_MAIL_IS_ALREADY_DOWNLOADED:
+            ss << "The mail is already downloaded";
+            break;
+        case EMAIL_ERROR_ATTACHMENT_SIZE_EXCEED_POLICY_LIMIT:
+            ss << "The attachment size is exceeded the policy value";
+            break;
+        case EMAIL_ERROR_MDM_SERVICE_FAILURE:
+            ss << "The MDM service did not work";
+            break;
+        case EMAIL_ERROR_NOTI:
+            ss << "The Notification API returned the error";
+            break;
+        case EMAIL_ERROR_ALREADY_INITIALIZED:
+            ss << "The thread is already intialized";
+            break;
+        case EMAIL_ERROR_UNKNOWN:
+            ss << "Unknown error";
+            break;
+        case EMAIL_ERROR_LOAD_ENGINE_FAILURE:
+            ss << "Loading engine failed";
+            break;
+        case EMAIL_ERROR_NULL_VALUE:
+            ss << "The value is null";
+            break;
+        case EMAIL_ERROR_SYSTEM_FAILURE:
+            ss << "There is a system error";
+            break;
+        case EMAIL_ERROR_ALREADY_EXISTS:
+            ss << "Data duplicated";
+            break;
+        case EMAIL_ERROR_NO_SMACK_RULE:
+            ss << "No smack rule exist for file access";
+            break;
+        case EMAIL_ERROR_INVALID_USER:
+            ss << "Invalid user ID was given. - Invalid user or password";
+            break;
+        case EMAIL_ERROR_INVALID_PATH:
+            ss << "Invalid flle path was given";
+            break;
+        case EMAIL_ERROR_DATA_TOO_SMALL:
+            ss << "Data is too small";
+            break;
+        case EMAIL_ERROR_NO_MMC_INSERTED:
+            ss << "The MMC card did not exist";
+            break;
+        case EMAIL_ERROR_VALIDATE_ACCOUNT_OF_SMTP:
+            ss << "Account validation of SMTP failed";
+            break;
+        case EMAIL_ERROR_DISCONNECTED:
+            ss << "Connection was disconnected";
+            break;
+        case EMAIL_ERROR_RETRIEVE_HEADER_DATA_FAILURE:
+            ss << "Retrieving header failed";
+            break;
+        case EMAIL_ERROR_XML_PARSER_FAILURE:
+            ss << "XML parsing failed";
+            break;
+        case EMAIL_ERROR_FLIGHT_MODE:
+            ss << "The network is flight mode";
+            break;
+        default:
+            ss << "Unknown Error";
+            break;
+    }
+
+    ss << ", " << errorCode;
+    return ss.str();
+}
+
+std::string MessagingUtil::getMsgErrorMessage(const int errorCode, const std::string& hint)
+{
+    std::stringstream ss;
+    ss << "Failed " << hint << ": ";
+
+    switch (errorCode) {
+        case MSG_ERR_NULL_MSGHANDLE:
+            ss << "Message handle is NULL";
+            break;
+        case MSG_ERR_NULL_MESSAGE:
+            ss << "Message is NULL";
+            break;
+        case MSG_ERR_INVALID_MSG_TYPE:
+            ss << "Message type is invalid";
+            break;
+        case MSG_ERR_INVALID_STORAGE_REG:
+            ss << "Storage registry is invalid";
+            break;
+        case MSG_ERR_INVALID_MSGHANDLE:
+            ss << "Message handle is invalid";
+            break;
+        case MSG_ERR_INVALID_MESSAGE:
+            ss << "Message is invalid";
+            break;
+        case MSG_ERR_INVALID_PLUGIN_HANDLE:
+            ss << "Plugin handle is invalid";
+            break;
+        case MSG_ERR_COMMUNICATION_ERROR:
+            ss << "Communication between client and server is error";
+            break;
+        case MSG_ERR_TRANSPORT_ERROR:
+            ss << "Transport event error";
+            break;
+        case MSG_ERR_CALLBACK_ERROR:
+            ss << "Callback event error";
+            break;
+        case MSG_ERR_FILTER_ERROR:
+            ss << "Filter event error";
+            break;
+        case MSG_ERR_MMPLAYER_CREATE:
+            ss << "Multimedia Error";
+            break;
+        case MSG_ERR_MMPLAYER_SET_ATTRS:
+            ss << "Multimedia Error";
+            break;
+        case MSG_ERR_MMPLAYER_PLAY:
+            ss << "Multimedia Error";
+            break;
+        case MSG_ERR_MMPLAYER_DESTROY:
+            ss << "Multimedia Error";
+            break;
+        case MSG_ERR_UNKNOWN:
+            ss << "Unknown errors";
+            break;
+        case MSG_ERR_DB_CONNECT:
+            ss << "DB connect error";
+            break;
+        case MSG_ERR_DB_EXEC:
+            ss << "DB command execute error";
+            break;
+        case MSG_ERR_DB_PREPARE:
+            ss << "DB prepare query error";
+            break;
+        case MSG_ERR_DB_NORECORD:
+            ss << "DB no-record error";
+            break;
+        case MSG_ERR_DB_MAKE_DIR:
+            ss << "mkdir error";
+            break;
+        case MSG_ERR_DB_ROW:
+            ss << "DB step() has another row ready";
+            break;
+        case MSG_ERR_DB_GENERIC:
+            ss << "Generic DB error";
+            break;
+        case MSG_ERR_SET_SETTING:
+            ss << "Error setting config data";
+            break;
+        case MSG_ERR_SET_READ_ERROR:
+            ss << "Error reading config settings";
+            break;
+        case MSG_ERR_SET_DELETE_ERROR:
+            ss << "Error in deleting config settings";
+            break;
+        case MSG_ERR_PLUGIN_TAPIINIT:
+            ss << "Telephony init error";
+            break;
+        case MSG_ERR_PLUGIN_TRANSPORT:
+            ss << "Transport (send/receive) error";
+            break;
+        case MSG_ERR_PLUGIN_SETTING:
+            ss << "Error setting config data";
+            break;
+        case MSG_ERR_PLUGIN_WAPDECODE:
+            ss << "WAP decode error";
+            break;
+        case MSG_ERR_PLUGIN_SIM_MSG_FULL:
+            ss << "SIM message full error";
+            break;
+        case MSG_ERR_MESSAGE_COUNT_FULL:
+            ss << "Message count full";
+            break;
+        case MSG_ERR_READREPORT_ALEADY_SENT:
+            ss << "Read report already sent";
+            break;
+        case MSG_ERR_FILTER_DUPLICATED:
+            ss << "Filter duplicate error";
+            break;
+        case MSG_ERR_NO_SIM:
+            ss << "No SIM";
+            break;
+        case MSG_ERR_SERVER_NOT_READY:
+            ss << "Message server not ready";
+            break;
+        case MSG_ERR_STORE_RESTRICT:
+            ss << "Storage restricted error";
+            break;
+        default:
+            ss << "Unknown Error";
+            break;
+    }
+
+    ss << ", " << errorCode;
+    return ss.str();
+}
+
+std::string MessagingUtil::getDbUtilErrorMessage(const int errorCode, const std::string& hint)
+{
+    std::stringstream ss;
+    ss << "Failed " << hint << ": ";
+
+    ss << (errorCode == DB_UTIL_ERROR ? "SQLite Error" : "Unknown Error");
+
+    ss << ", " << errorCode;
+    return ss.str();
+}
+
+std::string MessagingUtil::getTApiErrorMessage(const int errorCode, const std::string& hint)
+{
+
+    std::stringstream ss;
+    ss << "Failed " << hint << ": ";
+
+    switch (errorCode) {
+        case TAPI_API_INVALID_PTR:
+            ss << "Invalid pointer";
+            break;
+        case TAPI_API_DEPRICATED:
+            ss << "This API is deprecated and will be so in the future also";
+            break;
+        case TAPI_API_SYSTEM_RPC_LINK_DOWN:
+            ss << "RPC link down";
+            break;
+        case TAPI_API_SERVER_FAILURE:
+            ss << "Error occurred in the Telephony server";
+            break;
+        case TAPI_API_TRANSPORT_LAYER_FAILURE:
+            ss << "Transport layer Failure";
+            break;
+        case TAPI_API_REQUEST_MAX_IN_PROGRESS:
+            ss << "Maximum number of API Requests for the same service are already in progress";
+            break;
+        case TAPI_API_OPERATION_FAILED:
+            ss << "API operation failed";
+            break;
+        case TAPI_API_ACCESS_DENIED:
+            ss << "Access Denied";
+            break;
+        case TAPI_API_SYSTEM_RPC_LINK_NOT_EST:
+            ss << "RPC link down";
+            break;
+        case TAPI_API_SERVER_LAYER_FAILURE:
+            ss << "Server layer failure";
+            break;
+        case TAPI_API_INVALID_CALL_ID:
+            ss << "Invalid call ID";
+            break;
+        case TAPI_API_COULD_NOT_GET_CALL_CTXT:
+            ss << "Could not get the call context";
+            break;
+        case TAPI_API_COULD_NOT_DESTROY_CTXT:
+            ss << "Could not destroy the context";
+            break;
+        case TAPI_API_INVALID_CALL_HANDLE:
+            ss << "Invalid call handle";
+            break;
+        case TAPI_API_CALL_PRE_COND_FAILED:
+            ss << "Pre condition like MO call cannot be established now";
+            break;
+        case TAPI_API_MODEM_POWERED_OFF:
+            ss << "Modem is powered off";
+            break;
+        case TAPI_API_MODEM_ALREADY_OFF:
+            ss << "Modem is already off";
+            break;
+        case TAPI_API_NETTEXT_DEVICE_NOT_READY:
+            ss << "Nettext device is not ready";
+            break;
+        case TAPI_API_NETTEXT_INVALID_DATA_LEN:
+            ss << "Nettext Invalid data length";
+            break;
+        case TAPI_API_SIM_CARD_ERROR:
+            ss << "SIM general error";
+            break;
+        case TAPI_API_SIM_NOT_INITIALIZED:
+            ss << "SIM has not initialized yet (waiting for PIN verification)";
+            break;
+        case TAPI_API_SIM_PERM_BLOCKED:
+            ss << "SIM Permanently blocked state (no more allowing PUK input)";
+            break;
+        case TAPI_API_SAT_INVALID_COMMAND_ID:
+            ss << "Command Number Invalid      ";
+            break;
+        case TAPI_API_SAT_EVENT_NOT_REQUIRED_BY_USIM:
+            ss << "Event Not Requested by the USIM";
+            break;
+        case TAPI_API_NETWORK_INVALID_CTXT:
+            ss << "Network invalid contex t";
+            break;
+        case TAPI_API_NETWORK_ROAMING_NOT_ALLOWED:
+            ss << "Roaming not allowed";
+            break;
+        case TAPI_API_MISC_RETURN_NULL:
+            ss << "MISC return NULL";
+            break;
+        case TAPI_API_MISC_INPUTPARM_ERROR:
+            ss << "MISC input parameter error";
+            break;
+        case TAPI_API_MISC_OUTPARAM_NULL:
+            ss << "MISC input parameter error";
+            break;
+        default:
+            ss << "Unknown Error";
+            break;
+    }
+
+    ss << ", " << errorCode;
+    return ss.str();
+}
+
+}
+}
diff --git a/src/Messaging/MessagingUtil.h b/src/Messaging/MessagingUtil.h
new file mode 100644 (file)
index 0000000..08d5ced
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        MessagingUtil.h
+ */
+
+#ifndef __TIZEN_MESSAGING_UTIL_H__
+#define __TIZEN_MESSAGING_UTIL_H__
+#include <string>
+#include <Logger.h>
+#include <PlatformException.h>
+#include "MessageFolder.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+enum MessageType {
+    UNDEFINED = 0,
+    SMS,
+    MMS,
+    EMAIL
+};
+
+enum MessageStatus {
+    STATUS_UNDEFINED = 0,
+    STATUS_DRAFT,
+    STATUS_SENDING,
+    STATUS_SENT,
+    STATUS_LOADED,
+    STATUS_FAILED
+};
+
+class MessagingUtil {
+public:
+    static std::string messageFolderTypeToString(MessageFolderType);
+
+    static MessageType stringToMessageType(std::string);
+    static std::string messageTypeToString(MessageType);
+
+    static MessageStatus stringToMessageStatus(std::string status);
+    static std::string messageStatusToString(MessageStatus status);
+
+    static std::string ltrim(const std::string& input);
+    static std::string extractSingleEmailAddress(const std::string& address);
+    static std::vector<std::string> extractEmailAddresses(
+            const std::vector<std::string>& addresses);
+
+    /**
+    * Throws Common::IOException when file cannot be opened.
+    *
+    * To increase performance invoke this function this way:
+    * std::string result = loadFileContentToString(...);
+    * Reason: no copy constructor will be invoked on return.
+    */
+    static std::string loadFileContentToString(const std::string& file_path);
+
+    /**
+     * Function converts vector of shared_pointers into JSArray
+     */
+    template<class T, class U>
+    static JSObjectRef vectorToJSObjectArray(JSContextRef context,
+            const std::vector<T> & vec)
+    {
+        size_t count = vec.size();
+
+        JSObjectRef array[count];
+        for (size_t i = 0; i < count; ++i) {
+            array[i] = U::makeJSObject(context, vec[i]);
+        }
+        JSObjectRef result = JSObjectMakeArray(context, count,
+                count > 0 ? array : NULL, NULL);
+        if (!result) {
+            LOGW("Failed to create array");
+            throw Common::UnknownException("Failed to create array");
+        }
+        return result;
+    }
+
+    static std::string getEmailErrorMessage(const int errorCode, const std::string& hint);
+    static std::string getMsgErrorMessage(const int errorCode, const std::string& hint);
+    static std::string getDbUtilErrorMessage(const int errorCode, const std::string& hint);
+    static std::string getTApiErrorMessage(const int errorCode, const std::string& hint);
+
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwEmailException(const int errorCode, const std::string& hint) {
+        std::string message = MessagingUtil::getEmailErrorMessage(errorCode, hint);
+
+        LOGE("%s", message.c_str());
+        throw T(message.c_str());
+    }
+
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwMsgException(const int errorCode, const std::string& hint) {
+        std::string message = MessagingUtil::getMsgErrorMessage(errorCode, hint);
+
+        LOGE("%s", message.c_str());
+        throw T(message.c_str());
+    }
+};
+
+}
+}
+#endif // __TIZEN_MESSAGING_UTIL_H__
diff --git a/src/Messaging/ShortMsgManager.cpp b/src/Messaging/ShortMsgManager.cpp
new file mode 100644 (file)
index 0000000..77178ec
--- /dev/null
@@ -0,0 +1,1338 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <JSWebAPIError.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <msg.h>
+#include <msg_transport.h>
+#include <msg_storage.h>
+#include <unordered_set>
+#include <GlobalContextManager.h>
+
+#include "ShortMsgManager.h"
+#include "MessagingUtil.h"
+#include "MessageService.h"
+#include "MessageSMS.h"
+#include "MessageMMS.h"
+#include "JSMessage.h"
+#include "JSMessageConversation.h"
+#include "ChangeListenerContainer.h"
+#include "MessagingDatabaseManager.h"
+#include "Message.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+ShortMsgManager& ShortMsgManager::getInstance()
+{
+    LOGD("Entered");
+
+    static ShortMsgManager instance;
+    return instance;
+}
+
+static gboolean sendMessageCompleteCB(void* data)
+{
+    LOGD("Entered callback:%p", data);
+
+    MessageRecipientsCallbackData* callback =
+            static_cast<MessageRecipientsCallbackData*>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+
+            LOGD("Calling error callback with error:%s msg:%s",
+                    callback->getErrorName().c_str(),
+                    callback->getErrorMessage().c_str());
+
+            callback->callErrorCallback(errobj);
+            callback->getMessage()->setMessageStatus(MessageStatus::STATUS_FAILED);
+        }
+        else {
+            std::shared_ptr<Message> message = callback->getMessage();
+
+            LOGD("Calling success callback with: %d recipients", message->getTO().size());
+            callback->callSuccessCallback(
+                    JSUtil::toJSValueRef(context, message->getTO()));
+            callback->getMessage()->setMessageStatus(MessageStatus::STATUS_SENT);
+        }
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("Error while calling sendMessage callback: %s (%s)",
+                (err.getName()).c_str(),(err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error when calling sendMessage callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+static gboolean addDraftMessageCompleteCB(void *data)
+{
+    LOGD("Enter");
+    auto callback = static_cast<MessageCallbackUserData *>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return FALSE;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return FALSE;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+            callback->getMessage()->setMessageStatus(MessageStatus::STATUS_FAILED);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling addDraftMessage callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error when calling addDraftMessage callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return FALSE;
+}
+
+
+void ShortMsgManager::addDraftMessagePlatform(std::shared_ptr<Message> message)
+{
+    LOGD("Add new message(%p)", message.get());
+
+    // Save platform msg to get ID
+    msg_struct_t platform_msg
+            = Message::convertPlatformShortMessageToStruct(message.get(), m_msg_handle);
+    if (NULL == platform_msg) {
+        LOGE("Failed to prepare platform message");
+        throw UnknownException("Cannot prepare platform message");
+    }
+
+    msg_struct_t send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+    if (NULL == send_opt) {
+        LOGW("Failed msg_create_struct(): Invalid Values");
+    }
+    int err =  msg_set_bool_value(send_opt, MSG_SEND_OPT_SETTING_BOOL, false);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_set_bool_value()").c_str());
+    }
+    const int msg_id = msg_add_message(m_msg_handle, platform_msg, send_opt);
+    if (msg_id < MSG_SUCCESS) {
+        int ret = msg_release_struct(&send_opt);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        ret = msg_release_struct(&platform_msg);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+        }
+        LOGE("ret: %d", msg_id);
+        MessagingUtil::throwMsgException(msg_id, "msg_add_message()");
+    }
+
+    LOGD("Message(%p): New message ID: %d", message.get(), msg_id);
+    err = msg_set_int_value(platform_msg, MSG_MESSAGE_ID_INT, msg_id);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_set_int_value()").c_str());
+    }
+    message->setId(msg_id);
+    message->setMessageStatus(MessageStatus::STATUS_DRAFT);
+
+    msg_struct_t msg_conv = msg_create_struct(MSG_STRUCT_CONV_INFO);
+    if (NULL == msg_conv) {
+        LOGW("Failed msg_create_struct(): Invalid Values");
+    }
+    err = msg_get_conversation(m_msg_handle, msg_id, msg_conv);
+    if (MSG_SUCCESS == err) {
+        int conversationId = 0;
+        err = msg_get_int_value(msg_conv, MSG_CONV_MSG_THREAD_ID_INT, &conversationId);
+        if (MSG_SUCCESS != err) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_get_int_value()").c_str());
+        }
+        message->setConversationId(conversationId);
+    } else {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_get_conversation()").c_str());
+    }
+
+    Message* msgInfo = Message::convertPlatformShortMessageToObject(
+            platform_msg);
+
+    const int folderId = msgInfo->getFolderId();
+    message->setFolderId(folderId);
+
+    const time_t timestamp = msgInfo->getTimestamp();
+    message->setTimeStamp(timestamp);
+
+    const std::string from = msgInfo->getFrom();
+    LOGD("From: %s", from.c_str());
+    message->setFrom(from);
+
+    const bool isRead = msgInfo->getIsRead();
+    message->setIsRead(isRead);
+
+    const int inResponseTo = msgInfo->getInResponseTo();
+    message->setInResponseTo(inResponseTo);
+
+    err = msg_release_struct(&platform_msg);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+    }
+
+    err = msg_release_struct(&msg_conv);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+    }
+
+    err = msg_release_struct(&send_opt);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+    }
+    delete msgInfo;
+}
+
+void ShortMsgManager::sendMessage(MessageRecipientsCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    int msg_id;
+    Message* msgInfo = NULL;
+    msg_struct_t platform_msg = NULL;
+    msg_struct_t send_opt = NULL;
+    msg_struct_t msg_conv = NULL;
+    msg_struct_t req = NULL;
+
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+
+        std::shared_ptr<Message> message = callback->getMessage();
+        MessageStatus msg_status = message->getMessageStatus();
+        int ret = MSG_ERR_UNKNOWN;
+
+        // if it is draft message just send it
+        // in other case create new platform message
+        // add it to draft and finally send it
+        if (!( message->is_id_set() && MessageStatus::STATUS_DRAFT == msg_status)) {
+            LOGD("Add message to draft");
+            addDraftMessagePlatform(message);
+        }
+
+        msg_id = message->getId();
+        LOGD("Message ID: %d", msg_id);
+
+        platform_msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+        if (NULL == platform_msg) {
+            LOGW("Failed msg_create_struct(): Invalid Values");
+        }
+        send_opt = msg_create_struct(MSG_STRUCT_SENDOPT);
+        if (NULL == send_opt) {
+            LOGW("Failed msg_create_struct(): Invalid Values");
+        }
+        msg_conv = msg_create_struct(MSG_STRUCT_CONV_INFO);
+        if (NULL == msg_conv) {
+            LOGW("Failed msg_create_struct(): Invalid Values");
+        }
+        ret = msg_get_message(m_msg_handle, msg_id, platform_msg, send_opt);
+        if (MSG_SUCCESS != ret) {
+            LOGE("ret: %d", ret);
+            MessagingUtil::throwMsgException<UnknownException>(ret, "msg_get_message()");
+        }
+
+        // Send message
+        message->setMessageStatus(MessageStatus::STATUS_SENDING);
+        req = msg_create_struct(MSG_STRUCT_REQUEST_INFO);
+        if (NULL == req) {
+            LOGW("Failed msg_create_struct(): Invalid Values");
+        }
+        ret = msg_set_struct_handle(req, MSG_REQUEST_MESSAGE_HND, platform_msg);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_set_struct_handle()").c_str());
+        }
+
+        int req_id = -1;
+        ret = msg_get_int_value(req, MSG_REQUEST_REQUESTID_INT, &req_id);
+        if (MSG_SUCCESS != ret) {
+            LOGE("ret: %d", ret);
+            MessagingUtil::throwMsgException<UnknownException>(ret, "msg_get_int_value()");
+        }
+
+        std::string fname;
+        if (MessageType::MMS == message->getType()) {
+            LOGD("Send MMS message");
+            ret = msg_mms_send_message(m_msg_handle, req);
+            fname = "msg_mms_send_message()";
+        }
+        else if (MessageType::SMS == message->getType()) {
+            LOGD("Send SMS message");
+            ret = msg_sms_send_message(m_msg_handle, req);
+            fname = "msg_sms_send_message()";
+        }
+        else {
+            LOGE("Invalid message type: %d", message->getType());
+            throw TypeMismatchException("Invalid message type");
+        }
+
+        if (ret != MSG_SUCCESS) {
+            LOGE("ret: %d", ret);
+            MessagingUtil::throwMsgException<UnknownException>(ret, fname);
+        }
+
+        ret = msg_get_int_value(req, MSG_REQUEST_REQUESTID_INT, &req_id);
+        if (ret != MSG_SUCCESS) {
+            LOGE("ret: %d", ret);
+            MessagingUtil::throwMsgException<UnknownException>(ret, "msg_get_int_value()");
+        }
+        LOGD("req_id: %d", req_id);
+
+        msgInfo = Message::convertPlatformShortMessageToObject(platform_msg);
+
+        int conversationId;
+        ret = msg_get_conversation(m_msg_handle, msg_id, msg_conv);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_conversation()").c_str());
+        }
+        ret = msg_get_int_value(msg_conv, MSG_CONV_MSG_THREAD_ID_INT,
+                &conversationId);
+        if (MSG_SUCCESS != ret) {
+            LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_get_int_value()").c_str());
+        }
+        message->setConversationId(conversationId);
+
+        int folderId = msgInfo->getFolderId();
+        message->setFolderId(folderId);
+
+        time_t timestamp = msgInfo->getTimestamp();
+        message->setTimeStamp(timestamp);
+
+        std::string from = msgInfo->getFrom();
+        LOGD("From:%s", from.c_str());
+        message->setFrom(from);
+
+        bool isRead = msgInfo->getIsRead();
+        message->setIsRead(isRead);
+
+        int inResponseTo = msgInfo->getInResponseTo();
+        message->setInResponseTo(inResponseTo);
+
+        m_sendRequests[req_id] = callback;
+        LOGD("Send MSG_SUCCESS");
+    }
+    catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+        if (!g_idle_add(sendMessageCompleteCB, static_cast<void*>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    }
+    catch (...) {
+        LOGE("Message send failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Message send failed");
+        if (!g_idle_add(sendMessageCompleteCB, static_cast<void*>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    }
+
+    int err = msg_release_struct(&req);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+    }
+    err = msg_release_struct(&platform_msg);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+    }
+    err = msg_release_struct(&send_opt);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+    }
+    err = msg_release_struct(&msg_conv);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+    }
+    delete msgInfo;
+
+    return;
+}
+
+void ShortMsgManager::sendStatusCallback(msg_struct_t sent_status)
+{
+    int reqId = 0;
+    int status = MSG_NETWORK_NOT_SEND;
+
+    int err;
+    err = msg_get_int_value(sent_status, MSG_SENT_STATUS_REQUESTID_INT, &reqId);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_get_int_value()").c_str());
+    }
+    LOGD("Send msg %d", reqId);
+
+    err = msg_get_int_value(sent_status, MSG_SENT_STATUS_NETWORK_STATUS_INT, &status);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_get_int_value()").c_str());
+    }
+    LOGD("Send msg status: %d", status);
+
+    if(MSG_NETWORK_SEND_SUCCESS != status
+        && MSG_NETWORK_SEND_FAIL != status
+        && MSG_NETWORK_SEND_TIMEOUT != status)
+    {
+        LOGD("Not final status, return");
+        return;
+    }
+
+    std::lock_guard<std::mutex> lock(m_mutex);
+    SendReqMap::iterator it = m_sendRequests.find(reqId);
+    if (it != m_sendRequests.end()) {
+        LOGD("Matching request found");
+
+        MessageRecipientsCallbackData* callback = it->second;
+        m_sendRequests.erase(it);
+
+        if (MSG_NETWORK_SEND_FAIL == status
+                || MSG_NETWORK_SEND_TIMEOUT == status) {
+            LOGE("req_id:%d : Failed sending Message(%p) with msg_id:%d msg status is: %s",
+                reqId,
+                callback->getMessage().get(),
+                callback->getMessage()->getId(),
+                (MSG_NETWORK_SEND_FAIL == status ? "FAIL" : "TIMEOUT"));
+
+            callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                    "Send message failed");
+        }
+
+        if (!g_idle_add(sendMessageCompleteCB, static_cast<void*>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    }
+    else {
+        LOGE("No matching request found");
+    }
+
+    return;
+}
+
+static void sent_status_cb(msg_handle_t handle,
+        msg_struct_t sent_status,
+        void *data)
+{
+    LOGD("Entered");
+    ShortMsgManager::getInstance().sendStatusCallback(sent_status);
+
+    return;
+}
+
+void ShortMsgManager::callProperEventMessages(EventMessages* event,
+        msg_storage_change_type_t storageChangeType)
+{
+    LOGD("Entered event.items.size()=%d event.removed_conversations.size()=%d"
+            " sChangeType:%d", event->items.size(),
+            event->removed_conversations.size(), storageChangeType);
+
+    EventConversations* eventConv = new EventConversations();
+    eventConv->service_id = event->service_id;
+    eventConv->service_type = event->service_type;
+
+    if(MSG_STORAGE_CHANGE_DELETE == storageChangeType) {
+        eventConv->items = event->removed_conversations;
+    } else {
+        eventConv->items = ShortMsgManager::getConversationsForMessages(
+                event->items, storageChangeType);
+    }
+
+    switch (storageChangeType) {
+        case MSG_STORAGE_CHANGE_INSERT: {
+            ChangeListenerContainer::getInstance().callMessageAdded(event);
+            if (!eventConv->items.empty()) {
+
+                ConversationPtrVector added_conv;
+                ConversationPtrVector updated_conv;
+
+                for(ConversationPtrVector::iterator it = eventConv->items.begin();
+                        it != eventConv->items.end(); it++) {
+                    ConversationPtr cur_conv = *it;
+                    const bool new_conv = (cur_conv->getMessageCount() <= 1);
+                    if(new_conv) {
+                        added_conv.push_back(cur_conv);
+                    } else {
+                        updated_conv.push_back(cur_conv);
+                    }
+
+                    LOGD("%s conversation with id:%d last_msg_id:d",
+                            (new_conv ? "ADDED" : "UPDATED"),
+                            cur_conv->getConversationId(), cur_conv->getLastMessageId());
+                }
+
+                LOGD("num conversations:all=%d added=%d update=%d", eventConv->items.size(),
+                        added_conv.size(), updated_conv.size());
+
+                if(false == added_conv.empty()) {
+                    LOGD("%d new conversations, calling onConversationAdded",
+                            added_conv.size());
+                    eventConv->items = added_conv;
+                    ChangeListenerContainer::getInstance().callConversationAdded(
+                            eventConv);
+                }
+
+                if(false == updated_conv.empty()) {
+                    LOGD("%d updated conversation, calling onConversationUpdated",
+                            updated_conv.size());
+                    eventConv->items = updated_conv;
+                    ChangeListenerContainer::getInstance().callConversationUpdated(
+                            eventConv);
+                }
+
+            }
+        } break;
+        case MSG_STORAGE_CHANGE_DELETE: {
+            ChangeListenerContainer::getInstance().callMessageRemoved(event);
+
+            if(false == eventConv->items.empty()) {
+                LOGD("At least one conversation will be deleted, "
+                     "triggering also onConversationRemoved");
+                ChangeListenerContainer::getInstance().callConversationRemoved(eventConv);
+            }
+        } break;
+        case MSG_STORAGE_CHANGE_UPDATE: {
+            ChangeListenerContainer::getInstance().callMessageUpdated(event);
+            ChangeListenerContainer::getInstance().callConversationUpdated(eventConv);
+        } break;
+        default:
+            LOGW("Unknown storageChangeType: %d", storageChangeType);
+    }
+    delete event;
+    delete eventConv;
+}
+
+void ShortMsgManager::storage_change_cb(msg_handle_t handle,
+        msg_storage_change_type_t storageChangeType,
+        msg_id_list_s *pMsgIdList,
+        void* data)
+{
+    LOGD("Entered handle:%p sChangeType:%d numMsgs:%d", handle, storageChangeType,
+            pMsgIdList->nCount);
+
+    if (MSG_STORAGE_CHANGE_CONTACT == storageChangeType) {
+        LOGD("storageChangeType is MSG_STORAGE_CHANGE_CONTACT, ignoring");
+        return;
+    }
+
+    if (pMsgIdList->nCount < 1) {
+        LOGW("no messages in callback list");
+        return;
+    }
+
+    LOGD("Messages count %d", pMsgIdList->nCount);
+
+    /*
+     * There is possibility that in one callback from msg service will come
+     * SMS and MMS messages in the same list. ChangeListenerContainer requires
+     * that messages in event have common service_id and service_type. So we
+     * create here 2 events: one for SMS and one for MMS. If one of events
+     * has empty message list, we won't trigger it.
+     */
+    EventMessages* eventSMS = NULL;
+    EventMessages* eventMMS = NULL;
+    try {
+        // if allocation below fails than exception is thrown - no NULL check
+        eventSMS = new EventMessages();
+        eventSMS->service_type = MessageType::SMS;
+        eventSMS->service_id = SMS_ACCOUNT_ID;
+        eventMMS = new EventMessages();
+        eventMMS->service_type = MessageType::MMS;
+        eventMMS->service_id = MMS_ACCOUNT_ID;
+
+        if (MSG_STORAGE_CHANGE_DELETE == storageChangeType) {
+
+            ShortMsgManager& msg_manager = ShortMsgManager::getInstance();
+            std::lock_guard<std::mutex> lock(msg_manager.m_mutex);
+
+            std::map<int, MessagePtr>* rem_msgs[2] = {  // Recently removed messages
+                    &msg_manager.m_sms_removed_messages,
+                    &msg_manager.m_mms_removed_messages };
+            std::map<int, int>* rem_convs[2] = { // Recently removed conversations
+                    &msg_manager.m_sms_removed_msg_id_conv_id_map,
+                    &msg_manager.m_mms_removed_msg_id_conv_id_map };
+            EventMessages* dest_event[2] = { // SMS/MMS EventMessage to be propagated
+                    eventSMS,
+                    eventMMS };
+            std::map<int, ConversationPtr>* conv_map[2] = { //Map conversationId - object
+                    &msg_manager.m_sms_removed_conv_id_object_map,
+                    &msg_manager.m_mms_removed_conv_id_object_map };
+
+            for(int event_i = 0; event_i < 2; ++event_i) {
+
+                std::map<int, MessagePtr>& cur_rem_msgs = *(rem_msgs[event_i]);
+                std::map<int, int>& cur_rem_convs = *(rem_convs[event_i]);
+                EventMessages* cur_dest_event = dest_event[event_i];
+                std::map<int, ConversationPtr>& cur_conv_map = *(conv_map[event_i]);
+                std::unordered_set<int> conv_rem_now;
+
+                for (int i = 0; i < pMsgIdList->nCount; ++i) {
+                    const msg_message_id_t& msg_id = pMsgIdList->msgIdList[i];
+                    LOGD("pMsgIdList[%d] = %d", i, msg_id);
+
+                    std::map<int, MessagePtr> ::iterator it = cur_rem_msgs.find(msg_id);
+                    if(it != cur_rem_msgs.end()) {
+                        LOGD("[%d] is %s, Pushing message with id:%d subject:%s", i,
+                                (0 == i) ? "SMS" : "MMS",
+                                it->second->getId(),
+                                it->second->getSubject().c_str());
+                        cur_dest_event->items.push_back(it->second);
+                        cur_rem_msgs.erase(it);
+                    }
+
+                    std::map<int, int>::iterator cit = cur_rem_convs.find(msg_id);
+                    if(cit != cur_rem_convs.end()) {
+                        conv_rem_now.insert(cit->second);
+                        cur_rem_convs.erase(cit);
+                    }
+                }
+
+                for (auto it = conv_rem_now.begin(); it != conv_rem_now.end(); it++) {
+                    const int cur_rem_conv_id = *it;
+
+                    //---------------------------------------------------------------------
+                    // Check if we have removed last message from conversation
+                    //
+                    bool found = false;
+                    for(auto it2 = cur_rem_convs.begin();
+                            it2 != cur_rem_convs.end();
+                            it2++) {
+                        if( cur_rem_conv_id == it2->second) {
+                            found = true;
+                            break;
+                        }
+                    }
+
+                    if(false == found) {
+                        //We have removed last message from conversation
+
+                        std::map<int, ConversationPtr>::iterator conv_it =
+                            cur_conv_map.find(cur_rem_conv_id);
+                        if(conv_it != cur_conv_map.end()) {
+                            LOGD("Pushing removed %s MessageConversation(%p) with id:%d",
+                                    (0 == event_i) ? "SMS" : "MMS",
+                                    conv_it->second.get(), cur_rem_conv_id);
+
+                            cur_dest_event->removed_conversations.push_back(
+                                conv_it->second);
+                            cur_conv_map.erase(conv_it);
+                        } else {
+                            LOGW("Couldn't find ConversationPtr object with id:%d",
+                                    cur_rem_conv_id);
+                        }
+                    }
+                }
+            }
+
+        } else {
+            for (int i = 0; i < pMsgIdList->nCount; ++i) {
+
+                msg_struct_t msg = ShortMsgManager::getInstance().getMessage(
+                        pMsgIdList->msgIdList[i]);
+                if (NULL == msg) {
+                    LOGE("Failed to load short message");
+                    delete eventSMS;
+                    eventSMS = NULL;
+                    delete eventMMS;
+                    eventMMS = NULL;
+                    throw Common::UnknownException("Failed to load short message");
+                }
+                std::shared_ptr<Message> message(
+                        Message::convertPlatformShortMessageToObject(msg));
+                int err = msg_release_struct(&msg);
+                if (MSG_SUCCESS != err) {
+                    LOGW("%s", MessagingUtil::getMsgErrorMessage(
+                                err, "msg_release_struct()").c_str());
+                }
+                switch (message->getType()) {
+                    case MessageType::SMS:
+                        eventSMS->items.push_back(message);
+                        break;
+                    case MessageType::MMS:
+                        eventMMS->items.push_back(message);
+                        break;
+                    default:
+                        LOGE("Unsupported message type");
+                        delete eventSMS;
+                        eventSMS = NULL;
+                        delete eventMMS;
+                        eventMMS = NULL;
+                        throw Common::UnknownException("Unsupported message type");
+                }
+            }
+        }
+
+        if (!eventSMS->items.empty() || !eventSMS->removed_conversations.empty()) {
+            ShortMsgManager::callProperEventMessages(eventSMS, storageChangeType);
+        } else {
+            LOGD("No SMS messages, not triggering eventSMS");
+            delete eventSMS;
+            eventSMS = NULL;
+        }
+        if (!eventMMS->items.empty() || !eventMMS->removed_conversations.empty()) {
+            ShortMsgManager::callProperEventMessages(eventMMS, storageChangeType);
+        } else {
+            LOGD("No MMS messages, not triggering eventMMS");
+            delete eventMMS;
+            eventMMS = NULL;
+        }
+
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        delete eventSMS;
+        delete eventMMS;
+    } catch (...) {
+        LOGE("Failed to call callback");
+        delete eventSMS;
+        delete eventMMS;
+    }
+}
+
+void ShortMsgManager::registerStatusCallback(msg_handle_t msg_handle)
+{
+    m_msg_handle = msg_handle;
+    // set message sent status callback
+    int err = msg_reg_sent_status_callback(m_msg_handle,
+            &sent_status_cb, NULL);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(
+                    err, "msg_reg_sent_status_callback()").c_str());
+    }
+
+    err = msg_reg_storage_change_callback(m_msg_handle,
+            &storage_change_cb, NULL);
+    if (MSG_SUCCESS != err) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(
+                    err, "msg_reg_storage_change_callback()").c_str());
+    }
+}
+
+void ShortMsgManager::addDraftMessage(MessageCallbackUserData* callback)
+{
+    LOGD("Enter");
+
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::shared_ptr<Message> message = callback->getMessage();
+
+        addDraftMessagePlatform(message);
+
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Message add draft failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Message add draft failed");
+    }
+
+    // Complete task
+    if (!g_idle_add(addDraftMessageCompleteCB, static_cast<void *>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+void ShortMsgManager::removeMessages(MessagesCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    int error;
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<std::shared_ptr<Message>> messages = callback->getMessages();
+        MessageType type = callback->getMessageServiceType();
+        for(auto it = messages.begin() ; it != messages.end(); ++it) {
+            if((*it)->getType() != type) {
+                LOGE("Invalid message type: %d", (*it)->getType());
+                throw TypeMismatchException("Error while deleting message");
+            }
+        }
+        for (auto it = messages.begin() ; it != messages.end(); ++it) {
+
+            const int id = (*it)->getId();
+
+            //Store message object
+            LOGD("Storing removed message (id:%d) in m_removed_messages", id);
+            switch((*it)->getType()) {
+
+                case SMS:  m_sms_removed_messages[id] = (*it); break;
+                case MMS:  m_mms_removed_messages[id] = (*it); break;
+                default:
+                    LOGD("Unknown message type: %d", (*it)->getType());
+                    break;
+            }
+
+            error = msg_delete_message(m_msg_handle, id);
+            if (MSG_SUCCESS != error) {
+                LOGE("ret: %d", error);
+                MessagingUtil::throwMsgException<UnknownException>(error, "msg_delete_message()");
+            }
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Messages remove failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Messages remove failed");
+    }
+
+    //Complete task
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling removeShortMsg callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error when calling removeShortMsg callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+void ShortMsgManager::updateMessages(MessagesCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    LOGD("messages to update: %d", callback->getMessages().size());
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<std::shared_ptr<Message>> messages = callback->getMessages();
+        MessageType type = callback->getMessageServiceType();
+        for (auto it = messages.begin() ; it != messages.end(); ++it) {
+            if ((*it)->getType() != type) {
+                LOGE("Invalid message type");
+                throw TypeMismatchException("Error while updating message");
+            }
+        }
+        for (auto it = messages.begin() ; it != messages.end(); ++it) {
+
+            LOGD("updating Message(%p) msg_id:%d", (*it).get(), (*it)->getId());
+
+            msg_struct_t platform_msg
+                    = Message::convertPlatformShortMessageToStruct(it->get(), m_msg_handle);
+            if (NULL == platform_msg) {
+                LOGE("Failed to prepare platform message");
+                throw UnknownException("Cannot prepare platform message");
+            }
+            msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
+            if (NULL == sendOpt) {
+                LOGW("Failed msg_create_struct(): Invalid Values");
+            }
+            int error = msg_update_message(m_msg_handle, platform_msg, sendOpt);
+            int ret = msg_release_struct(&platform_msg);
+            if (MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+            }
+            ret = msg_release_struct(&sendOpt);
+            if (MSG_SUCCESS != ret) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(ret, "msg_release_struct()").c_str());
+            }
+            if (MSG_SUCCESS != error) {
+                LOGE("ret: %d", error);
+                MessagingUtil::throwMsgException<UnknownException>(error, "msg_update_message()");
+            }
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Messages update failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Messages update failed");
+    }
+
+    //Complete task
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling updateShortMsg callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error when calling updateShortMsg callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+msg_struct_t ShortMsgManager::getMessage(int msg_id)
+{
+    msg_struct_t sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
+    if (NULL == sendOpt) {
+        LOGW("Failed msg_create_struct(): Invalid Values");
+    }
+    msg_struct_t msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+    if (NULL == msg) {
+        LOGW("Failed msg_create_struct(): Invalid Values");
+    }
+    int error = msg_get_message(m_msg_handle, msg_id, msg, sendOpt);
+    if (MSG_SUCCESS != error) {
+        LOGE("ret: %d", error);
+        MessagingUtil::throwMsgException<UnknownException>(error, "msg_get_message()");
+    }
+    error = msg_release_struct(&sendOpt);
+    if (MSG_SUCCESS != error) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(error, "msg_release_struct()").c_str());
+    }
+    return msg;
+}
+
+ConversationPtrVector ShortMsgManager::getConversationsForMessages(
+        MessagePtrVector messages,
+        msg_storage_change_type_t storageChangeType)
+{
+    LOGD("Entered messages.size()=%d storageChangeType=%d", messages.size(),
+            storageChangeType);
+
+    std::unordered_set<int> unique_conv_ids;
+    ConversationPtrVector convs;
+    for (auto it = messages.begin(); it != messages.end(); ++it) {
+
+        MessagePtr msg = (*it);
+        const int conv_id = msg->getConversationId();
+        const int count = unique_conv_ids.count(conv_id);
+        LOGD("Message(%p) msg_id:%d conversationId: %d count:%d", msg.get(),
+                msg->getId(), conv_id, count);
+
+        if (0 == count) {
+            //conversation isn't loaded yet
+            unique_conv_ids.insert(conv_id);
+            ConversationPtr conv = MessageConversation::convertMsgConversationToObject(
+                    conv_id, ShortMsgManager::getInstance().m_msg_handle);
+
+            LOGD("Pushed conv=%p", conv.get());
+            convs.push_back(conv);
+        }
+    }
+    return convs;
+}
+
+void ShortMsgManager::findMessages(FindMsgCallbackUserData* callback)
+{
+    LOGD("Entered");
+
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<int> messagesIds =
+                MessagingDatabaseManager::getInstance().findShortMessages(callback);
+        int msgListCount = messagesIds.size();
+        LOGD("Found %d messages", msgListCount);
+
+        msg_struct_t msg;
+        msg_struct_t sendOpt;
+        msg_error_t err;
+        for (int i = 0; i < msgListCount; i++) {
+            msg = msg_create_struct(MSG_STRUCT_MESSAGE_INFO);
+            if (NULL == msg) {
+                LOGW("Failed msg_create_struct(): Invalid Values");
+            }
+            sendOpt = msg_create_struct(MSG_STRUCT_SENDOPT);
+            if (NULL == sendOpt) {
+                LOGW("Failed msg_create_struct(): Invalid Values");
+            }
+            err = msg_get_message(m_msg_handle, messagesIds.at(i), msg, sendOpt);
+
+            if (MSG_SUCCESS != err) {
+                LOGE("ret: %d", err);
+                MessagingUtil::throwMsgException(err, "msg_get_message()");
+            }
+
+            try {
+                std::shared_ptr<Message> message(
+                    Message::convertPlatformShortMessageToObject(msg));
+                callback->addMessage(message);
+
+                LOGD("Created message with id %d:", messagesIds[i]);
+            }
+            catch(const Common::InvalidValuesException& exception) {
+                //Ignore messages with not supported/unrecognized type
+            }
+
+            err = msg_release_struct(&sendOpt);
+            if (MSG_SUCCESS != err) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+            }
+            err = msg_release_struct(&msg);
+            if (MSG_SUCCESS != err) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(err, "msg_release_struct()").c_str());
+            }
+        }
+
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Message add draft failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Message add draft failed");
+    }
+
+    //Complete task
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback with %d messages:",
+                    callback->getMessages().size());
+            callback->callSuccessCallback(JSMessage::messageVectorToJSObjectArray(context,
+                    callback->getMessages()));
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling findMessages callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Failed to call findMessages callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+void ShortMsgManager::findConversations(ConversationCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if(!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        std::vector<int> conversationsIds =
+                MessagingDatabaseManager::getInstance().findShortMessageConversations(callback);
+        int convListCount = conversationsIds.size();
+        LOGD("Found %d conversations", convListCount);
+
+        for (int i = 0; i < convListCount; i++) {
+            std::shared_ptr<MessageConversation> conversation =
+                    MessageConversation::convertMsgConversationToObject(
+                            conversationsIds.at(i), m_msg_handle);
+
+            callback->addConversation(conversation);
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Message add draft failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Message add draft failed");
+    }
+
+    //Complete task
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback(MessagingUtil::vectorToJSObjectArray<
+                    ConversationPtr, JSMessageConversation>(context, callback->getConversations()));
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling findConversations callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Failed to call findConversations callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+void ShortMsgManager::removeConversations(ConversationCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if (!callback){
+        LOGE("Callback is null");
+        return;
+    }
+
+    int error = MSG_SUCCESS;
+    msg_handle_t handle = NULL;
+
+    try {
+        std::lock_guard<std::mutex> lock(m_mutex);
+        ConversationPtrVector conversations = callback->getConversations();
+        const MessageType type = callback->getMessageServiceType();
+
+        error = msg_open_msg_handle(&handle);
+        if (MSG_SUCCESS != error) {
+            LOGE("ret: %d", error);
+            MessagingUtil::throwMsgException<UnknownException>(error, "msg_open_msg_handle()");
+        }
+
+        for(auto it = conversations.begin() ; it != conversations.end(); ++it) {
+            if((*it)->getType() != type) {
+                LOGE("Invalid message type");
+                throw TypeMismatchException("Error while deleting message conversation");
+            }
+        }
+
+        std::map<int, int>* msg_id_conv_id_map = NULL;
+        std::map<int, ConversationPtr>* conv_id_object_map = NULL;
+        if(MessageType::SMS == type) {
+            msg_id_conv_id_map = &m_sms_removed_msg_id_conv_id_map;
+            conv_id_object_map = &m_sms_removed_conv_id_object_map;
+        } else if(MessageType::MMS == type) {
+            msg_id_conv_id_map = &m_mms_removed_msg_id_conv_id_map;
+            conv_id_object_map = &m_mms_removed_conv_id_object_map;
+        } else {
+            LOGE("Invalid message type:%d for ShortMsgManager!", type);
+            throw UnknownException("Invalid message type for ShortMsgManager!");
+        }
+
+        int conv_index = 0;
+        for (auto it = conversations.begin() ; it != conversations.end();
+                    ++it, ++conv_index) {
+
+            ConversationPtr conv = (*it);
+            msg_thread_id_t conv_id = conv->getConversationId();
+
+            LOGD("[%d] MessageConversation(%p) conv_id:%d", conv_index, conv.get(),
+                    conv_id);
+
+            msg_struct_list_s conv_view_list;
+            error = msg_get_conversation_view_list(handle, (msg_thread_id_t)conv_id,
+                    &conv_view_list);
+            if (MSG_SUCCESS == error) {
+                for(int msg_index = 0; msg_index < conv_view_list.nCount; ++msg_index)
+                {
+                    int cur_msg_id = 0;
+                    error = msg_get_int_value(conv_view_list.msg_struct_info[msg_index],
+                            MSG_CONV_MSG_ID_INT, &cur_msg_id);
+
+                    if(MSG_SUCCESS == error && cur_msg_id > 0) {
+                        (*msg_id_conv_id_map)[cur_msg_id] = conv_id;
+                        (*conv_id_object_map)[conv_id] = conv;
+
+                        LOGD("[%d] message[%d] msg_id:%d,"
+                                "saved MessageConversation(%p) with conv_id:%d",
+                                conv_index, msg_index, cur_msg_id, conv.get(), conv_id);
+                    } else {
+                        LOGW("%s", MessagingUtil::getMsgErrorMessage(
+                                    error, "msg_get_int_value()").c_str());
+                    }
+                }
+            } else {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(
+                         error, "msg_get_conversation_view_list()").c_str());
+            }
+
+            error = msg_release_list_struct(&conv_view_list);
+            if (MSG_SUCCESS != error) {
+                LOGW("%s", MessagingUtil::getMsgErrorMessage(
+                         error, "msg_release_list_struct()").c_str());
+            }
+
+            error = msg_delete_thread_message_list(handle, (msg_thread_id_t) conv_id,
+                    FALSE);
+            if (MSG_SUCCESS != error) {
+                LOGE("ret: %d", error);
+                MessagingUtil::throwMsgException<UnknownException>(
+                        error, "msg_delete_thread_message_list()");
+            }
+
+        }
+
+    } catch (const BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+        callback->setError(err.getName(), err.getMessage());
+    } catch (...) {
+        LOGE("Messages remove failed");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR, "Messages remove failed");
+    }
+
+    error = msg_close_msg_handle(&handle);
+    if (MSG_SUCCESS != error) {
+        LOGW("%s", MessagingUtil::getMsgErrorMessage(error, "msg_close_msg_handle()").c_str());
+    }
+
+    //Complete task
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(), callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const BasePlatformException& err) {
+        LOGE("Error while calling removeConversations callback: %s (%s)",
+                (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error when calling removeConversations callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+}
+
+ShortMsgManager::ShortMsgManager() : m_msg_handle(NULL)
+{
+    LOGD("Entered");
+}
+
+ShortMsgManager::~ShortMsgManager()
+{
+    LOGD("Entered");
+    LOGD("m_sms_removed_messages.size() = %d",
+            m_sms_removed_messages.size());
+    LOGD("m_mms_removed_messages.size() = %d",
+            m_mms_removed_messages.size());
+    LOGD("m_sms_removed_msg_id_conv_id_map.size() = %d",
+            m_sms_removed_msg_id_conv_id_map.size());
+    LOGD("m_sms_removed_conv_id_object_map.size() = %d",
+            m_sms_removed_conv_id_object_map.size());
+    LOGD("m_mms_removed_msg_id_conv_id_map.size() = %d",
+            m_mms_removed_msg_id_conv_id_map.size());
+    LOGD("m_mms_removed_conv_id_object_map.size() = %d",
+            m_mms_removed_conv_id_object_map.size());
+}
+
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/Messaging/ShortMsgManager.h b/src/Messaging/ShortMsgManager.h
new file mode 100755 (executable)
index 0000000..6f17f06
--- /dev/null
@@ -0,0 +1,134 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SEND_SHORT_MSG_MANAGER_H__
+#define __TIZEN_SEND_SHORT_MSG_MANAGER_H__
+
+#include <glib.h>
+#include <mutex>
+#include <map>
+
+#include <msg_storage_types.h>
+#include <CallbackUserData.h>
+#include <PlatformException.h>
+#include <msg_types.h>
+
+#include "ChangeListenerContainer.h"
+#include "MessagingUtil.h"
+#include "MessageService.h"
+#include "Message.h"
+#include "MessageConversation.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+class Message;
+class FindMsgCallbackUserData;
+
+class ShortMsgManager {
+public:
+    static ShortMsgManager& getInstance();
+
+    void sendMessage(MessageRecipientsCallbackData* callback);
+    void sendStatusCallback(msg_struct_t sent_status);
+
+    void addDraftMessage(MessageCallbackUserData* callback);
+    void findMessages(FindMsgCallbackUserData* callback);
+    void findConversations(ConversationCallbackData* callback);
+    void removeConversations(ConversationCallbackData* callback);
+
+    void registerStatusCallback(msg_handle_t msg_handle);
+
+    void removeMessages(MessagesCallbackUserData* callback);
+    void updateMessages(MessagesCallbackUserData* callback);
+    msg_struct_t getMessage(int msg_id);
+private:
+    ShortMsgManager();
+    ShortMsgManager(const ShortMsgManager &);
+    void operator=(const ShortMsgManager &);
+    virtual ~ShortMsgManager();
+
+    /**
+     * Listener for msg storage changes. Calls callbacks from ChangeListenerContainer.
+     * @param handle
+     * @param storageChangeType
+     * @param pMsgIdList
+     * @param data
+     */
+    static void storage_change_cb(msg_handle_t handle,
+        msg_storage_change_type_t storageChangeType,
+        msg_id_list_s *pMsgIdList,
+        void* data);
+
+    void addDraftMessagePlatform(std::shared_ptr<Message> message);
+    /**
+     * Returns unique list of conversations for given vector of messages.
+     * storageChangeType is needed to filter conversations returned:
+     * - for MSG_STORAGE_CHANGE_UPDATE all conversations are fetched
+     * - for MSG_STORAGE_CHANGE_INSERT only conversations with 1 message are returned
+     * - for MSG_STORAGE_CHANGE_DELETE  only conversations with 1 message are returned
+     * @param messages
+     * @param storageChangeType
+     * @return
+     */
+    static ConversationPtrVector getConversationsForMessages(
+            MessagePtrVector messages,
+            msg_storage_change_type_t storageChangeType);
+    static void callProperEventMessages(EventMessages* event,
+            msg_storage_change_type_t storageChangeType);
+    typedef std::map<msg_request_id_t, MessageRecipientsCallbackData*> SendReqMap;
+    SendReqMap m_sendRequests;
+    msg_handle_t m_msg_handle;
+
+    /**
+     * Map MessageId - Message object of recently removed SMS messages
+     */
+    std::map<int, MessagePtr> m_sms_removed_messages;
+
+    /**
+     * Map MessageId - Message object of recently removed MMS messages
+     */
+    std::map<int, MessagePtr> m_mms_removed_messages;
+
+
+
+    /**
+     * Map MessageId - ConversationId for SMS messages (only from removed conversation)
+     */
+    std::map<int, int> m_sms_removed_msg_id_conv_id_map;
+
+    /**
+     * Map ConversationId - ConversationPtr object (only removed) for SMS
+     */
+    std::map<int, ConversationPtr> m_sms_removed_conv_id_object_map;
+
+    /**
+     * Map MessageId - ConversationId for MMS messages (only from removed conversation)
+     */
+    std::map<int, int> m_mms_removed_msg_id_conv_id_map;
+
+    /**
+     * Map ConversationId - ConversationPtr object (only removed) for MMS
+     */
+    std::map<int, ConversationPtr> m_mms_removed_conv_id_object_map;
+
+    std::mutex m_mutex;
+};
+
+} // Messaging
+} // DeviceAPI
+#endif // __TIZEN_SEND_SHORT_MSG_MANAGER_H__
diff --git a/src/Messaging/TestScripts/addConversationsChangeListener_01.js b/src/Messaging/TestScripts/addConversationsChangeListener_01.js
new file mode 100644 (file)
index 0000000..285c8b7
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        addConversationsChangeListener_01.js
+ */
+
+//
+//
+//  Attribute      | Attribute filter| Attribute range filter
+//                 | supported       | supported
+// ----------------+-----------------+------------------------
+// id              | Yes             | No
+// type            | Yes             | No
+// timestamp       | No              | Yes
+// messageCount    | Yes             | No
+// unreadMessages  | Yes             | No
+// preview         | Yes             | No
+// subject         | No              | No
+// isRead          | No              | No
+// from            | Yes             | No
+// to              | Yes             | No
+// cc              | No              | No
+// bcc             | No              | No
+// lastMessageId   | No              | No
+
+
+var prefferedEmailService = "a.jacak.testmail";
+
+function containCaseInsensitive(string, searchString) {
+    var lcString = string.toLowerCase();
+    var lcSearchString = searchString.toLowerCase();
+    return lcString.indexOf(lcSearchString)>=0;
+}
+
+var currentService = null;
+
+function listConversations(prefix, conversations) {
+
+    for (var i=0; i<conversations.length; i++) {
+        var conversation = conversations[i];
+        console.log(prefix + " CONVERSATION[" + i + "] " +
+                " id: " + conversation.id +
+                " type: " + conversation.type +
+                " timestamp: " + conversation.timestamp +
+                " messageCount: " + conversation.messageCount +
+                " unreadMessages: " + conversation.unreadMessages +
+                " preview: " + conversation.preview +
+                " subject:" + conversation.subject +
+                " isRead: " + conversation.isRead +
+                " from: " + conversation.from +
+                " lastMessageId: " + conversation.lastMessageId);
+    }
+}
+
+var conversationChangeCB = {
+    conversationsupdated: function(conversations) {
+        console.log(conversations.length + " conversation(s) updated");
+        listConversations("conversationsupdated", conversations);
+    },
+    conversationsadded: function(conversations) {
+        console.log(conversations.length + " conversation(s) added");
+        listConversations("conversationsadded", conversations);
+    },
+    conversationsremoved: function(conversations) {
+        console.log(conversations.length + " conversation(s) removed");
+        listConversations("conversationsremoved", conversations);
+    }
+};
+
+function serviceSyncSuccessCB() {
+    console.log("Synced!");
+}
+
+function serviceSyncFailCB() {
+    console.log("Sync failed!");
+}
+
+function servicesListSuccessCB(services) {
+    console.log("servicesListSuccessCB: received:" + services.length + " services");
+
+    if(services.length > 0) {
+
+        var chosenServiceIndex = 0;
+        for(var i = 0; i < services.length; i++) {
+            if(containCaseInsensitive(services[i].name, prefferedEmailService)) {
+                chosenServiceIndex = i;
+                console.log("servicesListSuccessCB: " +
+                        "found service which name contains: " +
+                        prefferedEmailService);
+                break;
+            }
+        }
+        currentService = services[chosenServiceIndex];
+        console.log("servicesListSuccessCB: testing service:" + currentService.name);
+
+        var filter = new tizen.AttributeFilter("preview", "CONTAINS", "Home");
+        currentService.messageStorage.addConversationsChangeListener(
+                conversationChangeCB, filter);
+
+        currentService.sync(serviceSyncSuccessCB, serviceSyncFailCB, 30);
+    } else {
+        console.log("servicesListSuccessCB: ERROR: could not find any email service!");
+    }
+}
+
+tizen.messaging.getMessageServices("messaging.email", servicesListSuccessCB);
diff --git a/src/Messaging/TestScripts/addFoldersChangeListener_01.js b/src/Messaging/TestScripts/addFoldersChangeListener_01.js
new file mode 100644 (file)
index 0000000..f669a7e
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// Please send two emails with subject containing "Alaska"
+//  1. subject "Alaska Good" and body containing "hack"
+//  2. subject "Alaska Bad" and body NOT containing "hack"
+//
+// Only 1. should printed in JS console.
+
+/**
+ * @file        addFoldersChangeListener_01.js
+ */
+
+/**
+ *
+ *  Attribute      | Attribute filter| Attribute range filter
+ *                 | supported       | supported
+ * ----------------+-----------------+------------------------
+ *  id             | No              | No
+ *  parentId       | No              | No
+ *  serviceId      | Yes             | No
+ *  contentType    | No              | No
+ *  name           | No              | No
+ *  path           | No              | No
+ *  type           | No              | No
+ *  synchronizable | No              | No
+ */
+
+var prefferedEmailService = "a.jacak.testmail";
+
+function containCaseInsensitive(string, searchString) {
+    var lcString = string.toLowerCase();
+    var lcSearchString = searchString.toLowerCase();
+    return lcString.indexOf(lcSearchString)>=0;
+}
+
+var currentService = null;
+
+function listFolders(prefix, folders) {
+    for (var i=0; i<folders.length; i++) {
+        var folder = folders[i];
+        console.log(prefix + " FOLDER[" + i + "] id: "
+                + folder.id
+                + " name:" + folder.name
+                + " serviceid: " + folder.serviceId);
+    }
+}
+
+var folderChangeCB = {
+    foldersupdated: function(folders) {
+        console.log(folders.length + " folder(s) updated");
+        listFolders("foldersupdated",folders);
+    },
+    foldersadded: function(folders) {
+        console.log(folders.length + " folder(s) added");
+        listFolders("foldersadded",folders);
+    },
+    foldersremoved: function(folders) {
+        console.log(folders.length + " folder(s) removed");
+        listFolders("foldersremoved",folders);
+    }
+ };
+
+function serviceSyncSuccessCB() {
+    console.log("Synced!");
+}
+
+function serviceSyncFailCB() {
+    console.log("Sync failed!");
+}
+
+function servicesListSuccessCB(services) {
+    console.log("servicesListSuccessCB: received:" + services.length + " services");
+
+    if(services.length > 0) {
+        var chosenServiceIndex = 0;
+        for(var i = 0; i < services.length; i++) {
+            if(containCaseInsensitive(services[i].name, prefferedEmailService)) {
+                chosenServiceIndex = i;
+                console.log("servicesListSuccessCB: " +
+                        "found service which name contains: " +
+                        prefferedEmailService);
+                break;
+            }
+        }
+        currentService = services[chosenServiceIndex];
+        console.log("servicesListSuccessCB: testing service:" + currentService.name);
+
+        var filter = new tizen.AttributeFilter("serviceId", "EXACTLY", currentService.id);
+
+        currentService.messageStorage.addFoldersChangeListener(folderChangeCB, filter);
+        currentService.sync(serviceSyncSuccessCB, serviceSyncFailCB, 30);
+    } else {
+        console.log("servicesListSuccessCB: ERROR: could not find any email service!");
+    }
+}
+
+tizen.messaging.getMessageServices("messaging.email", servicesListSuccessCB);
\ No newline at end of file
diff --git a/src/Messaging/TestScripts/addMessagesChangeListener_01.js b/src/Messaging/TestScripts/addMessagesChangeListener_01.js
new file mode 100644 (file)
index 0000000..91455e9
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// Please send two emails with subject containing "Alaska"
+//  1. subject "Alaska Good" and body containing "hack"
+//  2. subject "Alaska Bad" and body NOT containing "hack"
+//
+// Only 1. should printed in JS console.
+
+/**
+ * @file        addMessagesChangeListener_01.js
+ */
+
+//https://developer.tizen.org/help/index.jsp?topic=%2Forg.tizen.gettingstarted%2Fhtml%2Ftizen_overview%2Fapplication_filtering.htm
+
+var prefferedEmailService = "a.jacak.testmail";
+
+function containCaseInsensitive(string, searchString) {
+    var lcString = string.toLowerCase();
+    var lcSearchString = searchString.toLowerCase();
+    return lcString.indexOf(lcSearchString)>=0;
+}
+
+var currentService = null;
+
+function listMessages(prefix, messages) {
+    for (var i=0; i<messages.length; i++) {
+        var message = messages[i];
+        console.log(prefix + " MSG[" + i + "] status: "
+                    + message.messageStatus
+                    + " subject:" + message.subject);
+    }
+}
+
+var messageChangeCB = {
+    messagesupdated: function(messages) {
+        console.log(messages.length + " message(s) updated");
+        listMessages("messagesupdated",messages);
+    },
+    messagesadded: function(messages) {
+       console.log("messagesadded: " + messages.length + " message(s) added");
+       listMessages("messagesadded",messages);
+
+    },
+    messagesremoved: function(messages) {
+        console.log(messages.length + " message(s) removed");
+        listMessages("messagesremoved",messages);
+    }
+};
+
+function serviceSyncSuccessCB() {
+    console.log("Synced!");
+}
+
+function serviceSyncFailCB() {
+    console.log("Sync failed!");
+}
+
+function servicesListSuccessCB(services) {
+    console.log("servicesListSuccessCB: received:" + services.length + " services");
+
+    if(services.length > 0) {
+
+        var chosenServiceIndex = 0;
+        for(var i = 0; i < services.length; i++) {
+            if(containCaseInsensitive(services[i].name, prefferedEmailService)) {
+                chosenServiceIndex = i;
+                console.log("servicesListSuccessCB: " +
+                        "found service which name contains: " +
+                        prefferedEmailService);
+                break;
+            }
+        }
+        currentService = services[chosenServiceIndex];
+        console.log("servicesListSuccessCB: testing service:" + currentService.name);
+
+        var subjectFilter1 = new tizen.AttributeFilter("subject", "CONTAINS", "Alaska");
+        var subjectFilter2 = new tizen.AttributeFilter("subject", "CONTAINS", "Alabama");
+        var subsfilter = new tizen.CompositeFilter("UNION",
+                [subjectFilter1, subjectFilter2]);
+
+        var pbodyFilter = new tizen.AttributeFilter("body.plainBody", "CONTAINS", "hack");
+        var filter = new tizen.CompositeFilter("INTERSECTION", [subsfilter, pbodyFilter]);
+
+        currentService.messageStorage.addMessagesChangeListener(messageChangeCB, filter);
+        currentService.sync(serviceSyncSuccessCB, serviceSyncFailCB, 30);
+    } else {
+        console.log("servicesListSuccessCB: ERROR: could not find any email service!");
+    }
+}
+
+tizen.messaging.getMessageServices("messaging.email", servicesListSuccessCB);
diff --git a/src/Messaging/TestScripts/allChangeListeners_01.js b/src/Messaging/TestScripts/allChangeListeners_01.js
new file mode 100644 (file)
index 0000000..ff7512f
--- /dev/null
@@ -0,0 +1,172 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        allChangeListeners_01.js
+ */
+
+var prefferedEmailService = "a.jacak.testmail";
+
+function containCaseInsensitive(string, searchString) {
+    var lcString = string.toLowerCase();
+    var lcSearchString = searchString.toLowerCase();
+    return lcString.indexOf(lcSearchString)>=0;
+}
+
+var currentService = null;
+
+//=============================================================================
+// FOLDERS
+//=============================================================================
+function listFolders(prefix, folders) {
+    for (var i=0; i<folders.length; i++) {
+        var folder = folders[i];
+        console.log(prefix + " FOLDER[" + i + "] id: "
+                + folder.id
+                + " name:" + folder.name
+                + " serviceid: " + folder.serviceId);
+    }
+}
+
+var folderChangeCB = {
+    foldersupdated: function(folders) {
+        console.log(folders.length + " folder(s) updated");
+        listFolders("foldersupdated",folders);
+    },
+    foldersadded: function(folders) {
+        console.log(folders.length + " folder(s) added");
+        listFolders("foldersadded",folders);
+    },
+    foldersremoved: function(folders) {
+        console.log(folders.length + " folder(s) removed");
+        listFolders("foldersremoved",folders);
+    }
+ };
+
+
+
+//=============================================================================
+// CONVERSATIONS
+//=============================================================================
+function listConversations(prefix, conversations) {
+
+    for (var i=0; i<conversations.length; i++) {
+        var conversation = conversations[i];
+        console.log(prefix + " CONVERSATION[" + i + "] " +
+                " id: " + conversation.id +
+                " type: " + conversation.type +
+                " timestamp: " + conversation.timestamp +
+                " messageCount: " + conversation.messageCount +
+                " unreadMessages: " + conversation.unreadMessages +
+                " preview: " + conversation.preview +
+                " subject:" + conversation.subject +
+                " isRead: " + conversation.isRead +
+                " from: " + conversation.from +
+                " lastMessageId: " + conversation.lastMessageId);
+    }
+}
+
+var conversationChangeCB = {
+    conversationsupdated: function(conversations) {
+        console.log(conversations.length + " conversation(s) updated");
+        listConversations("conversationsupdated", conversations);
+    },
+    conversationsadded: function(conversations) {
+        console.log(conversations.length + " conversation(s) added");
+        listConversations("conversationsadded", conversations);
+    },
+    conversationsremoved: function(conversations) {
+        console.log(conversations.length + " conversation(s) removed");
+        listConversations("conversationsremoved", conversations);
+    }
+};
+
+//=============================================================================
+// MESSAGES
+//=============================================================================
+function listMessages(prefix, messages) {
+    for (var i=0; i<messages.length; i++) {
+        var message = messages[i];
+        console.log(prefix + " MSG[" + i + "] status: "
+                    + message.messageStatus
+                    + " subject:" + message.subject);
+    }
+}
+
+var messageChangeCB = {
+    messagesupdated: function(messages) {
+        console.log(messages.length + " message(s) updated");
+        listMessages("messagesupdated",messages);
+    },
+    messagesadded: function(messages) {
+       console.log("messagesadded: " + messages.length + " message(s) added");
+       listMessages("messagesadded",messages);
+
+    },
+    messagesremoved: function(messages) {
+        console.log(messages.length + " message(s) removed");
+        listMessages("messagesremoved",messages);
+    }
+};
+
+
+//=============================================================================
+// Sync
+//=============================================================================
+function serviceSyncSuccessCB() {
+    console.log("Synced!");
+}
+
+function serviceSyncFailCB() {
+    console.log("Sync failed!");
+}
+
+//=============================================================================
+// Main
+//=============================================================================
+function servicesListSuccessCB(services) {
+    console.log("servicesListSuccessCB: received:" + services.length + " services");
+
+    if(services.length > 0) {
+
+        var chosenServiceIndex = 0;
+        for(var i = 0; i < services.length; i++) {
+            if(containCaseInsensitive(services[i].name, prefferedEmailService)) {
+                chosenServiceIndex = i;
+                console.log("servicesListSuccessCB: " +
+                        "found service which name contains: " +
+                        prefferedEmailService);
+                break;
+            }
+        }
+        currentService = services[chosenServiceIndex];
+        console.log("servicesListSuccessCB: testing service:" + currentService.name);
+
+        var filter = null;
+
+        currentService.messageStorage.addMessagesChangeListener(messageChangeCB, filter);
+        currentService.messageStorage.addFoldersChangeListener(folderChangeCB, filter);
+        currentService.messageStorage.addConversationsChangeListener(
+                conversationChangeCB, filter);
+
+        currentService.sync(serviceSyncSuccessCB, serviceSyncFailCB, 30);
+    } else {
+        console.log("servicesListSuccessCB: ERROR: could not find any email service!");
+    }
+}
+
+tizen.messaging.getMessageServices("messaging.email", servicesListSuccessCB);
diff --git a/src/Messaging/TestScripts/loadMessageAttachment_01.js b/src/Messaging/TestScripts/loadMessageAttachment_01.js
new file mode 100644 (file)
index 0000000..ed6a18c
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// For simplicity this script is using ONLY first found email message service.
+// If you want to change this please visit servicesListSuccessCB function.
+//
+// It is important to test mailservice which contains at least TWO mails containing
+// attachments.
+//
+
+/**
+ * @file        testLoadMessageAttachment_01.js
+ */
+
+var currentService = null;
+
+function loadMsgAttSuccessCB(attachment) {
+    console.log("loadMsgAttSuccessCB: received attachment:\n"
+            + "        attachmentId: " + attachment.id + "\n"
+            + "        filePath: " + attachment.filePath + "\n"
+            + "        messageId: " + attachment.messageId + "\n"
+            + "        mimeType: " + attachment.mimeType);
+}
+
+function loadMsgAttErrorCB(error) {
+    console.log("loadMsgAttErrorCB: Cannot load message attachment:" + error.message);
+}
+
+function findMessagesSuccessCB(messages) {
+    console.log("messagesFoundCB: found: " + messages.length + " messages");
+
+    for (var msgIndex = 0; msgIndex < messages.length; ++msgIndex) {
+        var message = messages[msgIndex];
+
+        for(var attIndex = 0; attIndex < message.attachments.length; ++attIndex) {
+            var attachment = message.attachments[attIndex];
+
+            console.log("messagesFoundCB: requesting loadMessageAttachment for:\n"
+                    + "        messageId: " + message.id + "\n"
+                    + "        message: " + message.subject + "\n"
+                    + "        attachmentId: " + attachment.id);
+
+            currentService.loadMessageAttachment(attachment, loadMsgAttSuccessCB,
+                         loadMsgAttErrorCB);
+        }
+    }
+}
+
+function findMessagesErrorCB(err) {
+    console.log("servicesListSuccessCB: error:" + err);
+}
+
+function servicesListSuccessCB(services) {
+    console.log("servicesListSuccessCB: received:" + services.length + " services");
+
+    if(services.length > 0) {
+        currentService = services[0];
+        console.log("servicesListSuccessCB: testing service:" + currentService.name);
+        console.log("servicesListSuccessCB: service id is:" + currentService.id);
+        var filter = new tizen.AttributeFilter("hasAttachment", "EXACTLY", true);
+        currentService.messageStorage.findMessages(filter, findMessagesSuccessCB,
+            findMessagesErrorCB);
+    } else {
+        console.log("servicesListSuccessCB: ERROR: could not find any email service!");
+    }
+}
+
+tizen.messaging.getMessageServices("messaging.email", servicesListSuccessCB);
diff --git a/src/Messaging/TestScripts/loadMessageBody_01.js b/src/Messaging/TestScripts/loadMessageBody_01.js
new file mode 100644 (file)
index 0000000..f15dd89
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+//
+// This script registers messagesChangeListener and requests syncing first
+// email message service.
+//
+// If there are new messages it requests loadBody for each message without
+// downloaded body data.
+//
+// Please ensure that there is new email waiting to receive (send new mail before
+// running this test).
+
+/**
+ * @file        testLoadMessageBody_01.js
+ */
+
+var currentService = null;
+
+function loadMBodySuccessCB(message) {
+    console.log("loadMBodySuccessCB: success!");
+    console.log("loadMBodySuccessCB: message subject:" + message.subject);
+
+    if(message.body.plainBody) {
+        console.log("loadMBodySuccessCB: message plainBody:" + message.body.plainBody);
+    } else if(message.body.htmlBody) {
+        console.log("loadMBodySuccessCB: message htmlBody:" + message.body.htmlBody);
+    } else {
+        console.log("loadMBodySuccessCB:"
+            + "ERROR: message do not contain plain nor htmlBody!");
+    }
+}
+function loadMBodyErrorCB(error) {
+    console.log("loadMBodyErrorCB: failes with error:"+error+"!");
+}
+
+var messageChangeCB = {
+    messagesupdated: function(messages) {
+        console.log(messages.length + " message(s) updated");
+    },
+    messagesadded: function(messages) {
+       console.log("messagesadded: " + messages.length + " message(s) added");
+
+        for (var i=0; i<messages.length; i++) {
+            var message = messages[i];
+
+            console.log("messagesadded: MSG[" + i + "] status: "
+                     + message.messageStatus
+                     + " subject:" + message.subject);
+
+            if (message.body.loaded) {
+                console.log("messagesadded: body for message[" + i
+                         + "] is already loaded");
+            } else {
+                console.log("messagesadded: requesting loadMessageBody for message["
+                         + i + "]");
+
+                currentService.loadMessageBody(message, loadMBodySuccessCB,
+                         loadMBodyErrorCB);
+            }
+        }
+    },
+    messagesremoved: function(messages) {
+        console.log(messages.length + " message(s) removed");
+    }
+ };
+
+function serviceSyncSuccessCB() {
+    console.log("Synced!");
+}
+
+function serviceSyncFailCB() {
+    console.log("Sync failed!");
+}
+
+function servicesListSuccessCB(services) {
+    console.log("servicesListSuccessCB: received:" + services.length + " services");
+
+    if(services.length > 0) {
+        currentService = services[0];
+        console.log("servicesListSuccessCB: testing service:" + currentService.name);
+
+        currentService.messageStorage.addMessagesChangeListener(messageChangeCB);
+        currentService.sync(serviceSyncSuccessCB, serviceSyncFailCB, 30);
+    } else {
+        console.log("servicesListSuccessCB: ERROR: could not find any email service!");
+    }
+}
+
+tizen.messaging.getMessageServices("messaging.email", servicesListSuccessCB);
+
diff --git a/src/Messaging/config.xml b/src/Messaging/config.xml
new file mode 100755 (executable)
index 0000000..aea0e73
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-messaging.so</library-name>
+    <feature-install-uri>messaging.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/messaging.read</name>
+        <device-capability>messaging.read</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/messaging.send</name>
+        <device-capability>messaging.send</device-capability>
+    </api-feature>
+
+     <api-feature>
+        <name>http://tizen.org/privilege/messaging.write</name>
+        <device-capability>messaging.write</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/Messaging/plugin_config.cpp b/src/Messaging/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..ecc4fc9
--- /dev/null
@@ -0,0 +1,302 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <map>
+#include <utility>
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include "plugin_config.h"
+
+#define MESSAGING_FEATURE_API_READ "http://tizen.org/privilege/messaging.read"
+#define MESSAGING_FEATURE_API_SEND "http://tizen.org/privilege/messaging.send"    // before sendMessage move to write privilege start
+#define MESSAGING_FEATURE_API_WRITE "http://tizen.org/privilege/messaging.write"
+
+#define MESSAGING_DEVICE_CAP_READ "messaging.read"
+#define MESSAGING_DEVICE_CAP_SEND "messaging.send"    // before sendMessage move to write privilege start
+#define MESSAGING_DEVICE_CAP_WRITE "messaging.write"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+using namespace WrtDeviceApis::Commons;
+
+static WrtDeviceApis::Commons::FunctionMapping createMessagingFunctions();
+static WrtDeviceApis::Commons::FunctionMapping MessagingFunctions = createMessagingFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(Messaging, MessagingFunctions);
+
+#pragma GCC visibility pop
+
+static WrtDeviceApis::Commons::FunctionMapping createMessagingFunctions()
+{
+     /**
+     * Device capabilities
+     */
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_MESSAGING_READ, MESSAGING_DEVICE_CAP_READ);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_MESSAGING_SEND, MESSAGING_DEVICE_CAP_SEND);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_MESSAGING_WRITE, MESSAGING_DEVICE_CAP_WRITE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_MESSAGING_READ);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_MESSAGING_READ, DEVICE_CAP_MESSAGING_READ);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_MESSAGING_SEND);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_MESSAGING_SEND, DEVICE_CAP_MESSAGING_SEND);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_MESSAGING_WRITE);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_MESSAGING_WRITE, DEVICE_CAP_MESSAGING_WRITE);
+
+    /**
+    * API features
+    */
+    ACE_CREATE_FEATURE(FEATURE_MESSAGING_READ, MESSAGING_FEATURE_API_READ);
+    ACE_CREATE_FEATURE(FEATURE_MESSAGING_SEND, MESSAGING_FEATURE_API_SEND);
+    ACE_CREATE_FEATURE(FEATURE_MESSAGING_WRITE, MESSAGING_FEATURE_API_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(MESSAGING_FEATURES_MESSAGING_READ_SEND_WRITE);
+
+    ACE_ADD_API_FEATURE(MESSAGING_FEATURES_MESSAGING_READ_SEND_WRITE, FEATURE_MESSAGING_READ);
+    ACE_ADD_API_FEATURE(MESSAGING_FEATURES_MESSAGING_READ_SEND_WRITE, FEATURE_MESSAGING_SEND);
+    ACE_ADD_API_FEATURE(MESSAGING_FEATURES_MESSAGING_READ_SEND_WRITE, FEATURE_MESSAGING_WRITE);
+
+    ACE_CREATE_FEATURE_LIST(MESSAGING_FEATURES_MESSAGING_READ);
+    ACE_ADD_API_FEATURE(MESSAGING_FEATURES_MESSAGING_READ, FEATURE_MESSAGING_READ);
+
+    ACE_CREATE_FEATURE_LIST(MESSAGING_FEATURES_MESSAGING_SEND);
+    ACE_ADD_API_FEATURE(MESSAGING_FEATURES_MESSAGING_SEND, FEATURE_MESSAGING_SEND);
+
+    ACE_CREATE_FEATURE_LIST(MESSAGING_FEATURES_MESSAGING_WRITE);
+    ACE_ADD_API_FEATURE(MESSAGING_FEATURES_MESSAGING_WRITE, FEATURE_MESSAGING_WRITE);
+
+// before sendMessage move to write privilege start
+    ACE_CREATE_FEATURE_LIST(MESSAGING_FEATURES_MESSAGING_SEND_WRITE);
+
+    ACE_ADD_API_FEATURE(MESSAGING_FEATURES_MESSAGING_SEND_WRITE, FEATURE_MESSAGING_SEND);
+    ACE_ADD_API_FEATURE(MESSAGING_FEATURES_MESSAGING_SEND_WRITE, FEATURE_MESSAGING_WRITE);
+// before sendMessage move to write privilege end
+
+    /**
+     * Functions
+     */
+
+     FunctionMapping MessagingMapping;
+
+    //get Message Service
+    AceFunction getMessagingServiceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_GET_MESSAGE_SERVICE,
+            MESSAGING_FEATURES_MESSAGING_READ_SEND_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert(std::make_pair(
+            MESSAGING_FUNCTION_API_GET_MESSAGE_SERVICE,
+            getMessagingServiceFunc));
+
+      /**  Read  **/
+    AceFunction stopSyncFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_STOP_SYNC,
+            MESSAGING_FEATURES_MESSAGING_READ,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_STOP_SYNC,
+            stopSyncFunc));
+
+    AceFunction findMessagesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_FIND_MESSAGES,
+            MESSAGING_FEATURES_MESSAGING_READ,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_FIND_MESSAGES,
+            findMessagesFunc));
+
+    AceFunction findConversationsFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_FIND_CONVERSATIONS,
+            MESSAGING_FEATURES_MESSAGING_READ,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_FIND_CONVERSATIONS,
+            findConversationsFunc));
+
+    AceFunction findFoldersFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_FIND_FOLDERS,
+            MESSAGING_FEATURES_MESSAGING_READ,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_FIND_FOLDERS,
+            findFoldersFunc));
+
+    AceFunction addMessagesChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_ADD_MESSAGES_CHANGE_LISTNER,
+            MESSAGING_FEATURES_MESSAGING_READ,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_ADD_MESSAGES_CHANGE_LISTNER,
+            addMessagesChangeListenerFunc));
+
+    AceFunction addConversationsChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_ADD_CONVERSATIONS_CHANGE_LISTNER,
+            MESSAGING_FEATURES_MESSAGING_READ,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_ADD_CONVERSATIONS_CHANGE_LISTNER,
+            addConversationsChangeListenerFunc));
+
+    AceFunction addFoldersChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_ADD_FOLDERS_CHANGE_LISTNER,
+            MESSAGING_FEATURES_MESSAGING_READ,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_ADD_FOLDERS_CHANGE_LISTNER,
+            addFoldersChangeListenerFunc));
+
+    AceFunction removeChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_REMOVE_CHANGE_LISTENER,
+            MESSAGING_FEATURES_MESSAGING_READ,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_REMOVE_CHANGE_LISTENER,
+            removeChangeListenerFunc));
+
+    /**  Send  **/
+
+    // before sendMessage move to write privilege start
+    AceFunction sendMessageFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_SEND_MESSAGE,
+            MESSAGING_FEATURES_MESSAGING_SEND_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_SEND_MESSAGE,
+            sendMessageFunc));
+// before sendMessage move to write privilege end
+      /**  Write  **/
+    AceFunction loadMessageBodyFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_LOAD_MESSAGE_BODY,
+            MESSAGING_FEATURES_MESSAGING_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_LOAD_MESSAGE_BODY,
+            loadMessageBodyFunc));
+
+    AceFunction loadMessageAttachmentFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_LOAD_MESSAGE_ATTACHMENT,
+            MESSAGING_FEATURES_MESSAGING_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_LOAD_MESSAGE_ATTACHMENT,
+            loadMessageAttachmentFunc));
+
+    AceFunction syncFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_SYNC,
+            MESSAGING_FEATURES_MESSAGING_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_SYNC,
+            syncFunc));
+
+    AceFunction syncFolderFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_SYNC_FOLDER,
+            MESSAGING_FEATURES_MESSAGING_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_SYNC_FOLDER,
+            syncFolderFunc));
+
+    AceFunction addDraftMessageFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_ADD_DRAFT_MESSAGE,
+            MESSAGING_FEATURES_MESSAGING_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_ADD_DRAFT_MESSAGE,
+            addDraftMessageFunc));
+
+    AceFunction removeMessagesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_REMOVE_MESSAGES,
+            MESSAGING_FEATURES_MESSAGING_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_REMOVE_MESSAGES,
+            removeMessagesFunc));
+
+    AceFunction removeConversationsFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_REMOVE_CONVERSATIONS,
+            MESSAGING_FEATURES_MESSAGING_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_REMOVE_CONVERSATIONS,
+            removeConversationsFunc));
+
+    AceFunction updateMessagesFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_MGR_SERVICE,
+            MESSAGING_FUNCTION_API_UPDATE_MESSAGES,
+            MESSAGING_FEATURES_MESSAGING_WRITE,
+            EMPTY_DEVICE_LIST);
+
+    MessagingMapping.insert( std::make_pair(
+            MESSAGING_FUNCTION_API_UPDATE_MESSAGES,
+            updateMessagesFunc));
+
+    return MessagingMapping;
+}
+
+}
+}
+
+#undef MESSAGING_FEATURE_API
+#undef MESSAGING_FEATURE_API_READ
+#undef MESSAGING_FEATURE_API_SEND // before sendMessage move to write privilege start
+#undef MESSAGING_FEATURE_API_WRITE
+#undef MESSAGING_DEVICE_CAP_READ
+#undef MESSAGING_DEVICE_CAP_SEND // before sendMessage move to write privilege start
+#undef MESSAGING_DEVICE_CAP_WRITE
+
diff --git a/src/Messaging/plugin_config.h b/src/Messaging/plugin_config.h
new file mode 100755 (executable)
index 0000000..c00107a
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _MESSAGING_PLUGIN_CONFIG_H_
+#define _MESSAGING_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Messaging {
+
+DECLARE_FUNCTION_GETTER(Messaging);
+
+#define MESSAGING_CHECK_ACCESS(functionName)   \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(        \
+    getMessagingFunctionData,                                              \
+    functionName)
+
+}
+}
+
+#endif //MESSAGING_PLUGIN_CONFIG_H_
+
diff --git a/src/Messaging/plugin_config_impl.h b/src/Messaging/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..9ade59b
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _MESSAGING_PLUGIN_CONFIG_IMPL_H_
+#define _MESSAGING_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_MESSAGING_MESSAGING_MANAGER_CLASS "messaging"
+#define TIZEN_MESSAGING_MESSAGE_INTERFACE "Message"
+#define TIZEN_MESSAGING_MESSAGE_ATTACHMENT_INTERFACE "MessageAttachment"
+
+// functions
+#define MESSAGING_FUNCTION_API_GET_MESSAGE_SERVICE "getMessageServices"
+#define MESSAGING_FUNCTION_API_SEND_MESSAGE "sendMessage"
+#define MESSAGING_FUNCTION_API_LOAD_MESSAGE_BODY "loadMessageBody"
+#define MESSAGING_FUNCTION_API_LOAD_MESSAGE_ATTACHMENT "loadMessageAttachment"
+#define MESSAGING_FUNCTION_API_SYNC "sync"
+#define MESSAGING_FUNCTION_API_SYNC_FOLDER "syncFolder"
+#define MESSAGING_FUNCTION_API_STOP_SYNC "stopSync"
+#define MESSAGING_FUNCTION_API_ADD_DRAFT_MESSAGE "addDraftMessage"
+#define MESSAGING_FUNCTION_API_FIND_MESSAGES "findMessages"
+#define MESSAGING_FUNCTION_API_REMOVE_MESSAGES "removeMessages"
+#define MESSAGING_FUNCTION_API_UPDATE_MESSAGES "updateMessages"
+#define MESSAGING_FUNCTION_API_FIND_CONVERSATIONS "findConversations"
+#define MESSAGING_FUNCTION_API_REMOVE_CONVERSATIONS "removeConversations"
+#define MESSAGING_FUNCTION_API_FIND_FOLDERS "findFolders"
+#define MESSAGING_FUNCTION_API_ADD_MESSAGES_CHANGE_LISTNER "addMessagesChangeListener"
+#define MESSAGING_FUNCTION_API_ADD_CONVERSATIONS_CHANGE_LISTNER "addConversationsChangeListener"
+#define MESSAGING_FUNCTION_API_ADD_FOLDERS_CHANGE_LISTNER "addFoldersChangeListener"
+#define MESSAGING_FUNCTION_API_REMOVE_CHANGE_LISTENER "removeChangeListener"
+
+#endif //MESSAGING_PLUGIN_CONFIG_IMPL_H_
+
diff --git a/src/Messaging/plugin_initializer.cpp b/src/Messaging/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..e613aa7
--- /dev/null
@@ -0,0 +1,133 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <Security.h>
+#include <TimeTracer.h>
+
+#include "JSMessageAttachment.h"
+#include "JSMessage.h"
+#include "JSMessagingManager.h"
+#include "MessagingManager.h"
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Messaging {
+
+AceSecurityStatus messagingAceCheckAccessFunction(const char* functionName)
+{
+    return MESSAGING_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerMessagingSetter, MessagingManager, gSecurityAccessor);
+
+class_definition_options_t MessagingOptions =
+{
+    JS_CLASS,
+    CREATE_INSTANCE,
+    ALWAYS_NOTICE,
+    USE_OVERLAYED, //ignored
+    AceCheckerMessagingSetter,
+    NULL,
+    NULL
+};
+
+class_definition_options_t MessagingInterfaceOptions = {
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL, // JSWidget::acquireGlobalContext,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId) {
+    LOGD("[Tizen\\MessagingManager] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, messagingAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId) {
+    LOGD("[Tizen\\MessagingManager] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "MessagingManager";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\MessagingManager] on_frame_load_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->
+            addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\MessagingManager] on_frame_unload_callback (%p)", context);
+    DeviceAPI::Common::GlobalContextManager::getInstance()->
+            removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_MESSAGING_MESSAGING_MANAGER_CLASS,
+        (js_class_template_getter)DeviceAPI::Messaging::JSMessagingManager::getClassRef,
+        &MessagingOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_MESSAGING_MESSAGE_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Messaging::JSMessage::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Messaging::JSMessage::constructor,
+        &MessagingInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_MESSAGING_MESSAGE_ATTACHMENT_INTERFACE,
+        (js_class_template_getter)DeviceAPI::Messaging::JSMessageAttachment::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Messaging::JSMessageAttachment::constructor,
+        &MessagingInterfaceOptions)
+PLUGIN_CLASS_MAP_END
+
+} // Messaging
+} // DeviceAPI
diff --git a/src/NFC/CMakeLists.txt b/src/NFC/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..c5637c3
--- /dev/null
@@ -0,0 +1,71 @@
+SET(TARGET_NAME ${nfc_target})
+SET(DESTINATION_NAME ${nfc_dest})
+SET(TARGET_IMPL_NAME ${nfc_impl})
+
+IF(ENABLE_OPTIONAL_NFC)
+PKG_CHECK_MODULES(platform_pkgs_nfc REQUIRED capi-appfw-application capi-network-nfc capi-system-info)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_nfc_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+${CMAKE_INSTALL_RPATH}
+${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSNFCManager.cpp
+    NFCManager.cpp
+    JSNdefMessage.cpp
+    NdefMessage.cpp
+    JSNdefRecord.cpp
+    NdefRecord.cpp
+    JSNdefRecordText.cpp
+    NdefRecordText.cpp
+    JSNdefRecordURI.cpp
+    NdefRecordURI.cpp
+    JSNdefRecordMedia.cpp
+    NdefRecordMedia.cpp
+    JSNFCAdapter.cpp
+    NFCAdapter.cpp
+    JSNFCTag.cpp
+    NFCTag.cpp
+    JSNFCPeer.cpp
+    NFCPeer.cpp
+    NFCUtil.cpp
+    NFCCallbackData.cpp
+    NFCPeerDetectCallback.cpp
+    NFCTagDetectCallback.cpp
+    JSNdefRecordVector.cpp
+    plugin_config.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${platform_pkgs_nfc_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_NFC)
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/nfc
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/NFC/JSNFCAdapter.cpp b/src/NFC/JSNFCAdapter.cpp
new file mode 100755 (executable)
index 0000000..6854b48
--- /dev/null
@@ -0,0 +1,1009 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "JSNFCManager.h"
+#include "NFCManager.h"
+#include "JSNFCAdapter.h"
+#include "JSNdefMessage.h"
+#include "JSNdefRecord.h"
+#include "NFCCallbackData.h"
+#include "plugin_config.h"
+#include "NFCUtil.h"
+
+#include <JSUtil.h>
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <GlobalContextManager.h>
+#include <ArgumentValidator.h>
+#include <TimeTracer.h>
+#include <system_info.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+namespace {
+const char* TIZEN_NFCADAPTER = "NFCAdapter";
+
+const char* TIZEN_NFCADAPTER_POWERED = "powered";
+const char* TIZEN_NFCADAPTER_CARD_EMULATION_MODE = "cardEmulationMode";
+const char* TIZEN_NFCADAPTER_ACTIVE_SECURE_ELEMENT = "activeSecureElement";
+const char* TIZEN_NFCADAPTER_SETTAGLISTENER = "setTagListener";
+const char* TIZEN_NFCADAPTER_UNSETTAGLISTENER = "unsetTagListener";
+const char* TIZEN_NFCADAPTER_SETPEERLISTENER = "setPeerListener";
+const char* TIZEN_NFCADAPTER_UNSETPEERLISTENER = "unsetPeerListener";
+const char* TIZEN_NFCADAPTER_GETCACHEDMESSAGE = "getCachedMessage";
+const char* TIZEN_NFCADAPTER_SETPOWERED = "setPowered";
+const char* TIZEN_NFCADAPTER_ADD_CARD_EMULATION_MODE_CHANGE_LISTENER =
+    "addCardEmulationModeChangeListener";
+const char* TIZEN_NFCADAPTER_REMOVE_CARD_EMULATION_MODE_CHANGE_LISTENER =
+    "removeCardEmulationModeChangeListener";
+const char* TIZEN_NFCADAPTER_ADD_TRANSACTION_EVENT_LISTENER =
+    "addTransactionEventListener";
+const char* TIZEN_NFCADAPTER_REMOVE_TRANSACTION_EVENT_LISTENER =
+    "removeTransactionEventListener";
+const char* TIZEN_NFCADAPTER_ADD_ACTIVE_SECURE_ELEMENT_CHANGE_LISTENER =
+    "addActiveSecureElementChangeListener";
+const char* TIZEN_NFCADAPTER_REMOVE_ACTIVE_SECURE_ELEMENT_CHANGE_LISTENER =
+    "removeActiveSecureElementChangeListener";
+const char* TIZEN_NFCADAPTER_SET_EXCLUSIVE_MODE_FOR_TRANSACTION =
+    "setExclusiveModeForTransaction";
+const char* TIZEN_NFC_ATTACHED = "onattach";
+const char* TIZEN_NFC_DETACHED = "ondetach";
+}
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+struct NFCAdapterHolder {
+    NFCAdapterPtr ptr;
+};
+
+static bool isCardEmultionSupported()
+{
+    bool supported = true;
+    // [TODO] "supported" value should be "false"
+    // after the device capability key is provided by Tizen 2.3 platform.
+
+    if (system_info_get_platform_bool("tizen.org/feature/network.nfc.card_emulation", &supported) != SYSTEM_INFO_ERROR_NONE) {
+        LOGW("Can't check card emulation is supported or not");
+    }
+    return supported;
+}
+
+JSClassDefinition JSNFCAdapter::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_NFCADAPTER,
+    NULL,
+    m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL, // hasProperty,
+    NULL, // getProperty,
+    NULL, // setProperty,
+    NULL, // deleteProperty,
+    NULL, // getPropertyNames,
+    NULL, // callAsFunction,
+    NULL, // callAsConstructor,
+    NULL, // hasInstance,
+    NULL  // convertToType
+};
+
+JSStaticValue JSNFCAdapter::m_property[] =
+{
+    {
+        TIZEN_NFCADAPTER_POWERED,
+        getPowered,
+        NULL,
+        kJSPropertyAttributeDontDelete
+        | kJSPropertyAttributeReadOnly
+    },
+    {
+        TIZEN_NFCADAPTER_CARD_EMULATION_MODE,
+        getCardEmulationMode,
+        setCardEmulationMode,
+        kJSPropertyAttributeNone
+        | kJSPropertyAttributeDontDelete
+    },
+    {
+        TIZEN_NFCADAPTER_ACTIVE_SECURE_ELEMENT,
+        getActiveSecureElement,
+        setActiveSecureElement,
+        kJSPropertyAttributeNone
+        | kJSPropertyAttributeDontDelete
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSNFCAdapter::m_function[] = {
+    {
+        TIZEN_NFCADAPTER_SETPOWERED,
+        setPowered,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_SETTAGLISTENER,
+        setTagListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_UNSETTAGLISTENER,
+        unsetTagListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_SETPEERLISTENER,
+        setPeerListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_UNSETPEERLISTENER,
+        unsetPeerListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_ADD_CARD_EMULATION_MODE_CHANGE_LISTENER,
+        addCardEmulationModeChangeListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_REMOVE_CARD_EMULATION_MODE_CHANGE_LISTENER,
+        removeCardEmulationModeChangeListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_ADD_TRANSACTION_EVENT_LISTENER,
+        addTransactionEventListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_REMOVE_TRANSACTION_EVENT_LISTENER,
+        removeTransactionEventListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_ADD_ACTIVE_SECURE_ELEMENT_CHANGE_LISTENER,
+        addActiveSecureElementChangeListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_REMOVE_ACTIVE_SECURE_ELEMENT_CHANGE_LISTENER,
+        removeActiveSecureElementChangeListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_GETCACHEDMESSAGE,
+        getCachedMessage,
+        kJSPropertyAttributeNone
+    },
+    {
+        TIZEN_NFCADAPTER_SET_EXCLUSIVE_MODE_FOR_TRANSACTION,
+        setExclusiveModeForTransaction,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSNFCAdapter::m_jsClassRef = JSClassCreate(JSNFCAdapter::getClassInfo());
+
+void JSNFCAdapter::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSNFCAdapter::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+NFCAdapterPtr JSNFCAdapter::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    NFCAdapterHolder* priv = static_cast<NFCAdapterHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw DeviceAPI::Common::UnknownException("Priv is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv ptr is null");
+        throw DeviceAPI::Common::UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+const JSClassRef JSNFCAdapter::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNFCAdapter::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSObjectRef JSNFCAdapter::makeJSObject(JSContextRef context, NFCAdapterPtr native)
+{
+    LOGD("Entered");
+
+    if (!native) {
+        LOGW("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    NFCAdapterHolder* priv = new(std::nothrow) NFCAdapterHolder();
+    if (!priv) {
+        LOGW("Memory allocation error");
+        throw UnknownException("Memory allocation error");
+    }
+    priv->ptr = native;
+    priv->ptr->copyAceCheckAccessFunction(NFCManager::getInstance());
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (!obj) {
+        LOGE("Object creation failed");
+        delete priv;
+        throw UnknownException("Object creation failed");
+    }
+    return obj;
+}
+
+JSValueRef JSNFCAdapter::getPowered(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try{
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context,priv->getPowered());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("type get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...){
+        LOGE("Unsupported error while getting type");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCAdapter::setPowered(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    AdapterCallbackData *callback = NULL;
+    try{
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_ADMIN_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        LOGD("Entered");
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        callback = new AdapterCallbackData(
+            g_ctx,
+            validator.toBool(0));
+
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        priv->setPowered(callback);
+    } catch (const BasePlatformException &error) {
+        LOGE("setPowered failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("setPowered failed");
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCAdapter::getCardEmulationMode(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, object);
+        std::string mode = NFCUtil::toStringCardEmulationMode(
+            priv->getCardEmulationMode());
+
+        return JSUtil::toJSValueRef(context, mode);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...){
+        LOGE("Unsupported error while getting card emulation mode");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSNFCAdapter::setCardEmulationMode(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+            NFC_FUNCTION_API_CARD_EMULATION_FUNCS);
+        std::string mode = JSUtil::JSValueToString(context, value);
+
+        priv->setCardEmulationMode(NFCUtil::toCardEmulationMode(mode));
+        return true;
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("Unsupported error while setting card emulation mode");
+        JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return false;
+}
+
+JSValueRef JSNFCAdapter::getActiveSecureElement(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, object);
+        std::string type = NFCUtil::toStringSecureElementType(
+            priv->getActiveSecureElement());
+
+        return JSUtil::toJSValueRef(context, type);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...){
+        LOGE("Unsupported error while getting active secure element");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSNFCAdapter::setActiveSecureElement(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, object);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+            NFC_FUNCTION_API_CARD_EMULATION_FUNCS);
+        std::string type = JSUtil::JSValueToString(context, value);
+
+        priv->setActiveSecureElement(NFCUtil::toSecureElementType(type));
+        return true;
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        JSWebAPIErrorFactory::postException(context, exception,err);
+    } catch (...) {
+        LOGE("Unsupported error while setting active secure element");
+        JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return false;
+}
+
+JSValueRef JSNFCAdapter::setTagListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    NFCAdapterPtr priv;
+    try {
+        priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_TAG_FUNCS);
+
+        ArgumentValidator validator(context ,argumentCount, arguments);
+        JSObjectRef callback_obj = validator.toCallbackObject(0, false,
+                TIZEN_NFC_ATTACHED, TIZEN_NFC_DETACHED, NULL);
+
+        JSObjectRef onattach_obj = NULL;
+        JSValueRef onattach_value = JSUtil::getProperty(context, callback_obj,
+                TIZEN_NFC_ATTACHED);
+        if(!JSValueIsUndefined(context, onattach_value)) {
+            LOGD("onattach exists");
+            onattach_obj = JSUtil::JSValueToObject(context, onattach_value);
+        }
+
+        JSObjectRef ondetach_obj = NULL;
+        JSValueRef ondetach_value = JSUtil::getProperty(context, callback_obj,
+                TIZEN_NFC_DETACHED);
+        if(!JSValueIsUndefined(context, ondetach_value)) {
+            LOGD("ondetach exists");
+            ondetach_obj = JSUtil::JSValueToObject(context, ondetach_value);
+        }
+
+        std::vector <std::string> tag_str_filter = validator.toStringVector(1, true);
+        std::vector <nfc_tag_type_e> tag_filter;
+
+        if (tag_str_filter.empty()) {
+            NFCUtil::setDefaultFilterValues(tag_filter);
+        } else {
+            for (size_t i=0; i<tag_str_filter.size(); ++i) {
+                tag_filter.push_back(NFCUtil::toNfcTagString(tag_str_filter[i]));
+            }
+        }
+
+        JSContextRef global_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        priv->setTagCallback(new NFCTagDetectCallback(global_ctx, onattach_obj, ondetach_obj));
+        priv->getTagCallback()->setFilterValue(tag_filter);
+        priv->setTagListener(priv->getTagCallback());
+
+    } catch (const BasePlatformException &error) {
+        LOGE("setTagListener failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        if (priv) {
+            priv->removeTagCallback();
+        }
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("setTagListener failed");
+        if (priv) {
+            priv->removeTagCallback();
+        }
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCAdapter::setPeerListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    NFCAdapterPtr priv;
+    try {
+        priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_P2P_FUNCS);
+
+        ArgumentValidator validator(context ,argumentCount, arguments);
+        JSObjectRef callback_obj = validator.toCallbackObject(0, false,
+                TIZEN_NFC_ATTACHED, TIZEN_NFC_DETACHED, NULL);
+
+        JSObjectRef onattach_obj = NULL;
+        JSValueRef onattach_value = JSUtil::getProperty(context, callback_obj,
+                TIZEN_NFC_ATTACHED);
+        if(!JSValueIsUndefined(context, onattach_value)) {
+            LOGD("onattach exists");
+            onattach_obj = JSUtil::JSValueToObject(context, onattach_value);
+        }
+
+        JSObjectRef ondetach_obj = NULL;
+        JSValueRef ondetach_value = JSUtil::getProperty(context, callback_obj,
+                TIZEN_NFC_DETACHED);
+        if(!JSValueIsUndefined(context, ondetach_value)) {
+            LOGD("ondetach exists");
+            ondetach_obj = JSUtil::JSValueToObject(context, ondetach_value);
+        }
+
+        JSContextRef global_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        priv->setPeerCallback(new NFCPeerDetectCallback(global_ctx, onattach_obj, ondetach_obj));
+        priv->setPeerListener(priv->getPeerCallback());
+
+    } catch (const BasePlatformException &error) {
+        LOGE("setPeerListener failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        if (priv) {
+            priv->removePeerCallback();
+        }
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("setPeerListener failed");
+        if (priv) {
+            priv->removePeerCallback();
+        }
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCAdapter::unsetTagListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_TAG_FUNCS);
+
+        priv->unsetTagListener();
+    } catch (const BasePlatformException &error) {
+        LOGE("unsetPeerListener failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("unsetPeerListener failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCAdapter::unsetPeerListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_P2P_FUNCS);
+
+        priv->unsetPeerListener();
+    } catch (const BasePlatformException &error) {
+        LOGE("unsetPeerListener failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("unsetPeerListener failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCAdapter::addCardEmulationModeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+            NFC_FUNCTION_API_CARD_EMULATION_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // CardEmulationModeChangeCallback
+        CardEmulationModeChangeCallback *changeCallback =
+            new CardEmulationModeChangeCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        changeCallback->setSuccessCallback(validator.toFunction(0));
+
+        long watchId = priv->addCardEmulationModeChangeListener(changeCallback);
+        return JSUtil::toJSValueRef(context, watchId);
+
+    } catch (const BasePlatformException &error) {
+        LOGE("addCardEmulationModeChangeListener failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("addCardEmulationModeChangeListener failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+JSValueRef JSNFCAdapter::removeCardEmulationModeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+            NFC_FUNCTION_API_CARD_EMULATION_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // watchId
+        long watchId = validator.toLong(0);
+
+        priv->removeCardEmulationModeChangeListener(watchId);
+    } catch (const BasePlatformException &error) {
+        LOGE("removeCardEmulationModeChangeListener failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("removeCardEmulationModeChangeListener failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCAdapter::addTransactionEventListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+            NFC_FUNCTION_API_CARD_EMULATION_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // Secure Element Type
+        nfc_se_type_e type = NFCUtil::toSecureElementType(validator.toString(0));
+
+        // TransactionEventCallback
+        TransactionEventCallback *eventCallback =
+            new TransactionEventCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context),
+                type);
+        eventCallback->setSuccessCallback(validator.toFunction(1));
+
+        long watchId = priv->addTransactionEventListener(type, eventCallback);
+        return JSUtil::toJSValueRef(context, watchId);
+    } catch (const BasePlatformException &error) {
+        LOGE("addTransactionEventListener failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("addTransactionEventListener failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+JSValueRef JSNFCAdapter::removeTransactionEventListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+            NFC_FUNCTION_API_CARD_EMULATION_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // watchId
+        long watchId = validator.toLong(0);
+
+        priv->removeTransactionEventListener(watchId);
+    } catch (const BasePlatformException &error) {
+        LOGE("removeTransactionEventListener failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("removeTransactionEventListener failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCAdapter::addActiveSecureElementChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+            NFC_FUNCTION_API_CARD_EMULATION_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // ActiveSecureElementChangeCallback
+        ActiveSecureElementChangeCallback *changeCallback =
+            new ActiveSecureElementChangeCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        changeCallback->setSuccessCallback(validator.toFunction(0));
+
+        long watchId = priv->addActiveSecureElementChangeListener(changeCallback);
+        return JSUtil::toJSValueRef(context, watchId);
+
+    } catch (const BasePlatformException &error) {
+        LOGE("addActiveSecureElementChangeListener failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("addActiveSecureElementChangeListener failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+JSValueRef JSNFCAdapter::removeActiveSecureElementChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+            NFC_FUNCTION_API_CARD_EMULATION_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        long watchId = validator.toLong(0);
+
+        priv->removeActiveSecureElementChangeListener(watchId);
+
+    } catch (const BasePlatformException &error) {
+        LOGE("removeActiveSecureElementChangeListener failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("removeActiveSecureElementChangeListener failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCAdapter::getCachedMessage(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_COMMON_FUNCS);
+
+        NdefMessagePtr message = priv->getCachedMessage();
+
+        if(message) {
+            return JSNdefMessage::makeJSObject(context, message);
+        }
+
+    } catch (const BasePlatformException &error) {
+        LOGE("getCachedMessage failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("getCachedMessage failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeNull(context);
+}
+
+JSValueRef JSNFCAdapter::setExclusiveModeForTransaction(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        bool supported = isCardEmultionSupported();
+
+        if (supported) {
+            LOGD("card emulation is supported");
+        } else {
+            LOGW("card emulation is not supported");
+            throw NotSupportedException("Card emulation is not supported");
+        }
+
+        NFCAdapterPtr priv = JSNFCAdapter::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(),
+            NFC_FUNCTION_API_CARD_EMULATION_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // mode
+        bool mode = validator.toBool(0);
+
+        priv->setExclusiveModeForTransaction(mode);
+
+    } catch (const BasePlatformException &error) {
+        LOGE("setExclusiveModeForTransaction failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("setExclusiveModeForTransaction failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/JSNFCAdapter.h b/src/NFC/JSNFCAdapter.h
new file mode 100755 (executable)
index 0000000..147ed0e
--- /dev/null
@@ -0,0 +1,194 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_JS_NFCADAPTER_H_
+#define __TIZEN_NFC_JS_NFCADAPTER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "NFCAdapter.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class JSNFCAdapter
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static NFCAdapterPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static JSObjectRef makeJSObject(JSContextRef context, NFCAdapterPtr native);
+private:
+    /**
+     * This member variable contains the values which has to be passed when
+     * the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to the
+     * data structure JSPropertySpec.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Getters  for properties
+     */
+    static JSValueRef getPowered(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef setPowered(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getCardEmulationMode(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setCardEmulationMode(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef  value,
+            JSValueRef* exception);
+
+    static JSValueRef getActiveSecureElement(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setActiveSecureElement(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef  value,
+            JSValueRef* exception);
+
+    static JSValueRef setTagListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setPeerListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetTagListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetPeerListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addCardEmulationModeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeCardEmulationModeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addTransactionEventListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeTransactionEventListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef addActiveSecureElementChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeActiveSecureElementChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getCachedMessage(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setExclusiveModeForTransaction(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_JS_NFCADAPTER_H_
diff --git a/src/NFC/JSNFCManager.cpp b/src/NFC/JSNFCManager.cpp
new file mode 100755 (executable)
index 0000000..5ad8b0b
--- /dev/null
@@ -0,0 +1,320 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSNFCManager.h"
+#include "NFCManager.h"
+#include "JSNFCAdapter.h"
+#include "plugin_config.h"
+
+#include <Logger.h>
+#include <ArgumentValidator.h>
+#include <SecurityExceptions.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+#include <JSUtil.h>
+#include <Export.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+namespace {
+const char* TIZEN_NFCMANAGER = "NFCManager";
+
+const char* TIZEN_NFCMANAGER_GET_DEFAULT_MANAGER = "getDefaultAdapter";
+const char* TIZEN_NFCMANAGER_SET_EXCLUSIVE_MODE = "setExclusiveMode";
+
+const char* TIZEN_NFCMANAGER_TNF_EMPTY = "NFC_RECORD_TNF_EMPTY";
+const char* TIZEN_NFCMANAGER_TNF_WELL_KNOWN = "NFC_RECORD_TNF_WELL_KNOWN";
+const char* TIZEN_NFCMANAGER_TNF_MIME_MEDIA = "NFC_RECORD_TNF_MIME_MEDIA";
+const char* TIZEN_NFCMANAGER_TNF_URI = "NFC_RECORD_TNF_URI";
+const char* TIZEN_NFCMANAGER_TNF_EXTERNAL_RTD = "NFC_RECORD_TNF_EXTERNAL_RTD";
+const char* TIZEN_NFCMANAGER_TNF_UNKNOWN = "NFC_RECORD_TNF_UNKNOWN";
+const char* TIZEN_NFCMANAGER_TNF_UNCHANGED = "NFC_RECORD_TNF_UNCHANGED";
+}
+
+JSClassDefinition JSNFCManager::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_NFCMANAGER,
+    NULL,
+    m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL, // hasProperty,
+    NULL, // getProperty,
+    NULL, // setProperty,
+    NULL, // deleteProperty,
+    NULL, // getPropertyNames,
+    NULL, // callAsFunction,
+    NULL, // callAsConstructor,
+    NULL, // hasInstance,
+    NULL  // convertToType
+};
+
+JSStaticValue JSNFCManager::m_property[] =
+{
+    //NFCManagerProperties
+    {TIZEN_NFCMANAGER_TNF_EMPTY,  get_TNF_EMPTY, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NFCMANAGER_TNF_WELL_KNOWN,  get_TNF_WELL_KNOWN, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NFCMANAGER_TNF_MIME_MEDIA,  get_TNF_MIME_MEDIA, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NFCMANAGER_TNF_URI,  get_TNF_URI, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NFCMANAGER_TNF_EXTERNAL_RTD,  get_TNF_EXTERNAL_RTD, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NFCMANAGER_TNF_UNKNOWN,  get_TNF_UNKNOWN, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NFCMANAGER_TNF_UNCHANGED,  get_TNF_UNCHANGED, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSNFCManager::m_function[] = {
+    {TIZEN_NFCMANAGER_GET_DEFAULT_MANAGER, JSNFCManager::getDefaultAdapter,
+            kJSPropertyAttributeNone },
+    {TIZEN_NFCMANAGER_SET_EXCLUSIVE_MODE, JSNFCManager::setExclusiveMode,
+            kJSPropertyAttributeNone },
+    { 0, 0, 0}
+};
+
+JSClassRef JSNFCManager::m_jsClassRef = JSClassCreate(JSNFCManager::getClassInfo());
+
+void JSNFCManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+    JSObjectSetPrivate(object, static_cast<void*>(&(NFCManager::getInstance())));
+}
+
+void JSNFCManager::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+
+const JSClassRef DLL_EXPORT JSNFCManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+         m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNFCManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSNFCManager::get_TNF_EMPTY(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        return JSValueMakeNumber(context,
+                NFCManager::getInstance().NFC_RECORD_TNF_EMPTY);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("get_TNF_EMPTY failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...){
+        LOGE("get_TNF_EMPTY failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCManager::get_TNF_WELL_KNOWN(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        return JSValueMakeNumber(context,
+                NFCManager::getInstance().NFC_RECORD_TNF_WELL_KNOWN);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("get_TNF_WELL_KNOWN failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...){
+        LOGE("get_TNF_WELL_KNOWN failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCManager::get_TNF_MIME_MEDIA(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        return JSValueMakeNumber(context,
+                NFCManager::getInstance().NFC_RECORD_TNF_MIME_MEDIA);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("get_TNF_MIME_MEDIA failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...){
+        LOGE("get_TNF_MIME_MEDIA failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCManager::get_TNF_URI(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        return JSValueMakeNumber(context,
+                NFCManager::getInstance().NFC_RECORD_TNF_URI);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("get_TNF_URI failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...){
+        LOGE("get_TNF_URI failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCManager::get_TNF_EXTERNAL_RTD(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        return JSValueMakeNumber(context,
+                NFCManager::getInstance().NFC_RECORD_TNF_EXTERNAL_RTD);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("get_TNF_EXTERNAL_RTD failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...){
+        LOGE("get_TNF_EXTERNAL_RTD failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCManager::get_TNF_UNKNOWN(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        return JSValueMakeNumber(context,
+                NFCManager::getInstance().NFC_RECORD_TNF_UNKNOWN);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("get_TNF_UNKNOWN failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...){
+        LOGE("get_TNF_UNKNOWN failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCManager::get_TNF_UNCHANGED(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        return JSValueMakeNumber(context,
+                NFCManager::getInstance().NFC_RECORD_TNF_UNCHANGED);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("get_TNF_UNCHANGED failed: name: %s, msg: %s",
+            error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...){
+        LOGE("get_TNF_UNCHANGED failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCManager::getDefaultAdapter (JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    TIZEN_CHECK_ACCESS(context, exception, &(NFCManager::getInstance()),
+            NFC_FUNCTION_API_COMMON_FUNCS);
+
+    try {
+        JSObjectRef js_object = JSNFCAdapter::makeJSObject(context,
+                NFCManager::getInstance().getDefaultAdapter());
+        return js_object;
+    } catch (const BasePlatformException &error) {
+        LOGE("getDefaultAdapter failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("getDefaultAdapter failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+JSValueRef JSNFCManager::setExclusiveMode (JSContextRef context, JSObjectRef object,
+        JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    TIZEN_CHECK_ACCESS(context, exception, &(NFCManager::getInstance()),
+            NFC_FUNCTION_API_COMMON_FUNCS);
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        bool mode = validator.toBool(0);
+        NFCManager::getInstance().setExclusiveMode(mode);
+    } catch (const BasePlatformException &error) {
+        LOGE("getDefaultAdapter failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("getDefaultAdapter failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+}
+}
diff --git a/src/NFC/JSNFCManager.h b/src/NFC/JSNFCManager.h
new file mode 100755 (executable)
index 0000000..3818ff5
--- /dev/null
@@ -0,0 +1,120 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_NFC_JS_NFCMANAGER_H_
+#define __TIZEN_NFC_JS_NFCMANAGER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+
+class JSNFCManager
+{
+public:
+    static const JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+private:
+    /**
+     * This member variable contains the values which has to be passed when
+     * the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to the
+     * data structure JSPropertySpec.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef get_TNF_EMPTY(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef get_TNF_WELL_KNOWN(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef get_TNF_MIME_MEDIA(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef get_TNF_URI(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef get_TNF_EXTERNAL_RTD(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef get_TNF_UNKNOWN(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef get_TNF_UNCHANGED(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getDefaultAdapter(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setExclusiveMode(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+};
+
+}
+}
+
+#endif // __TIZEN_NFC_JS_NFCMANAGER_H_
diff --git a/src/NFC/JSNFCPeer.cpp b/src/NFC/JSNFCPeer.cpp
new file mode 100755 (executable)
index 0000000..515cfac
--- /dev/null
@@ -0,0 +1,322 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NFCManager.h"
+#include "NFCPeer.h"
+#include "JSNFCPeer.h"
+#include "JSNFCManager.h"
+#include "JSNdefMessage.h"
+#include "plugin_config.h"
+
+#include <JSUtil.h>
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+namespace {
+const char* TIZEN_NFCPEER = "NFCPeer";
+
+const char* TIZEN_NFCPEER_ISCONNECTED = "isConnected";
+const char* TIZEN_NFCPEER_SETRECEIVENDEFLISTENER = "setReceiveNDEFListener";
+const char* TIZEN_NFCPEER_UNSETRECEIVENDEFLISTENER = "unsetReceiveNDEFListener";
+const char* TIZEN_NFCPEERSENDNDEF = "sendNDEF";
+}
+
+namespace DeviceAPI {
+namespace NFC {
+
+using namespace DeviceAPI::Common;
+
+struct NFCPeerHolder{
+    NFCPeerPtr ptr;
+};
+
+JSClassDefinition JSNFCPeer::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_NFCPEER,
+    NULL,
+    m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL, // hasProperty,
+    NULL, // getProperty,
+    NULL, // setProperty,
+    NULL, // deleteProperty,
+    NULL, // getPropertyNames,
+    NULL, // callAsFunction,
+    NULL, // callAsConstructor,
+    NULL, // hasInstance,
+    NULL  // convertToType
+};
+
+JSStaticValue JSNFCPeer::m_property[] =
+{
+    //NFCTargetProperties
+    { TIZEN_NFCPEER_ISCONNECTED, getIsConnected, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSNFCPeer::m_function[] = {
+    {TIZEN_NFCPEER_SETRECEIVENDEFLISTENER, setReceiveNDEFListener,
+            kJSPropertyAttributeNone},
+    {TIZEN_NFCPEER_UNSETRECEIVENDEFLISTENER, unsetReceiveNDEFListener,
+            kJSPropertyAttributeNone},
+    {TIZEN_NFCPEERSENDNDEF, sendNDEF, kJSPropertyAttributeNone},
+    { 0, 0, 0}
+};
+
+JSClassRef JSNFCPeer::m_jsClassRef = JSClassCreate(JSNFCPeer::getClassInfo());
+
+void JSNFCPeer::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSNFCPeer::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+const JSClassRef JSNFCPeer::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNFCPeer::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+NFCPeerPtr JSNFCPeer::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    NFCPeerHolder* priv = static_cast<NFCPeerHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (!(priv->ptr)){
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+JSObjectRef JSNFCPeer::makeJSObject(JSContextRef context, NFCPeerPtr data)
+{
+    LOGD("Entered");
+    if (!data) {
+        LOGE("Null Peer pointer given");
+        throw UnknownException("Null RecordText pointer given");
+    }
+
+    NFCPeerHolder* priv = new(std::nothrow) NFCPeerHolder();
+    if (!priv) {
+        LOGE("Memory allocation error");
+        throw UnknownException("Memory allocation error");
+    }
+    priv->ptr = data;
+    priv->ptr->copyAceCheckAccessFunction(NFCManager::getInstance());
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (!obj) {
+        LOGE("Object creation failed");
+        delete priv;
+        throw UnknownException("Object creation failed");
+    }
+    return obj;
+}
+
+JSValueRef JSNFCPeer::getIsConnected(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSNFCPeer::getPrivateObject(context,object);
+
+        return JSUtil::toJSValueRef(context, priv->isConnected());
+    }
+    catch(const BasePlatformException &e) {
+        LOGE("get is connected flag failed: %s : %s", (e.getName()).c_str(),
+                (e.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting is connected flag.");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCPeer::setReceiveNDEFListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    Common::CallbackUserData *callback = NULL;
+    NFCPeerPtr priv;
+    try {
+        priv = JSNFCPeer::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_P2P_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        callback = new(std::nothrow) Common::CallbackUserData(g_ctx);
+        if(!callback) {
+            LOGE("Callback data creation failed");
+            throw Common::UnknownException("Callback data creation failed");
+        }
+
+        callback->setSuccessCallback(validator.toFunction(0, false));
+
+        priv->setPeerCallback(callback);
+
+        priv->setReceiveNDEFListener(priv->getPeerCallback());
+
+    } catch (const BasePlatformException &error) {
+        LOGE("setPeerListener failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        if(callback) {
+            delete callback;
+            callback = NULL;
+            priv->setPeerCallback(NULL);
+        }
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("setPeerListener failed");
+        if(callback) {
+            delete callback;
+            callback = NULL;
+            priv->setPeerCallback(NULL);
+        }
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCPeer::unsetReceiveNDEFListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        NFCPeerPtr priv = JSNFCPeer::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_P2P_FUNCS);
+
+        priv->unsetReceiveNDEFListener();
+    } catch(const BasePlatformException &error) {
+        LOGE("unsetReceiverNDEFListener failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch(...) {
+        LOGE("unsetReceiveNDEFListener failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCPeer::sendNDEF(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    NdefMessageCallbackData *callback = NULL;
+    try {
+        auto priv = JSNFCPeer::getPrivateObject(context,thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_P2P_FUNCS);
+
+//        void sendNDEF(NDEFMessage ndefMessage,
+//                optional SuccessCallback? successCallback,
+//                optional ErrorCallback? errorCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        NdefMessagePtr ndef_message = JSNdefMessage::getPrivateObject(context,
+                        validator.toJSValueRef(0));
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        callback = new(std::nothrow) NdefMessageCallbackData(g_ctx);
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw UnknownException("Callback data creation failed");
+        }
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setMessage(ndef_message);
+
+        priv->sendNDEF(callback);
+    }
+    catch(const BasePlatformException &e) {
+        LOGE("Error while sending NDEF message: %s : %s", (e.getName()).c_str(),
+                (e.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+    catch(...) {
+        LOGE("Error while sending NDEF message");
+        UnknownException err("Error while sending NDEF message");
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/JSNFCPeer.h b/src/NFC/JSNFCPeer.h
new file mode 100755 (executable)
index 0000000..2170ac4
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_NFC_JS_NFCPEER_H_
+#define __TIZEN_NFC_JS_NFCPEER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "NFCPeer.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class JSNFCPeer
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static NFCPeerPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static JSObjectRef makeJSObject(JSContextRef ctx, NFCPeerPtr data);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed when
+     * the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to the
+     * data structure JSPropertySpec.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Getters and setters for properties
+     */
+    static JSValueRef getIsConnected(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef setReceiveNDEFListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetReceiveNDEFListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef sendNDEF(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_JS_NFCPEER_H_
diff --git a/src/NFC/JSNFCTag.cpp b/src/NFC/JSNFCTag.cpp
new file mode 100755 (executable)
index 0000000..37864d4
--- /dev/null
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "NFCManager.h"
+#include "JSNFCTag.h"
+#include "JSNdefMessage.h"
+#include "JSNFCManager.h"
+#include "plugin_config.h"
+#include "NFCUtil.h"
+#include "NFCTag.h"
+#include "NFCCallbackData.h"
+
+#include <JSUtil.h>
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+#include <TimeTracer.h>
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+namespace {
+const char* TIZEN_NFCTAG = "NFCTag";
+
+const char* TIZEN_NFCTAG_TYPE = "type";
+const char* TIZEN_NFCTAG_ISSUPPORTEDNDEF = "isSupportedNDEF";
+const char* TIZEN_NFCTAG_NDEFSIZE = "ndefSize";
+const char* TIZEN_NFCTAG_PROPERTIES = "properties";
+const char* TIZEN_NFCTAG_ISCONNECTED = "isConnected";
+const char* TIZEN_NFCTAG_READNDEF = "readNDEF";
+const char* TIZEN_NFCTAG_WRITENDEF = "writeNDEF";
+const char* TIZEN_NFCTAG_TRANSCEIVE = "transceive";
+}
+
+namespace DeviceAPI {
+namespace NFC {
+
+using namespace DeviceAPI::Common;
+
+struct NFCTagHolder{
+    NFCTagPtr ptr;
+};
+
+JSClassDefinition JSNFCTag::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_NFCTAG,
+    NULL,
+    m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL, // hasProperty,
+    NULL, // getProperty,
+    NULL, // setProperty,
+    NULL, // deleteProperty,
+    NULL, // getPropertyNames,
+    NULL, // callAsFunction,
+    NULL, // callAsConstructor,
+    NULL, // hasInstance,
+    NULL  // convertToType
+};
+
+JSStaticValue JSNFCTag::m_property[] =
+{
+    //NFCTagProperties
+    { TIZEN_NFCTAG_TYPE, getType, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { TIZEN_NFCTAG_ISSUPPORTEDNDEF, getIsSupportedNDEF, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { TIZEN_NFCTAG_NDEFSIZE, getNdefSize, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { TIZEN_NFCTAG_PROPERTIES, getProperties, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { TIZEN_NFCTAG_ISCONNECTED, getIsConnected, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSNFCTag::m_function[] = {
+    {TIZEN_NFCTAG_READNDEF, readNDEF, kJSPropertyAttributeNone},
+    {TIZEN_NFCTAG_WRITENDEF, writeNDEF, kJSPropertyAttributeNone},
+    {TIZEN_NFCTAG_TRANSCEIVE, transceive, kJSPropertyAttributeNone},
+    { 0, 0, 0}
+};
+
+JSClassRef JSNFCTag::m_jsClassRef = JSClassCreate(JSNFCTag::getClassInfo());
+
+void JSNFCTag::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSNFCTag::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+const JSClassRef JSNFCTag::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNFCTag::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+NFCTagPtr JSNFCTag::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    if(!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    NFCTagHolder* priv = static_cast<NFCTagHolder*>(JSObjectGetPrivate(object));
+    if(!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if(!priv->ptr) {
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+JSObjectRef JSNFCTag::makeJSObject(JSContextRef context, NFCTagPtr data)
+{
+    LOGD("Entered");
+    if (!data) {
+        LOGE("Null Tag pointer given");
+        throw UnknownException("Null Tag pointer given");
+    }
+
+    NFCTagHolder* priv = new(std::nothrow) NFCTagHolder();
+    if (!priv) {
+        LOGE("Memory allocation error");
+        throw UnknownException("Memory allocation error");
+    }
+    priv->ptr = data;
+    priv->ptr->copyAceCheckAccessFunction(NFCManager::getInstance());
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (!obj) {
+        LOGE("Object creation failed");
+        delete priv;
+        throw UnknownException("Object creation failed");
+    }
+    return obj;
+}
+
+JSValueRef JSNFCTag::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSNFCTag::getPrivateObject(context,object);
+
+        return JSUtil::toJSValueRef(context, priv->getTypeString());
+    }
+    catch(const BasePlatformException &e) {
+        LOGE("get tag type failed: %s : %s", (e.getName()).c_str(),
+                (e.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting tag type");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCTag::getIsSupportedNDEF(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSNFCTag::getPrivateObject(context,object);
+
+        return JSUtil::toJSValueRef(context, priv->isSupportedNDEF());
+    }
+    catch(const BasePlatformException &e) {
+        LOGE("get is NDEF supported flag failed: %s : %s", (e.getName()).c_str(),
+                (e.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting is NDEF supported flag");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCTag::getNdefSize(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSNFCTag::getPrivateObject(context,object);
+
+        return JSUtil::toJSValueRef(context, priv->getNdefSize());
+    }
+    catch(const BasePlatformException &e) {
+        LOGE("get NDEF size failed: %s : %s", (e.getName()).c_str(),
+                (e.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting NDEF size");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCTag::getProperties(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSNFCTag::getPrivateObject(context,object);
+
+        return JSUtil::toJSValueRef_(context, priv->getProperties());
+    }
+    catch(const BasePlatformException &e) {
+        LOGE("get tag properties failed: %s : %s", (e.getName()).c_str(),
+                (e.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting tag properties");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCTag::getIsConnected(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        auto priv = JSNFCTag::getPrivateObject(context,object);
+
+        return JSUtil::toJSValueRef(context, priv->isConnected());
+    }
+    catch(const BasePlatformException &e) {
+        LOGE("get is connected flag failed: %s : %s", (e.getName()).c_str(),
+                (e.getMessage()).c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting is connected flag");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCTag::readNDEF(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    NdefMessageCallbackData *callback = NULL;
+    try {
+        NFCTagPtr priv = JSNFCTag::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_TAG_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSContextRef global_ctx = GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        callback = new NdefMessageCallbackData(global_ctx);
+        callback->setSuccessCallback(validator.toFunction(0));
+        callback->setErrorCallback(validator.toFunction(1,true));
+
+        priv->readNDEF(callback);
+
+    } catch (const BasePlatformException &error) {
+        LOGE("readNDEF failed: name: %s, msg: %s",
+                error.getName().c_str(),error.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("readNDEF failed.");
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "readNDEF failed");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCTag::writeNDEF(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    NdefMessageCallbackData *callback = NULL;
+    try {
+        auto priv = JSNFCTag::getPrivateObject(context,thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_TAG_FUNCS);
+//        void writeNDEF(NDEFMessage ndefMessage,
+//                           optional SuccessCallback? successCallback,
+//                           optional ErrorCallback? errorCallback);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        NdefMessagePtr ndef_message = JSNdefMessage::getPrivateObject(context,
+                        validator.toJSValueRef(0));
+
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        callback = new(std::nothrow) NdefMessageCallbackData(g_ctx);
+        if (!callback) {
+            LOGE("Callback data creation failed");
+            throw UnknownException("Callback data creation failed");
+        }
+        callback->setSuccessCallback(validator.toFunction(1, true));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setMessage(ndef_message);
+
+        priv->writeNDEF(callback);
+    }
+    catch(const BasePlatformException &e) {
+        LOGE("Error while writing NDEF message: %s : %s", (e.getName()).c_str(),
+                (e.getMessage()).c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+    catch(...) {
+        LOGE("Error while writing NDEF message");
+        UnknownException err("Error while writing NDEF message");
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNFCTag::transceive(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ByteArraySuccessCallback *callback = NULL;
+    try{
+        NFCTagPtr priv = JSNFCTag::getPrivateObject(context, thisObject);
+        TIZEN_CHECK_ACCESS(context, exception, priv.get(), NFC_FUNCTION_API_TAG_FUNCS);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        callback = new ByteArraySuccessCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        if (!callback) {
+             LOGE("Callback data creation failed");
+             throw UnknownException("Callback data creation failed");
+        }
+
+        callback->setInputData(validator.toUCharVector(0));
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+
+        priv->transceive(callback);
+    } catch (const BasePlatformException &error) {
+        LOGE("transceive failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("transceive failed");
+        delete callback;
+        callback = NULL;
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/JSNFCTag.h b/src/NFC/JSNFCTag.h
new file mode 100755 (executable)
index 0000000..8b9012c
--- /dev/null
@@ -0,0 +1,126 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#ifndef __TIZEN_NFC_JS_NFCTAG_H_
+#define __TIZEN_NFC_JS_NFCTAG_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "NFCTag.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class JSNFCTag
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static NFCTagPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static JSObjectRef makeJSObject(JSContextRef ctx, NFCTagPtr data);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed when
+     * the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to the
+     * data structure JSPropertySpec.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Getters for properties
+     */
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsSupportedNDEF(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getNdefSize(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getProperties(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsConnected(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef readNDEF(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef writeNDEF(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef transceive(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_JS_NFCTAG_H_
diff --git a/src/NFC/JSNdefMessage.cpp b/src/NFC/JSNdefMessage.cpp
new file mode 100755 (executable)
index 0000000..43ee418
--- /dev/null
@@ -0,0 +1,382 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSNdefMessage.h"
+#include "JSNdefRecord.h"
+#include "JSNdefRecordText.h"
+#include "JSNdefRecordURI.h"
+#include "JSNdefRecordMedia.h"
+#include "NdefRecord.h"
+
+#include <Logger.h>
+#include <JSUtil.h>
+#include <TimeTracer.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <Export.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+using namespace DeviceAPI::Common;
+
+struct NdefMessageHolder{
+    NdefMessagePtr ptr;
+};
+
+namespace {
+const char* TIZEN_NDEFMESSAGE = "NDEFMessage";
+const char* TIZEN_NDEFMESSAGE_RECORDCOUNT = "recordCount";
+const char* TIZEN_NDEFMESSAGE_RECORDS = "records";
+}
+
+JSClassDefinition JSNdefMessage::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_NDEFMESSAGE,
+    NULL,
+    m_property,
+    m_function,
+    initialize,
+    finalize,
+    NULL, // hasProperty,
+    NULL, // getProperty,
+    NULL, // setProperty,
+    NULL, // deleteProperty,
+    NULL, // getPropertyNames,
+    NULL, // callAsFunction,
+    NULL, // callAsConstructor,
+    NULL, // hasInstance,
+    NULL  // convertToType
+};
+
+JSStaticValue JSNdefMessage::m_property[] =
+{
+    { TIZEN_NDEFMESSAGE_RECORDCOUNT, getRecordCount, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { TIZEN_NDEFMESSAGE_RECORDS, getRecords, setRecords,
+            kJSPropertyAttributeDontDelete},
+    { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSNdefMessage::m_function[] = {
+    {"toByte", JSNdefMessage::toByte, kJSPropertyAttributeNone},
+    { 0, 0, 0}
+};
+
+JSClassRef JSNdefMessage::m_jsClassRef = JSClassCreate(JSNdefMessage::getClassInfo());
+
+
+void JSNdefMessage::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSNdefMessage::finalize(JSObjectRef object)
+{
+    LOGD( "Entered");
+}
+
+const JSClassRef DLL_EXPORT JSNdefMessage::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNdefMessage::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSNdefMessage::setPrivateObject(JSObjectRef object, NdefMessagePtr data)
+{
+    LOGD("Entered");
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    NdefMessageHolder* priv = static_cast<NdefMessageHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new(std::nothrow) NdefMessageHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in NdefRecord");
+            throw UnknownException(
+                    "Failed to set NdefRecord private data");
+        }
+    }
+}
+
+NdefMessagePtr JSNdefMessage::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    NdefMessageHolder* priv = static_cast<NdefMessageHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw TypeMismatchException("Type mismatch");
+    }
+    if (!(priv->ptr)){
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+JSObjectRef JSNdefMessage::makeJSObject(JSContextRef context, NdefMessagePtr native)
+{
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    NdefMessageHolder* priv = new(std::nothrow) NdefMessageHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (!obj) {
+        LOGE("Object creation failed");
+        delete priv;
+        priv = NULL;
+        throw UnknownException("Object creation failed");
+    }
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSNdefMessage::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef js_obj_ref = JSObjectMake(context, getClassRef(), NULL);
+    JSStringRef ctor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, js_obj_ref, ctor_name, constructor,
+            kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctor_name);
+
+    try {
+        NdefMessagePtr priv;
+        if (validator.isOmitted(0) || validator.isNull(0) || validator.isUndefined(0)) {
+            priv = NdefMessagePtr(new (std::nothrow) NdefMessage());
+        } else {
+            if(JSIsArrayValue(context, arguments[0])) {
+                JSObjectRef data = validator.toArrayObject(0);
+                bool is_record_array = false, is_byte_array = false;
+                NdefRecordPtrVector records;
+                size_t size = JSGetArrayLength(context, data);
+                unsigned char *buffer = new unsigned char[size];
+                for (unsigned int i = 0; i < size; ++i) {
+                    JSValueRef element = JSGetArrayElement(context, data, i);
+                    if (JSValueIsObjectOfClass(context, element,
+                                JSNdefRecordText::getClassRef())) {
+                        is_record_array = true;
+                        records.push_back(JSNdefRecordText::getPrivateObject(
+                            context, element));
+                    } else if (JSValueIsObjectOfClass(context, element,
+                                JSNdefRecordURI::getClassRef())) {
+                        is_record_array = true;
+                        records.push_back(JSNdefRecordURI::getPrivateObject(
+                            context, element));
+                    } else if (JSValueIsObjectOfClass(context, element,
+                                JSNdefRecordMedia::getClassRef())) {
+                        is_record_array = true;
+                        records.push_back(JSNdefRecordMedia::getPrivateObject(
+                            context, element));
+                    } else if(JSValueIsObjectOfClass(context, element,
+                            JSNdefRecord::getClassRef())) {
+                        is_record_array = true;
+                        records.push_back(JSNdefRecord::getPrivateObject(context,
+                            element));
+                    } else {
+                        is_byte_array = true;
+                        buffer[i] = static_cast<unsigned char>(
+                            JSUtil::JSValueToByte(context, element));
+                    }
+                    if (is_record_array && is_byte_array) {
+                        break;
+                    }
+                }
+                if (!is_record_array && is_byte_array) {
+                    priv = NdefMessagePtr(new (std::nothrow) NdefMessage(buffer, size));
+                }
+                if (is_record_array && !is_byte_array) {
+                    priv = NdefMessagePtr(new (std::nothrow) NdefMessage(records));
+                }
+                if (!is_record_array && !is_byte_array) {
+                    priv = NdefMessagePtr(new (std::nothrow) NdefMessage());
+                }
+                delete [] buffer;
+            }
+        }
+        setPrivateObject(js_obj_ref, priv);
+    } catch (const BasePlatformException &error) {
+        LOGE("constructor failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+    } catch (...) {
+        LOGE("constructor failed");
+    }
+
+    return js_obj_ref;
+}
+
+JSValueRef JSNdefMessage::getRecordCount(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        NdefMessagePtr priv = JSNdefMessage::getPrivateObject(context, object);
+
+        return  JSUtil::toJSValueRef(context,priv->getRecordsCount());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("tnf get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...){
+        LOGE("Unsupported error while getting tnf");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNdefMessage::getRecords(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        NdefMessagePtr priv = JSNdefMessage::getPrivateObject(context, object);
+
+        return priv->getJSRecords(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("records get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...){
+        LOGE("Unsupported error while getting records");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSNdefMessage::setRecords(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    NdefMessagePtr priv;
+    NdefRecordPtrVector records;
+
+    try{
+        if (JSValueIsNull(context, value)
+            || JSValueIsUndefined(context, value)
+            || !JSIsArrayValue(context, value)) {
+            LOGE("value is invalid");
+            return false;
+        }
+
+        priv = JSNdefMessage::getPrivateObject(context, object);
+
+        records = JSUtil::JSArrayToType_<NdefRecordPtr>(
+                context, value, JSNdefRecord::getPrivateObject);
+        priv->setRecords(records);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("records set failed: %s : %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...)
+    {
+        LOGE("Unsupported error while setting records");
+    }
+    // given record is invalid
+    if (records.empty()) {
+        try{
+            NdefRecordPtr invalid_record (new (std::nothrow) NdefRecord());
+            if (invalid_record) {
+                records.push_back(invalid_record);
+            }
+            priv->setRecords(records);
+        }
+        catch (...)
+        {
+            LOGE("Unsupported error while setting records");
+        }
+    }
+
+    return true;
+}
+
+JSValueRef JSNdefMessage::toByte(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        NdefMessagePtr priv = JSNdefMessage::getPrivateObject(context, thisObject);
+
+        return JSUtil::toJSValueRef_(context,priv->toByte());
+    } catch (const BasePlatformException &error) {
+        LOGE("toByte failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, error);
+    } catch (...) {
+        LOGE("toByte failed");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+}
+
+}
+}
diff --git a/src/NFC/JSNdefMessage.h b/src/NFC/JSNdefMessage.h
new file mode 100755 (executable)
index 0000000..23e442b
--- /dev/null
@@ -0,0 +1,131 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#ifndef __TIZEN_NFC_JS_NDEFMESSAGE_H_
+#define __TIZEN_NFC_JS_NDEFMESSAGE_H_
+
+#include "NdefMessage.h"
+
+#include <Logger.h>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+class JSNdefMessage
+{
+public:
+
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static NdefMessagePtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, NdefMessagePtr data);
+
+    static JSObjectRef makeJSObject(JSContextRef context, NdefMessagePtr native);
+
+    static JSObjectRef constructor(JSContextRef ctx,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed when
+     * the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to the
+     * data structure JSPropertySpec.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+
+    /**
+     * Getters and setters for properties
+     */
+    static JSValueRef getRecordCount(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getRecords(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setRecords(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef toByte(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    template<class T, class U>
+    static JSObjectRef toJSObjectArray(JSContextRef context,
+            const std::vector<T> & vec)
+    {
+        size_t vec_size = vec.size();
+        JSObjectRef array[vec_size];
+        for (size_t i = 0; i < vec_size; ++i) {
+            array[i] = U::makeJSObject(context, vec[i]);
+        }
+        JSObjectRef result = JSObjectMakeArray(context,
+                vec_size, vec_size ? array : NULL, NULL);
+        if (!result) {
+            LOGW("Array is null");
+            throw Common::UnknownException("Array is null");
+        }
+        return result;
+    }
+};
+
+}
+}
+
+#endif /* __TIZEN_NFC_JS_NDEFMESSAGE_H_ */
diff --git a/src/NFC/JSNdefRecord.cpp b/src/NFC/JSNdefRecord.cpp
new file mode 100755 (executable)
index 0000000..9b6447c
--- /dev/null
@@ -0,0 +1,327 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSNdefRecord.h"
+#include "NdefRecord.h"
+
+#include <JSUtil.h>
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <Export.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+using namespace DeviceAPI::Common;
+
+struct NdefRecordHolder{
+    NdefRecordPtr ptr;
+};
+
+namespace {
+const char*  TIZEN_NDEFRECORD = "NDEFRecord";
+
+const char*  TIZEN_NDEFRECORD_TNF = "tnf";
+const char*  TIZEN_NDEFRECORD_TYPE = "type";
+const char*  TIZEN_NDEFRECORD_ID = "id";
+const char*  TIZEN_NDEFRECORD_PAYLOAD = "payload";
+}
+
+JSClassDefinition JSNdefRecord::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_NDEFRECORD,
+    NULL,
+    m_property,
+    NULL,
+    initialize,
+    finalize,
+    NULL, // hasProperty,
+    NULL, // getProperty,
+    NULL, // setProperty,
+    NULL, // deleteProperty,
+    NULL, // getPropertyNames,
+    NULL, // callAsFunction,
+    NULL, // callAsConstructor,
+    NULL, // hasInstance,
+    NULL  // convertToType
+};
+
+JSStaticValue JSNdefRecord::m_property[] =
+{
+    {TIZEN_NDEFRECORD_TNF,  getTnf, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NDEFRECORD_TYPE,  getType, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NDEFRECORD_ID,  getId, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NDEFRECORD_PAYLOAD,  getPayload, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSNdefRecord::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNdefRecord::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSNdefRecord::m_jsClassRef = JSClassCreate(JSNdefRecord::getClassInfo());
+
+void JSNdefRecord::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSNdefRecord::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+NdefRecordPtr JSNdefRecord::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    NdefRecordHolder* priv = static_cast<NdefRecordHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw TypeMismatchException("Type mismatch");
+    }
+    if (!(priv->ptr)){
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+void JSNdefRecord::setPrivateObject(JSObjectRef object, NdefRecordPtr data)
+{
+    LOGD("Entered");
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    NdefRecordHolder* priv = static_cast<NdefRecordHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new(std::nothrow) NdefRecordHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in NdefRecord");
+            throw UnknownException(
+                    "Failed to set NdefRecord private data");
+        }
+    }
+}
+
+JSObjectRef JSNdefRecord::makeJSObject(JSContextRef context, NdefRecordPtr native)
+{
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    NdefRecordHolder* priv = new(std::nothrow) NdefRecordHolder();
+    if (!priv) {
+        LOGE("Memory allocation error");
+        throw UnknownException("Memory allocation error");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (!obj) {
+        LOGE("Object creation failed");
+        delete priv;
+        throw UnknownException("Object creation failed");
+    }
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSNdefRecord::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef js_obj_ref = JSObjectMake(context, getClassRef(), NULL);
+    JSStringRef ctor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, js_obj_ref, ctor_name, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctor_name);
+
+    try {
+        NdefRecordPtr priv;
+        if (validator.isOmitted(0) || validator.isNull(0) || validator.isUndefined(0)) {
+            LOGE("Argument count is 0.");
+            throw TypeMismatchException("Argument count is 0.");
+        }
+
+        if(JSIsArrayValue(context, arguments[0])) {
+            JSObjectRef raw_data = validator.toArrayObject(0);
+
+            size_t size = JSGetArrayLength(context, raw_data);
+            if (0 == size) {
+                priv = NdefRecordPtr(new (std::nothrow) NdefRecord());
+            } else {
+                unsigned char *buffer = new unsigned char[size];
+                for(size_t i = 0; i < size; ++i) {
+                    JSValueRef element = JSGetArrayElement(context, raw_data, i);
+                    buffer[i] = static_cast<unsigned char>(JSUtil::JSValueToByte(context, element));
+                }
+                priv = NdefRecordPtr(new (std::nothrow) NdefRecord(buffer, size));
+                delete buffer;
+            }
+        } else {
+            short tnf = static_cast<short>(validator.toLong(0));
+
+            JSObjectRef type_attr = validator.toArrayObject(1);
+            UCharVector type = JSUtil::JSArrayToType_<unsigned char>(
+                context, type_attr, JSUtil::JSValueToOctet);
+
+            JSObjectRef payload_attr = validator.toArrayObject(2);
+            UCharVector payload = JSUtil::JSArrayToType_<unsigned char>(
+                context, payload_attr, JSUtil::JSValueToOctet);
+
+            JSObjectRef id_attr = validator.toArrayObject(3, true);
+            UCharVector id = JSUtil::JSArrayToType_<unsigned char>(
+                context, id_attr, JSUtil::JSValueToOctet);
+
+            priv = NdefRecordPtr(new (std::nothrow) NdefRecord(tnf, type, payload, id));
+        }
+        setPrivateObject(js_obj_ref, priv);
+    } catch (const BasePlatformException &error) {
+        LOGE("constructor failed: name: %s, msg: %s",
+                error.getName().c_str(), error.getMessage().c_str());
+    } catch (...) {
+        LOGE("constructor failed");
+    }
+
+    return js_obj_ref;
+}
+
+JSValueRef JSNdefRecord::getTnf(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        NdefRecordPtr priv = JSNdefRecord::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context,static_cast<long int>(priv->getTnf()));
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("tnf get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...){
+        LOGE("Unsupported error while getting tnf");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNdefRecord::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        NdefRecordPtr priv = JSNdefRecord::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef_(context,priv->getType());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("type get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...){
+        LOGE("Unsupported error while getting type");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNdefRecord::getId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        NdefRecordPtr priv = JSNdefRecord::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef_(context,priv->getId());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("id get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...){
+        LOGE("Unsupported error while getting id");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNdefRecord::getPayload(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try{
+        NdefRecordPtr priv = JSNdefRecord::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef_(context,priv->getPayload());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("payload get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...){
+        LOGE("Unsupported error while getting payload");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+
+} //NFC
+} //DeviceAPI
+
diff --git a/src/NFC/JSNdefRecord.h b/src/NFC/JSNdefRecord.h
new file mode 100755 (executable)
index 0000000..ee77688
--- /dev/null
@@ -0,0 +1,99 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#ifndef __TIZEN_NFC_JS_NDEFRECORD_H_
+#define __TIZEN_NFC_JS_NDEFRECORD_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "NdefRecord.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class JSNdefRecord
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static NdefRecordPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, NdefRecordPtr data);
+
+    static JSObjectRef makeJSObject(JSContextRef context, NdefRecordPtr native);
+
+    static JSObjectRef constructor(JSContextRef ctx,
+                JSObjectRef constructor,
+                size_t argumentCount,
+                const JSValueRef arguments[],
+                JSValueRef* exception);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Getters for properties
+     */
+    static JSValueRef getTnf(JSContextRef context,
+                JSObjectRef object,
+                JSStringRef propertyName,
+                JSValueRef* exception);
+
+    static JSValueRef getType(JSContextRef context,
+                JSObjectRef object,
+                JSStringRef propertyName,
+                JSValueRef* exception);
+
+    static JSValueRef getId(JSContextRef context,
+                JSObjectRef object,
+                JSStringRef propertyName,
+                JSValueRef* exception);
+
+    static JSValueRef getPayload(JSContextRef context,
+                JSObjectRef object,
+                JSStringRef propertyName,
+                JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared value property.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //NFC
+} //DeviceAPI
+
+#endif // __TIZEN_NFC_JS_NDEFRECORD_H_
diff --git a/src/NFC/JSNdefRecordMedia.cpp b/src/NFC/JSNdefRecordMedia.cpp
new file mode 100755 (executable)
index 0000000..7c31d11
--- /dev/null
@@ -0,0 +1,231 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSNdefRecordMedia.h"
+
+#include <JSUtil.h>
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <string>
+#include <Export.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace NFC {
+
+struct NdefRecordMediaHolder {
+    NdefRecordMediaPtr ptr;
+};
+
+namespace {
+const char* TIZEN_NDEFRECORD_MEDIA = "NDEFRecordMedia";
+
+const char* TIZEN_NDEFRECORD_MEDIA_MIMETYPE = "mimeType";
+}
+
+JSClassDefinition JSNdefRecordMedia::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_NDEFRECORD_MEDIA,
+    JSNdefRecord::getClassRef(),
+    m_property,
+    NULL,
+    initialize,
+    finalize,
+    NULL, // hasProperty,
+    NULL, // getProperty
+    NULL, // setProperty,
+    NULL, // deleteProperty,
+    NULL, // getPropertyNames,
+    NULL, // callAsFunction,
+    NULL, // callAsConstructor,
+    NULL, // hasInstance
+    NULL, // convertToType
+};
+
+JSStaticValue JSNdefRecordMedia::m_property[] =
+{
+    {TIZEN_NDEFRECORD_MEDIA_MIMETYPE, getMimeType, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSNdefRecordMedia::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNdefRecordMedia::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSNdefRecordMedia::m_jsClassRef = JSClassCreate(JSNdefRecordMedia::getClassInfo());
+
+void JSNdefRecordMedia::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSNdefRecordMedia::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    NdefRecordMediaHolder *priv = static_cast<NdefRecordMediaHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+NdefRecordMediaPtr JSNdefRecordMedia::getPrivateObject(JSContextRef context,
+        JSValueRef value){
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    NdefRecordMediaHolder* priv = static_cast<NdefRecordMediaHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw TypeMismatchException("Type mismatch");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+void JSNdefRecordMedia::setPrivateObject(JSObjectRef object,
+        NdefRecordMediaPtr data){
+    LOGD("Entered");
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    NdefRecordMediaHolder* priv = static_cast<NdefRecordMediaHolder*>(
+                JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new (std::nothrow) NdefRecordMediaHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set NdefRecordMedia private data");
+            throw UnknownException("Failed to set NdefRecordMedia private data");
+        }
+    }
+}
+
+JSObjectRef JSNdefRecordMedia::makeJSObject(JSContextRef context,
+        NdefRecordMediaPtr native){
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    NdefRecordMediaHolder* priv = new (std::nothrow) NdefRecordMediaHolder();
+    if (!priv) {
+        LOGE("Memory allocation error");
+        throw UnknownException("Memory allocation error");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (!obj) {
+        LOGE("Object creation failed");
+        delete priv;
+        throw UnknownException("Object creation failed");
+    }
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSNdefRecordMedia::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, obj, ctor_name, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctor_name);
+
+    try {
+        std::string mime_type = validator.toString(0);
+        JSObjectRef data_attr = validator.toArrayObject(1);
+        UCharVector data = JSUtil::JSArrayToType_<unsigned char>(
+                context, data_attr, JSUtil::JSValueToOctet);
+
+        NdefRecordMediaPtr priv = NdefRecordMediaPtr(new (std::nothrow)
+                NdefRecordMedia(mime_type, data));
+        setPrivateObject(obj, priv);
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("constructor failed name:%s, msg: %s", e.getName().c_str(),
+                e.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("constructor failed");
+    }
+    return obj;
+}
+
+JSValueRef JSNdefRecordMedia::getMimeType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        NdefRecordMediaPtr priv = JSNdefRecordMedia::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getMimeType());
+    }
+    catch (const BasePlatformException &e) {
+        LOGE("mimeType get failed: %s : %s", (e.getName()).c_str(), (e.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unsupported error while getting mimeType");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} //NFC
+} //DeviceAPI
+
diff --git a/src/NFC/JSNdefRecordMedia.h b/src/NFC/JSNdefRecordMedia.h
new file mode 100755 (executable)
index 0000000..6f17894
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#ifndef __TIZEN_NFC_JS_NDEFRECORD_MEDIA_H_
+#define __TIZEN_NFC_JS_NDEFRECORD_MEDIA_H_
+
+#include "JSNdefRecord.h"
+#include "NdefRecordMedia.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class JSNdefRecordMedia
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static NdefRecordMediaPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, NdefRecordMediaPtr data);
+
+    static JSObjectRef makeJSObject(JSContextRef context, NdefRecordMediaPtr native);
+
+    static JSObjectRef constructor(JSContextRef ctx,
+                JSObjectRef constructor,
+                size_t argumentCount,
+                const JSValueRef arguments[],
+                JSValueRef* exception);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * The callback invoked when getting a property's value.
+     */
+    static JSValueRef getMimeType(JSContextRef context,
+                JSObjectRef object,
+                JSStringRef propertyName,
+                JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared value property.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //NFC
+} //DeviceAPI
+
+#endif // __TIZEN_NFC_JS_NDEFRECORD_MEDIA_H_
diff --git a/src/NFC/JSNdefRecordText.cpp b/src/NFC/JSNdefRecordText.cpp
new file mode 100755 (executable)
index 0000000..2dcce99
--- /dev/null
@@ -0,0 +1,280 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSNdefRecordText.h"
+#include "NdefRecordText.h"
+#include "plugin_config.h"
+
+#include <JSUtil.h>
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <Export.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace NFC {
+
+struct NdefRecordTextHolder {
+    NdefRecordTextPtr ptr;
+};
+
+const char* TIZEN_NDEFRECORD_TEXT = "NDEFRecordText";
+const char* TIZEN_NDEFRECORD_TEXT_TEXT = "text";
+const char* TIZEN_NDEFRECORD_TEXT_LANGCODE = "languageCode";
+const char* TIZEN_NDEFRECORD_TEXT_ENCODING = "encoding";
+
+JSClassDefinition JSNdefRecordText::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_NDEFRECORD_TEXT,
+    JSNdefRecord::getClassRef(),
+    m_property,
+    NULL,
+    initialize,
+    finalize,
+    NULL, //HasProperty,
+    NULL,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL, //ConvertToType
+};
+
+JSStaticValue JSNdefRecordText::m_property[] =
+{
+    {TIZEN_NDEFRECORD_TEXT_TEXT,  getText, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NDEFRECORD_TEXT_LANGCODE,  getLanguageCode, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    {TIZEN_NDEFRECORD_TEXT_ENCODING,  getEncoding, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSNdefRecordText::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNdefRecordText::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSNdefRecordText::m_jsClassRef = JSClassCreate(JSNdefRecordText::getClassInfo());
+
+void JSNdefRecordText::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSNdefRecordText::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    NdefRecordTextHolder *priv = static_cast<NdefRecordTextHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+NdefRecordTextPtr JSNdefRecordText::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    LOGD("Entered");
+
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    NdefRecordTextHolder* priv = static_cast<NdefRecordTextHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw TypeMismatchException("Type mismatch");
+    }
+    if (!(priv->ptr)){
+        LOGE("Priv ptr is null");
+        throw UnknownException("Priv ptr is null");
+    }
+    return priv->ptr;
+}
+
+void JSNdefRecordText::setPrivateObject(JSObjectRef object, NdefRecordTextPtr data)
+{
+    LOGD("Entered");
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+    NdefRecordTextHolder* priv = static_cast<NdefRecordTextHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new(std::nothrow) NdefRecordTextHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in NdefRecordText");
+            throw UnknownException("Failed to set NdefRecordText private data");
+        }
+    }
+}
+
+JSObjectRef JSNdefRecordText::makeJSObject(JSContextRef context, NdefRecordTextPtr data)
+{
+    LOGD("Entered");
+    if (!data) {
+        LOGE("Null RecordText pointer given");
+        throw UnknownException("Null RecordText pointer given");
+    }
+
+    NdefRecordTextHolder* priv = new(std::nothrow) NdefRecordTextHolder();
+    if (!priv) {
+        LOGE("Memory allocation error");
+        throw UnknownException("Memory allocation error");
+    }
+    priv->ptr = data;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if (!obj) {
+        delete priv;
+        priv = NULL;
+        LOGE("Object creation failed");
+        throw UnknownException("Object creation failed");
+    }
+
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSNdefRecordText::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef js_obj_ref = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, js_obj_ref, ctor_name, constructor,
+            kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctor_name);
+
+    try {
+        const std::string text = validator.toString(0);
+        const std::string language_code = validator.toString(1);
+        std::string encoding = validator.toString(2, true);
+        nfc_encode_type_e encode_type = NdefRecordText::convertToNfcEncodeUTF(encoding);
+
+        NdefRecordTextPtr priv = NdefRecordTextPtr(new (std::nothrow)
+                NdefRecordText(text, language_code, encode_type));
+        JSNdefRecordText::setPrivateObject(js_obj_ref, priv);
+    } catch (const BasePlatformException &err) {
+        LOGE("Constructor failed: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("Constructor failed");
+    }
+
+    return js_obj_ref;
+}
+
+JSValueRef JSNdefRecordText::getText(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        NdefRecordTextPtr priv = JSNdefRecordText::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getText());
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Text get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting text.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNdefRecordText::getLanguageCode(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        NdefRecordTextPtr priv = JSNdefRecordText::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getLanguageCode());
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Language code get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting language code.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNdefRecordText::getEncoding(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        NdefRecordTextPtr priv = JSNdefRecordText::getPrivateObject(context, object);
+        std::string encoding = priv->convertToTextNfcEncodeUTF(priv->getEncoding());
+        return JSUtil::toJSValueRef(context, encoding);
+    }
+    catch(const BasePlatformException &err) {
+        LOGE("Encoding get failed: %s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch(...) {
+        LOGE("Unsupported error while getting encoding.");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} //NFC
+} //DeviceAPI
diff --git a/src/NFC/JSNdefRecordText.h b/src/NFC/JSNdefRecordText.h
new file mode 100755 (executable)
index 0000000..5af18d8
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#ifndef __TIZEN_NFC_JS_NDEFRECORD_TEXT_H_
+#define __TIZEN_NFC_JS_NDEFRECORD_TEXT_H_
+
+#include "JSNdefRecord.h"
+#include "NdefRecordText.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class JSNdefRecordText
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static NdefRecordTextPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, NdefRecordTextPtr data);
+
+    static JSObjectRef makeJSObject(JSContextRef context, NdefRecordTextPtr data);
+
+    static JSObjectRef constructor(JSContextRef ctx,
+                JSObjectRef constructor,
+                size_t argumentCount,
+                const JSValueRef arguments[],
+                JSValueRef* exception);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * The callback invoked when getting a property's value.
+     */
+    static JSValueRef getText(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getLanguageCode(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getEncoding(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared value property.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //NFC
+} //DeviceAPI
+
+#endif // __TIZEN_NFC_JS_NDEFRECORD_TEXT_H_
diff --git a/src/NFC/JSNdefRecordURI.cpp b/src/NFC/JSNdefRecordURI.cpp
new file mode 100755 (executable)
index 0000000..0fc7a9d
--- /dev/null
@@ -0,0 +1,232 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSNdefRecordURI.h"
+#include "NdefRecordURI.h"
+#include "JSUtil.h"
+
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <Export.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace NFC {
+
+namespace {
+const char* TIZEN_NDEFRECORD_URI = "NDEFRecordURI";
+
+const char* TIZEN_NDEFRECORD_URI_URI = "uri";
+}
+
+JSClassDefinition JSNdefRecordURI::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    TIZEN_NDEFRECORD_URI,
+    JSNdefRecord::getClassRef(),
+    m_property,
+    NULL,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //callAsFunction,
+    NULL, //callAsConstructor,
+    NULL, //hasInstance
+    NULL, //convertToType
+};
+
+JSStaticValue JSNdefRecordURI::m_property[] =
+{
+    {TIZEN_NDEFRECORD_URI_URI,  getUri, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+    { 0, 0, 0, 0 }
+};
+
+const JSClassRef DLL_EXPORT JSNdefRecordURI::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNdefRecordURI::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSNdefRecordURI::m_jsClassRef = JSClassCreate(JSNdefRecordURI::getClassInfo());
+
+void JSNdefRecordURI::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSNdefRecordURI::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    NdefRecordURIHolder* priv = static_cast<NdefRecordURIHolder*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+NdefRecordURIPtr JSNdefRecordURI::getPrivateObject(
+        JSContextRef context,
+        JSValueRef value)
+{
+    if(!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Object type do not match");
+        throw TypeMismatchException("Object type is not NdefRecordURI");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    NdefRecordURIHolder* priv = static_cast<NdefRecordURIHolder*>(
+            JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("NULL private data");
+        throw TypeMismatchException("Type mismatch");
+    }
+    if (!(priv->ptr)) {
+        LOGE("NULL shared pointer in private data");
+        throw UnknownException("Private data is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSNdefRecordURI::setPrivateObject(JSObjectRef object,
+        NdefRecordURIPtr data)
+{
+    if (!data) {
+        LOGE("NULL shared pointer given to set as private data");
+        throw UnknownException("NULL private data given");
+    }
+
+    NdefRecordURIHolder* priv = static_cast<NdefRecordURIHolder*>(
+            JSObjectGetPrivate(object));
+    if (priv) {
+        priv->ptr = data;
+    }
+    else {
+        priv = new(std::nothrow) NdefRecordURIHolder();
+        if (!priv) {
+            LOGE("Memory allocation failure");
+            throw UnknownException("Failed to allocate memory");
+        }
+        priv->ptr = data;
+        if(!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+            priv = NULL;
+            LOGE("Failed to set private data in NdefRecordURI");
+            throw UnknownException("Failed to set NdefRecordURI private data");
+        }
+    }
+}
+
+JSObjectRef JSNdefRecordURI::makeJSObject(JSContextRef context,
+        NdefRecordURIPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to attachment given");
+        throw UnknownException("NULL pointer to attachment given");
+    }
+
+    NdefRecordURIHolder* priv = new(std::nothrow) NdefRecordURIHolder();
+    if (!priv) {
+        LOGW("Failed to allocate memory for NdefRecordURIHolder");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    if(!obj) {
+        LOGE("Object creation failed");
+        delete priv;
+        priv = NULL;
+        throw UnknownException("Object creation failed");
+    }
+
+    return obj;
+}
+
+JSObjectRef DLL_EXPORT JSNdefRecordURI::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef js_obj_ref = JSObjectMake(context, JSNdefRecordURI::getClassRef(),NULL);
+
+    JSStringRef ctor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, js_obj_ref, ctor_name, constructor,
+            kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete |
+            kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctor_name);
+
+    try {
+        std::string uri = validator.toString(0);
+
+        auto priv = NdefRecordURIPtr(new(std::nothrow) NdefRecordURI(uri));
+
+        JSNdefRecordURI::setPrivateObject(js_obj_ref, priv);
+    }
+    catch (BasePlatformException &err) {
+        LOGE("NdefRecordURI creation failed: %s", err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("NdefRecordURI creation failed: Unknown exception.");
+    }
+
+    return js_obj_ref;
+}
+
+JSValueRef JSNdefRecordURI::getUri(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        NdefRecordURIPtr priv = JSNdefRecordURI::getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getURI());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getURI - unknown exception.");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} //NFC
+} //DeviceAPI
+
diff --git a/src/NFC/JSNdefRecordURI.h b/src/NFC/JSNdefRecordURI.h
new file mode 100755 (executable)
index 0000000..f1ec85e
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#ifndef __TIZEN_NFC_JS_NDEFRECORD_URI_H_
+#define __TIZEN_NFC_JS_NDEFRECORD_URI_H_
+
+#include "JSNdefRecord.h"
+#include "NdefRecordURI.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class JSNdefRecordURI
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef ctx,
+                JSObjectRef constructor,
+                size_t argumentCount,
+                const JSValueRef arguments[],
+                JSValueRef* exception);
+
+    static NdefRecordURIPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, NdefRecordURIPtr data);
+
+    static JSObjectRef makeJSObject(JSContextRef context, NdefRecordURIPtr attptr);
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * The callback invoked when getting a property's value.
+     */
+    static JSValueRef getUri(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared value property.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+};
+
+} //NFC
+} //DeviceAPI
+
+#endif /* __TIZEN_NFC_JS_NDEFRECORD_URI_H_ */
diff --git a/src/NFC/JSNdefRecordVector.cpp b/src/NFC/JSNdefRecordVector.cpp
new file mode 100644 (file)
index 0000000..2a08b98
--- /dev/null
@@ -0,0 +1,97 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include "JSNdefRecord.h"
+#include "JSNdefRecordMedia.h"
+#include "JSNdefRecordText.h"
+#include "JSNdefRecordURI.h"
+#include "JSNdefRecordVector.h"
+#include "NdefRecordMedia.h"
+#include "NdefRecordText.h"
+#include "NdefRecordURI.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+JSValueRef JSNdefRecordVector::makeJSValue(JSContextRef ctx, NdefRecordPtr ptr)
+{
+    switch(ptr->getRecordType()) {
+        case NFC_RECORD_TEXT:
+            return JSNdefRecordText::makeJSObject(ctx,
+                    std::static_pointer_cast<NdefRecordText>(ptr));
+            break;
+        case NFC_RECORD_URI:
+            return JSNdefRecordURI::makeJSObject(ctx,
+                    std::static_pointer_cast<NdefRecordURI>(ptr));
+            break;
+        case NFC_RECORD_MEDIA:
+            return JSNdefRecordMedia::makeJSObject(ctx,
+                    std::static_pointer_cast<NdefRecordMedia>(ptr));
+            break;
+        default:
+            return JSNdefRecord::makeJSObject(ctx, ptr);
+    }
+}
+
+NdefRecordPtr JSNdefRecordVector::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    LOGD("Entered");
+    if (JSValueIsObjectOfClass(context, value, JSNdefRecordURI::getClassRef())) {
+        // URI support
+        return std::static_pointer_cast<NdefRecord>(
+                JSNdefRecordURI::getPrivateObject(context, value));
+    }
+    if (JSValueIsObjectOfClass(context, value, JSNdefRecordText::getClassRef())) {
+        // Text support
+        return std::static_pointer_cast<NdefRecord>(
+                JSNdefRecordText::getPrivateObject(context, value));
+    }
+    if (JSValueIsObjectOfClass(context, value, JSNdefRecordMedia::getClassRef())) {
+        // Media support
+        return std::static_pointer_cast<NdefRecord>(
+                JSNdefRecordMedia::getPrivateObject(context, value));
+    }
+    if (JSValueIsObjectOfClass(context, value, JSNdefRecord::getClassRef())) {
+        // Base record
+        return JSNdefRecord::getPrivateObject(context, value);
+    }
+
+    LOGE("Given object does not match any of known objects.");
+    throw Common::TypeMismatchException("Type mismatch");
+}
+
+
+JSNdefRecordVector::JSNdefRecordVector(const std::vector<NdefRecordPtr>& vec):
+        Common::JSVector<NdefRecordPtr>(vec, getPrivateObject, makeJSValue)
+{
+}
+
+JSNdefRecordVector::JSNdefRecordVector():
+        Common::JSVector<NdefRecordPtr>(getPrivateObject, makeJSValue)
+{
+}
+
+JSNdefRecordVector& JSNdefRecordVector::operator=(const std::vector<NdefRecordPtr>& list )
+{
+    Common::JSVector<NdefRecordPtr>::operator=(list);
+    return *this;
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/JSNdefRecordVector.h b/src/NFC/JSNdefRecordVector.h
new file mode 100644 (file)
index 0000000..16a70b7
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NDEFRECORD_VECTOR_H_
+#define __TIZEN_NFC_NDEFRECORD_VECTOR_H_
+
+#include <memory>
+#include <vector>
+#include <JSVector.h>
+#include "NdefRecord.h"
+
+
+namespace DeviceAPI {
+namespace NFC {
+
+class JSNdefRecordVector : public Common::JSVector<NdefRecordPtr> {
+        static JSValueRef makeJSValue(JSContextRef ctx, NdefRecordPtr ptr);
+        static NdefRecordPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    public:
+        JSNdefRecordVector(const std::vector<NdefRecordPtr>& vec);
+        JSNdefRecordVector();
+        JSNdefRecordVector& operator=( const std::vector<NdefRecordPtr>& list );
+};
+
+} // NFC
+} // DeviceAPI
+
+
+#endif // __TIZEN_NFC_NDEFRECORD_VECTOR_H_
diff --git a/src/NFC/NFCAdapter.cpp b/src/NFC/NFCAdapter.cpp
new file mode 100755 (executable)
index 0000000..85a9d33
--- /dev/null
@@ -0,0 +1,761 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NFCAdapter.h"
+#include "NFCUtil.h"
+
+#include <nfc.h>
+#include <glib.h>
+#include <Logger.h>
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+namespace {
+
+    static gboolean setPoweredCompleteCB(void * data)
+    {
+        auto *callback = static_cast<AdapterCallbackData*>(data);
+        if (NULL == callback) {
+            LOGE("Callback is null");
+            return false;
+        }
+
+        JSContextRef context = callback->getContext();
+        if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            delete callback;
+            callback = NULL;
+            return false;
+        }
+
+        try {
+            if (!callback->isError()) {
+                callback->callSuccessCallback();
+            } else {
+                JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+                callback->callErrorCallback(errobj);
+            }
+        }
+        catch (const Common::BasePlatformException &err) {
+            LOGE("Error while calling setPowered callback: %s (%s)",
+                    (err.getName()).c_str(), (err.getMessage()).c_str());
+        }
+        catch(...) {
+            LOGE("Unknown error when calling setPowered callback.");
+        }
+
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    static void se_event_callback(nfc_se_event_e event, void *user_data)
+    {
+        LOGD("Entered");
+
+        NFCAdapter *adapter = reinterpret_cast<NFCAdapter *>(user_data);
+        nfc_se_type_e type;
+        nfc_se_card_emulation_mode_type_e mode;
+        switch (event) {
+            case NFC_SE_EVENT_SE_TYPE_CHANGED:
+                type = adapter->getActiveSecureElement();
+                adapter->broadcastActiveSecureElementEvent(type);
+                break;
+            case NFC_SE_EVENT_CARD_EMULATION_CHANGED:
+                mode = adapter->getCardEmulationMode();
+                adapter->broadcastCardEmulationEvent(mode);
+                break;
+            default:
+                LOGD("se_event_occured: %d", event);
+                break;
+        }
+    }
+
+    static void transaction_event_callback(nfc_se_type_e type,
+                                           unsigned char *_aid,
+                                           int aid_size,
+                                           unsigned char *param,
+                                           int param_size,
+                                           void *user_data)
+    {
+        LOGD("Entered");
+
+        NFCAdapter *adapter = reinterpret_cast<NFCAdapter *>(user_data);
+        std::vector<unsigned char> aid(_aid, _aid + aid_size);
+        std::vector<unsigned char> data(param, param + param_size);
+
+        adapter->broadcastTransactionEvent(type, aid, data);
+    }
+}
+NFCAdapter::NFCAdapter() :
+        SecurityAccessor(),
+        m_card_se_callbacks_counter(0),
+        m_transaction_callbacks_counter(0),
+        m_active_se_callbacks_counter(0)
+{
+    LOGD("Entered");
+    if(!nfc_manager_is_supported()) {
+        LOGE("Not Support");
+        throw Common::NotSupportedException("Not Support");
+    }
+    m_peer_callback = NULL;
+    m_tag_callback = NULL;
+
+    for (int i = (int)NFC_SE_TYPE_ESE; i == (int)NFC_SE_TYPE_UICC; i++) {
+        TransactionEventCallbackMap cbMap;
+        nfc_se_type_e e = (nfc_se_type_e)i;
+        std::pair<nfc_se_type_e, TransactionEventCallbackMap> row(e, cbMap);
+        m_transaction_callbacks.insert(row);
+    }
+}
+
+NFCAdapter::~NFCAdapter()
+{
+    LOGD("Entered");
+    removePeerCallback();
+    removeTagCallback();
+
+    m_card_se_callbacks.clear();
+    for (int i = (int)NFC_SE_TYPE_DISABLE; i == (int)NFC_SE_TYPE_UICC; i++) {
+        nfc_se_type_e e = (nfc_se_type_e)i;
+        TransactionEventCallbackMap &cbMap = m_transaction_callbacks.find(e)->second;
+
+        cbMap.clear();
+        nfc_manager_unset_se_transaction_event_cb(e);
+    }
+    m_active_se_callbacks.clear();
+    nfc_manager_unset_se_event_cb();
+}
+
+bool NFCAdapter::getPowered() const
+{
+    LOGD("Entered");
+    return nfc_manager_is_activated();
+}
+
+nfc_se_card_emulation_mode_type_e NFCAdapter::getCardEmulationMode() const
+{
+    LOGD("Entered");
+
+    nfc_se_card_emulation_mode_type_e mode;
+    int ret = nfc_se_get_card_emulation_mode(&mode);
+    if (NFC_ERROR_NONE != ret) {
+        LOGE("getCardEmulationMode failed: %d, %s", ret,
+            NFCUtil::getNFCErrorMessage(ret).c_str());
+        NFCUtil::throwNFCException(ret, NFCUtil::getNFCErrorString(ret).c_str());
+    }
+    return mode;
+}
+
+void NFCAdapter::setCardEmulationMode(nfc_se_card_emulation_mode_type_e mode)
+{
+    LOGD("Entered");
+
+    nfc_se_card_emulation_mode_type_e current_mode = getCardEmulationMode();
+    if (mode == current_mode) {
+        LOGD("cardEmulationMode is already set to %d", mode);
+        return;
+    }
+
+    int ret = NFC_ERROR_NONE;
+    switch (mode) {
+        case NFC_SE_CARD_EMULATION_MODE_OFF:
+            ret = nfc_se_disable_card_emulation();
+            break;
+        case NFC_SE_CARD_EMULATION_MODE_ON:
+            ret = nfc_se_enable_card_emulation();
+            break;
+        default:
+            LOGE("card emulation mode is invalid: %x", mode);
+            throw InvalidValuesException("card emulation mode is invalid");
+    }
+
+    if (NFC_ERROR_NONE != ret) {
+        LOGE("setCardEmulationMode failed: %d, %s", ret,
+            NFCUtil::getNFCErrorMessage(ret).c_str());
+        NFCUtil::throwNFCException(ret, NFCUtil::getNFCErrorMessage(ret).c_str());
+    }
+}
+
+nfc_se_type_e NFCAdapter::getActiveSecureElement() const
+{
+    LOGD("Entered");
+
+    nfc_se_type_e type;
+    int ret = nfc_manager_get_se_type(&type);
+    if (NFC_ERROR_NONE != ret) {
+        LOGE("getActiveSecureElement failed: %d, %s", ret,
+            NFCUtil::getNFCErrorMessage(ret).c_str());
+        NFCUtil::throwNFCException(ret, NFCUtil::getNFCErrorMessage(ret).c_str());
+    }
+    return type;
+}
+
+void NFCAdapter::setActiveSecureElement(nfc_se_type_e type)
+{
+    LOGD("Entered");
+
+    nfc_se_type_e current_type = getActiveSecureElement();
+    if (type == current_type) {
+        LOGD("activeSecureElement is already set to %d", type);
+        return;
+    }
+
+    int ret = nfc_manager_set_se_type(type);
+    if (NFC_ERROR_NONE != ret) {
+        LOGE("setActiveSecureElement failed: %d, %s", ret,
+            NFCUtil::getNFCErrorMessage(ret).c_str());
+        NFCUtil::throwNFCException(ret, NFCUtil::getNFCErrorMessage(ret).c_str());
+    }
+}
+
+void NFCAdapter::setPeerCallback(NFCPeerDetectCallback *callback)
+{
+    LOGD("Entered");
+    m_peer_callback = callback;
+}
+
+NFCPeerDetectCallback* NFCAdapter::getPeerCallback() const
+{
+    LOGD("Entered");
+    return m_peer_callback;
+}
+
+void NFCAdapter::removePeerCallback()
+{
+    LOGD("Entered");
+    delete m_peer_callback;
+    m_peer_callback = NULL;
+}
+
+void NFCAdapter::setTagCallback(NFCTagDetectCallback *callback)
+{
+    LOGD("Entered");
+    m_tag_callback = callback;
+}
+
+NFCTagDetectCallback* NFCAdapter::getTagCallback() const
+{
+    LOGD("Entered");
+    return m_tag_callback;
+}
+
+void NFCAdapter::removeTagCallback()
+{
+    LOGD("Entered");
+    delete m_tag_callback;
+    m_tag_callback = NULL;
+}
+#ifndef APP_CONTROL_SETTING_SUPPORT
+static void NFCSetActivationCompletedCallback(nfc_error_e error, void *user_data)
+{
+    LOGD("Entered");
+    if (NULL == user_data) {
+        LOGE("Callback is null");
+        return;
+    }
+
+    auto callback = static_cast<AdapterCallbackData*>(user_data);
+
+    if (NFC_ERROR_NONE != error) {
+        callback->setError(NFCUtil::getNFCErrorString(error),
+            NFCUtil::getNFCErrorMessage(error));
+    }
+
+    if (!g_idle_add(setPoweredCompleteCB, static_cast<void *>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+#endif
+void NFCAdapter::setPowered(AdapterCallbackData *callback)
+{
+    LOGD("Entered");
+    if (!callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("No data add");
+    }
+
+    if (getPowered() == callback->getPoweredState()) {
+        if (!g_idle_add(setPoweredCompleteCB, static_cast<void *>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+        return;
+    }
+
+    int ret = 0;
+#ifdef APP_CONTROL_SETTING_SUPPORT
+    app_control_h service = NULL;
+    ret = app_control_create(&service);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("app_control_create failed: %d", ret);
+        throw UnknownException("app_control_create failed");
+    }
+
+    ret = app_control_set_operation(service,
+        "http://tizen.org/appcontrol/operation/setting/nfc");
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("app_control_set_operation failed: %d", ret);
+        throw UnknownException("app_control_set_operation failed");
+    }
+
+    ret = app_control_add_extra_data(service, "type", "nfc");
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("app_control_add_extra_data failed: %d", ret);
+        throw UnknownException("app_control_add_extra_data failed");
+    }
+
+    ret = app_control_send_launch_request(service, [](app_control_h request,
+        app_control_h reply, app_control_result_e result, void *user_data){
+        AdapterCallbackData* callback =
+            static_cast<AdapterCallbackData *>(user_data);
+        if (!callback) {
+            LOGE("callback is NULL");
+            return;
+        }
+
+        try {
+            if (result == APP_CONTROL_RESULT_SUCCEEDED) {
+                char *type = NULL;
+                int ret = app_control_get_extra_data(reply, "nfc_status",
+                    &type);
+                if (ret != APP_CONTROL_ERROR_NONE) {
+                    LOGE("app_control_get_extra_data failed: %d", ret);
+                    throw UnknownException("app_control_get_extra_data failed");
+                }
+
+                LOGD("app_control result: %s", type);
+            } else {
+                LOGE("NFC enable app control failed : %d", result);
+                throw UnknownException("NFC enable app control failed");
+            }
+        } catch (BasePlatformException &e) {
+            callback->setError(e.getName(), e.getMessage());
+        }
+
+        if (!g_idle_add(setPoweredCompleteCB, static_cast<void *>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    }, static_cast<void *>(callback));
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("app_control_send_launch_request failed: %d", ret);
+        throw UnknownException("app_control_send_operation failed");
+    }
+
+    ret = app_control_destroy(service);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("app_control_destroy failed: %d", ret);
+        throw UnknownException("app_control_destroy failed");
+    }
+
+#else
+    ret = nfc_manager_set_activation(callback->getPoweredState(),
+            NFCSetActivationCompletedCallback, static_cast<void *>(callback));
+    if (NFC_ERROR_NONE != ret) {
+        LOGE("setPowered failed: %d, %s", ret,
+            NFCUtil::getNFCErrorMessage(ret).c_str());
+        NFCUtil::throwNFCException(ret, "setPowered failed.");
+    }
+#endif
+}
+
+static void targetDetectedCallback(nfc_discovered_type_e type, nfc_p2p_target_h target,
+        void *data)
+{
+    LOGD("Entered");
+
+    auto *callback = static_cast<NFCPeerDetectCallback*>(data);
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        return;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    if (NFC_DISCOVERED_TYPE_ATTACHED == type) {
+        NFCPeerPtr peer = NFCPeerPtr(new NFCPeer(target));
+        callback->onAttach(peer);
+    }
+    else {
+        callback->onDetach();
+    }
+
+}
+
+void NFCAdapter::setPeerListener(NFCPeerDetectCallback *callback)
+{
+    LOGD("Entered");
+
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+    int result = nfc_manager_set_p2p_target_discovered_cb (targetDetectedCallback,
+            static_cast<void *>(callback));
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Failed to set callback: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "setPeerListener failed");
+    }
+
+}
+
+void NFCAdapter::unsetPeerListener()
+{
+    LOGD("Entered");
+    nfc_manager_unset_p2p_target_discovered_cb();
+    this->removePeerCallback();
+}
+
+static void tagDetectedCallback(nfc_discovered_type_e type, nfc_tag_h tag, void *data)
+{
+    LOGD("Entered");
+
+    auto *callback = static_cast<NFCTagDetectCallback*>(data);
+
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        return;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    if (NFC_DISCOVERED_TYPE_ATTACHED == type) {
+        nfc_tag_type_e tag_type;
+        int result;
+        result = nfc_tag_get_type(tag, &tag_type);
+        if(NFC_ERROR_NONE != result) {
+            LOGE("nfc_tag_get_type failed: %d, %s", result,
+                NFCUtil::getNFCErrorMessage(result).c_str());
+            return;
+        }
+
+        for (auto it = callback->getFilterValue().begin();
+                it != callback->getFilterValue().end(); ++it) {
+            if (*it == tag_type) {
+                NFCTagPtr new_tag = NFCTagPtr(new NFCTag (tag));
+                callback->onAttach(new_tag);
+                return;
+            }
+        }
+    }
+    else {
+        callback->onDetach();
+    }
+
+}
+
+void NFCAdapter::setTagListener(NFCTagDetectCallback *callback)
+{
+    LOGD("Entered");
+
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+    nfc_manager_set_tag_filter(NFC_TAG_FILTER_ALL_ENABLE);
+    int result = nfc_manager_set_tag_discovered_cb (tagDetectedCallback,
+            static_cast <void *>(callback));
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Failed to set callback: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "setTagListener failed");
+    }
+}
+
+void NFCAdapter::unsetTagListener()
+{
+    LOGD("Entered");
+    nfc_manager_unset_tag_discovered_cb();
+
+    this->removeTagCallback();
+}
+
+long NFCAdapter::addCardEmulationModeChangeListener(
+                                CardEmulationModeChangeCallback *changeCallback)
+{
+    LOGD("Entered");
+
+    std::lock_guard<std::mutex> lock(m_se_callbacks_mutex);
+    long listenerId = ++m_card_se_callbacks_counter;
+    int ret;
+    CardEmulationModeChangeCallbackPtr cb(changeCallback);
+
+    std::pair<long, CardEmulationModeChangeCallbackPtr> row(listenerId, cb);
+    m_card_se_callbacks.insert(row);
+
+    if (m_card_se_callbacks.size() + m_active_se_callbacks.size() == 1) {
+        ret = nfc_manager_set_se_event_cb(se_event_callback, this);
+        if (NFC_ERROR_NONE != ret) {
+            LOGE("addCardEmulationModeChangeListener failed: %d, %s", ret,
+                NFCUtil::getNFCErrorMessage(ret).c_str());
+            NFCUtil::throwNFCException(ret,
+                NFCUtil::getNFCErrorMessage(ret).c_str());
+        }
+    }
+    return listenerId;
+}
+
+void NFCAdapter::removeCardEmulationModeChangeListener(long watchId)
+{
+    LOGD("Entered");
+
+    std::lock_guard<std::mutex> lock(m_se_callbacks_mutex);
+    auto it = m_card_se_callbacks.find(watchId);
+    if (it != m_card_se_callbacks.end()) {
+        m_card_se_callbacks.erase(it);
+
+        if (m_card_se_callbacks.empty() && m_active_se_callbacks.empty()) {
+            nfc_manager_unset_se_event_cb();
+        }
+    }
+}
+
+long NFCAdapter::addTransactionEventListener(nfc_se_type_e type,
+                                        TransactionEventCallback *eventCallback)
+{
+    LOGD("Entered");
+
+    std::lock_guard<std::mutex> lock(m_transaction_callbacks_mutex);
+    long listenerId;
+    int ret = NFC_ERROR_NONE;
+    TransactionEventCallbackPtr cb(eventCallback);
+
+    listenerId = ++m_transaction_callbacks_counter;
+    std::pair<long, TransactionEventCallbackPtr> row(listenerId, cb);
+    TransactionEventCallbackMap &cbMap = m_transaction_callbacks.find(type)->second;
+    cbMap.insert(row);
+
+    if (cbMap.size() == 1) {
+        ret = nfc_manager_set_se_transaction_event_cb(type,
+            transaction_event_callback, this);
+        if (NFC_ERROR_NONE != ret) {
+            LOGE("addTransactionEventListener failed: %d, %s", ret,
+                NFCUtil::getNFCErrorMessage(ret).c_str());
+            NFCUtil::throwNFCException(ret,
+                NFCUtil::getNFCErrorMessage(ret).c_str());
+        }
+    }
+
+    return listenerId;
+}
+
+void NFCAdapter::removeTransactionEventListener(long watchId)
+{
+    LOGD("Entered");
+
+    std::lock_guard<std::mutex> lock(m_transaction_callbacks_mutex);
+
+    for (auto it = m_transaction_callbacks.begin();
+         it != m_transaction_callbacks.end();
+         ++it) {
+
+        auto type = it->first;
+        auto &cbMap = it->second;
+        auto cb = cbMap.find(watchId);
+
+        if (cb != cbMap.end()) {
+            cbMap.erase(cb);
+            if (cbMap.empty()) {
+                 nfc_manager_unset_se_transaction_event_cb(type);
+            }
+            break;
+        }
+    }
+}
+
+long NFCAdapter::addActiveSecureElementChangeListener(
+                              ActiveSecureElementChangeCallback *changeCallback)
+{
+    LOGD("Entered");
+
+    std::lock_guard<std::mutex> lock(m_se_callbacks_mutex);
+    long listenerId = ++m_active_se_callbacks_counter;
+    int ret;
+    ActiveSecureElementChangeCallbackPtr cb(changeCallback);
+
+    std::pair<long, ActiveSecureElementChangeCallbackPtr> row(listenerId, cb);
+    m_active_se_callbacks.insert(row);
+
+    if (m_card_se_callbacks.size() + m_active_se_callbacks.size() == 1) {
+        ret = nfc_manager_set_se_event_cb(se_event_callback, this);
+        if (NFC_ERROR_NONE != ret) {
+            LOGE("addActiveSecureElementChangeListener failed: %d, %s", ret,
+                NFCUtil::getNFCErrorMessage(ret).c_str());
+            NFCUtil::throwNFCException(ret,
+                NFCUtil::getNFCErrorMessage(ret).c_str());
+        }
+    }
+    return listenerId;
+}
+
+void NFCAdapter::removeActiveSecureElementChangeListener(long watchId)
+{
+    LOGD("Entered");
+
+    std::lock_guard<std::mutex> lock(m_se_callbacks_mutex);
+    auto it = m_active_se_callbacks.find(watchId);
+    if (it != m_active_se_callbacks.end()) {
+        m_active_se_callbacks.erase(it);
+
+        if (m_card_se_callbacks.empty() && m_active_se_callbacks.empty()) {
+            nfc_manager_unset_se_event_cb();
+        }
+    }
+}
+
+NdefMessagePtr NFCAdapter::getCachedMessage()
+{
+    LOGD("Entered");
+
+    NdefMessagePtr message;
+    nfc_ndef_message_h message_handle = NULL;
+    int result = nfc_manager_get_cached_message(&message_handle);
+
+    if (NFC_ERROR_INVALID_NDEF_MESSAGE == result || NFC_ERROR_NO_NDEF_MESSAGE == result) {
+        if (NULL != message_handle) {
+            int err = nfc_ndef_message_destroy(message_handle);
+            if (NFC_ERROR_NONE != err) {
+                LOGE("Failed to free cached message: %d, %s", err,
+                    NFCUtil::getNFCErrorMessage(err).c_str());
+            }
+        }
+        return message;
+    }
+
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Failed to get cached message: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Failed to get cached message");
+    }
+
+    message = NdefMessagePtr (new NdefMessage());
+    message->toNdefRecords(message_handle);
+
+    result = nfc_ndef_message_destroy(message_handle);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Failed to destroy message: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+    }
+
+    return message;
+}
+
+void NFCAdapter::setExclusiveModeForTransaction(bool mode)
+{
+    LOGD("Entered");
+
+    int ret = NFC_ERROR_NONE;
+    if (mode) {
+        ret = nfc_manager_enable_transaction_fg_dispatch();
+    } else {
+        ret = nfc_manager_disable_transaction_fg_dispatch();
+    }
+
+    if (NFC_ERROR_NONE != ret) {
+        LOGD("setExclusiveModeForTransaction failed: %d, %s", ret,
+            NFCUtil::getNFCErrorMessage(ret).c_str());
+        NFCUtil::throwNFCException(ret, NFCUtil::getNFCErrorMessage(ret).c_str());
+    }
+}
+
+void NFCAdapter::broadcastCardEmulationEvent(nfc_se_card_emulation_mode_type_e mode)
+{
+    std::lock_guard<std::mutex> lock(m_se_callbacks_mutex);
+
+    for (auto it = m_card_se_callbacks.begin();
+         it != m_card_se_callbacks.end();
+         ++it) {
+        CardEmulationModeChangeCallbackPtr cb = it->second;
+        cb->setCardEmulationMode(mode);
+
+        CardEmulationModeChangeCallbackPtr* data =
+            new CardEmulationModeChangeCallbackPtr(cb);
+        if (!g_idle_add(CardEmulationModeChangeCallback::complete, data)) {
+            LOGE("g_idle_add failed");
+        }
+    }
+}
+
+void NFCAdapter::broadcastTransactionEvent(nfc_se_type_e type,
+                                           std::vector<unsigned char> aid,
+                                           std::vector<unsigned char> data)
+{
+    std::lock_guard<std::mutex> lock(m_transaction_callbacks_mutex);
+    auto it = m_transaction_callbacks.find(type);
+    if (it == m_transaction_callbacks.end()) {
+        LOGE("Invalid type : %d", type);
+        return;
+    }
+
+    auto &cbMap = it->second;
+    for (auto row = cbMap.begin(); row != cbMap.end(); ++row) {
+        TransactionEventCallbackPtr cb = row->second;
+        cb->setAppletId(aid);
+        cb->setData(data);
+
+        TransactionEventCallbackPtr* data =
+            new TransactionEventCallbackPtr(cb);
+        if (!g_idle_add(TransactionEventCallback::complete, data)) {
+            LOGE("g_idle_add failed");
+        }
+    }
+}
+
+void NFCAdapter::broadcastActiveSecureElementEvent(nfc_se_type_e type)
+{
+    std::lock_guard<std::mutex> lock(m_se_callbacks_mutex);
+
+    for (auto it = m_active_se_callbacks.begin();
+         it != m_active_se_callbacks.end();
+         ++it) {
+        ActiveSecureElementChangeCallbackPtr cb = it->second;
+        cb->setActiveSecureElement(type);
+
+        ActiveSecureElementChangeCallbackPtr* data =
+            new ActiveSecureElementChangeCallbackPtr(cb);
+        if (!g_idle_add(ActiveSecureElementChangeCallback::complete, data)) {
+            LOGE("g_idle_add failed");
+        }
+    }
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NFCAdapter.h b/src/NFC/NFCAdapter.h
new file mode 100755 (executable)
index 0000000..8ab30a5
--- /dev/null
@@ -0,0 +1,103 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NFCADAPTER_H_
+#define __TIZEN_NFC_NFCADAPTER_H_
+
+#include "NFCCallbackData.h"
+#include "NFCPeerDetectCallback.h"
+#include "NFCTagDetectCallback.h"
+#include "NdefMessage.h"
+#include <Security.h>
+#include <memory>
+#include <mutex>
+
+#ifdef APP_CONTROL_SETTING_SUPPORT
+#include <app_control.h>
+#endif
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NFCAdapter;
+
+typedef std::shared_ptr<NFCAdapter> NFCAdapterPtr;
+typedef std::map<long, TransactionEventCallbackPtr> TransactionEventCallbackMap;
+
+class NFCAdapter : public Common::SecurityAccessor
+{
+public:
+    NFCAdapter();
+    virtual ~NFCAdapter();
+
+    bool getPowered() const;
+    void setPeerCallback(NFCPeerDetectCallback *callback);
+    nfc_se_card_emulation_mode_type_e getCardEmulationMode() const;
+    void setCardEmulationMode(nfc_se_card_emulation_mode_type_e mode);
+    nfc_se_type_e getActiveSecureElement() const;
+    void setActiveSecureElement(nfc_se_type_e type);
+    NFCPeerDetectCallback* getPeerCallback() const;
+    void removePeerCallback();
+    void setTagCallback(NFCTagDetectCallback *callback);
+    NFCTagDetectCallback* getTagCallback() const;
+    void removeTagCallback();
+
+    void setPowered(AdapterCallbackData *callback);
+    void setPeerListener(NFCPeerDetectCallback *callback);
+    void unsetPeerListener();
+    void setTagListener(NFCTagDetectCallback *callback);
+    void unsetTagListener();
+    long addCardEmulationModeChangeListener(
+        CardEmulationModeChangeCallback *callback);
+    void removeCardEmulationModeChangeListener(long watchId);
+    long addTransactionEventListener(
+        nfc_se_type_e type,
+        TransactionEventCallback *callback);
+    void removeTransactionEventListener(long watchId);
+    long addActiveSecureElementChangeListener(
+        ActiveSecureElementChangeCallback *callback);
+    void removeActiveSecureElementChangeListener(long watchId);
+    NdefMessagePtr getCachedMessage();
+    void setExclusiveModeForTransaction(bool mode);
+
+    void broadcastCardEmulationEvent(nfc_se_card_emulation_mode_type_e mode);
+    void broadcastTransactionEvent(nfc_se_type_e type,
+                                   std::vector<unsigned char> aid,
+                                   std::vector<unsigned char> data);
+    void broadcastActiveSecureElementEvent(nfc_se_type_e type);
+
+private:
+    NFCPeerDetectCallback *m_peer_callback;
+    NFCTagDetectCallback* m_tag_callback;
+
+    long m_card_se_callbacks_counter;
+    long m_transaction_callbacks_counter;
+    long m_active_se_callbacks_counter;
+    std::map<long, CardEmulationModeChangeCallbackPtr> m_card_se_callbacks;
+    std::map<nfc_se_type_e, TransactionEventCallbackMap>
+        m_transaction_callbacks;
+    std::map<long, ActiveSecureElementChangeCallbackPtr>
+        m_active_se_callbacks;
+
+    std::mutex m_se_callbacks_mutex;
+    std::mutex m_transaction_callbacks_mutex;
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_NFCADAPTER_H_
diff --git a/src/NFC/NFCCallbackData.cpp b/src/NFC/NFCCallbackData.cpp
new file mode 100644 (file)
index 0000000..d8609c2
--- /dev/null
@@ -0,0 +1,277 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NFCCallbackData.h"
+
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+OperationCallbackData::OperationCallbackData(JSContextRef global_ctx):
+        Common::CallbackUserData(global_ctx),
+        m_is_error(false)
+{
+}
+
+OperationCallbackData::~OperationCallbackData()
+{
+}
+
+void OperationCallbackData::setError(const std::string &err_name,
+        const std::string &err_message)
+{
+    m_err_name = err_name;
+    m_err_message = err_message;
+    m_is_error = true;
+}
+
+bool OperationCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+std::string OperationCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string OperationCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+AdapterCallbackData::AdapterCallbackData(JSContextRef global_ctx,
+        bool powered_state):
+        OperationCallbackData(global_ctx),
+        m_powered_state(powered_state)
+{
+}
+
+AdapterCallbackData::~AdapterCallbackData()
+{
+}
+
+bool AdapterCallbackData::getPoweredState() const
+{
+    return m_powered_state;
+}
+
+NdefMessageCallbackData::NdefMessageCallbackData(JSContextRef global_ctx):
+        OperationCallbackData(global_ctx)
+{
+}
+
+NdefMessageCallbackData::~NdefMessageCallbackData()
+{
+}
+
+void NdefMessageCallbackData::setMessage(NdefMessagePtr message)
+{
+    m_ndef_message = message;
+}
+
+NdefMessagePtr NdefMessageCallbackData::getMessage() const
+{
+    return m_ndef_message;
+}
+
+ByteArraySuccessCallback::ByteArraySuccessCallback(JSContextRef global_ctx):
+        OperationCallbackData(global_ctx)
+{
+}
+
+ByteArraySuccessCallback::~ByteArraySuccessCallback()
+{
+}
+
+void ByteArraySuccessCallback::setInputData(const UCharVector& byte_array)
+{
+    m_input_data = byte_array;
+}
+
+UCharVector ByteArraySuccessCallback::getInputData() const
+{
+    return m_input_data;
+}
+
+void ByteArraySuccessCallback::setOutputData(const UCharVector& byte_array)
+{
+    m_output_data = byte_array;
+}
+
+UCharVector ByteArraySuccessCallback::getOutputData() const
+{
+    return m_output_data;
+}
+
+CardEmulationModeChangeCallback::CardEmulationModeChangeCallback(
+    JSContextRef global_ctx) : OperationCallbackData(global_ctx)
+{
+}
+
+CardEmulationModeChangeCallback::~CardEmulationModeChangeCallback()
+{
+}
+
+void CardEmulationModeChangeCallback::setCardEmulationMode(
+    nfc_se_card_emulation_mode_type_e mode)
+{
+    m_mode = mode;
+}
+
+nfc_se_card_emulation_mode_type_e CardEmulationModeChangeCallback::getCardEmulationMode() const
+{
+    return m_mode;
+}
+
+gboolean CardEmulationModeChangeCallback::complete(void *data)
+{
+    LOGD("Entered");
+    CardEmulationModeChangeCallbackPtr* holder =
+        static_cast<CardEmulationModeChangeCallbackPtr *>(data);
+    CardEmulationModeChangeCallbackPtr cb = *holder;
+
+    try {
+        JSContextRef context = cb->getContext();
+        if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            throw UnknownException("context was closed");
+        }
+        std::string mode =
+            NFCUtil::toStringCardEmulationMode(cb->getCardEmulationMode());
+        cb->callSuccessCallback(JSUtil::toJSValueRef(context, mode));
+    } catch (BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("Something strange happened");
+    }
+
+    delete holder;
+    return false;
+}
+
+TransactionEventCallback::TransactionEventCallback(
+    JSContextRef global_ctx,
+    nfc_se_type_e type)
+    : OperationCallbackData(global_ctx),
+    m_type(type)
+{
+}
+
+TransactionEventCallback::~TransactionEventCallback()
+{
+}
+
+void TransactionEventCallback::setAppletId(const UCharVector& applet_id)
+{
+    m_applet_id = applet_id;
+}
+
+UCharVector TransactionEventCallback::getAppletId() const
+{
+    return m_applet_id;
+}
+
+void TransactionEventCallback::setData(const UCharVector& data)
+{
+    m_data = data;
+}
+
+UCharVector TransactionEventCallback::getData() const
+{
+    return m_data;
+}
+
+gboolean TransactionEventCallback::complete(void *data)
+{
+    LOGD("Entered");
+    TransactionEventCallbackPtr* holder =
+        static_cast<TransactionEventCallbackPtr *>(data);
+    TransactionEventCallbackPtr cb = *holder;
+
+    try {
+        JSContextRef context = cb->getContext();
+        if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            throw UnknownException("context was closed");
+        }
+
+        JSValueRef args[2];
+        args[0] = JSUtil::toJSValueRef_(context, cb->getAppletId());
+        args[1] = JSUtil::toJSValueRef_(context, cb->getData());
+        cb->callSuccessCallback(2, args);
+    } catch (BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("Something strange happened");
+    }
+
+    delete holder;
+    return false;
+}
+
+ActiveSecureElementChangeCallback::ActiveSecureElementChangeCallback(
+    JSContextRef global_ctx) : OperationCallbackData(global_ctx)
+{
+}
+
+ActiveSecureElementChangeCallback::~ActiveSecureElementChangeCallback()
+{
+}
+
+void ActiveSecureElementChangeCallback::setActiveSecureElement(nfc_se_type_e type)
+{
+    m_type = type;
+}
+
+nfc_se_type_e ActiveSecureElementChangeCallback::getActiveSecureElement() const
+{
+    return m_type;
+}
+
+gboolean ActiveSecureElementChangeCallback::complete(void *data)
+{
+    LOGD("Entered");
+    ActiveSecureElementChangeCallbackPtr* holder =
+        static_cast<ActiveSecureElementChangeCallbackPtr *>(data);
+    ActiveSecureElementChangeCallbackPtr cb = *holder;
+
+    try {
+        JSContextRef context = cb->getContext();
+        if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            throw UnknownException("context was closed");
+        }
+
+        std::string type =
+            NFCUtil::toStringSecureElementType(cb->getActiveSecureElement());
+        cb->callSuccessCallback(JSUtil::toJSValueRef(context, type));
+    } catch (BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("Something strange happened");
+    }
+
+    delete holder;
+    return false;
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NFCCallbackData.h b/src/NFC/NFCCallbackData.h
new file mode 100644 (file)
index 0000000..772dde3
--- /dev/null
@@ -0,0 +1,155 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _NFCCALLBACKDATA_H_
+#define _NFCCALLBACKDATA_H_
+
+#include <CallbackUserData.h>
+#include <string>
+#include <memory>
+#include <glib.h>
+#include "NFCUtil.h"
+#include "NdefMessage.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace NFC {
+
+class OperationCallbackData: public Common::CallbackUserData
+{
+public:
+    OperationCallbackData(JSContextRef global_ctx);
+    virtual ~OperationCallbackData();
+
+    void setError(const std::string &err_name,
+            const std::string &err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+private:
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+};
+
+class AdapterCallbackData : public OperationCallbackData
+{
+public:
+    AdapterCallbackData(JSContextRef global_ctx, bool powered_state);
+    virtual ~AdapterCallbackData();
+
+    bool getPoweredState() const;
+
+private:
+    bool m_powered_state;
+
+};
+
+class NdefMessageCallbackData : public OperationCallbackData
+{
+public:
+    NdefMessageCallbackData(JSContextRef global_ctx);
+    virtual ~NdefMessageCallbackData();
+
+    void setMessage(NdefMessagePtr message);
+    NdefMessagePtr getMessage() const;
+
+private:
+    NdefMessagePtr m_ndef_message;
+};
+
+class ByteArraySuccessCallback : public OperationCallbackData
+{
+public:
+    ByteArraySuccessCallback(JSContextRef global_ctx);
+    virtual ~ByteArraySuccessCallback();
+
+    void setInputData(const UCharVector& byte_array);
+    UCharVector getInputData() const;
+
+    void setOutputData(const UCharVector& byte_array);
+    UCharVector getOutputData() const;
+
+private:
+    UCharVector m_input_data;
+    UCharVector m_output_data;
+};
+
+class CardEmulationModeChangeCallback : public OperationCallbackData
+{
+public:
+    CardEmulationModeChangeCallback(JSContextRef global_ctx);
+    virtual ~CardEmulationModeChangeCallback();
+
+    void setCardEmulationMode(nfc_se_card_emulation_mode_type_e mode);
+    nfc_se_card_emulation_mode_type_e getCardEmulationMode() const;
+
+    static gboolean complete(void *data);
+
+private:
+    nfc_se_card_emulation_mode_type_e m_mode;
+};
+
+typedef std::shared_ptr<CardEmulationModeChangeCallback>
+    CardEmulationModeChangeCallbackPtr;
+
+class TransactionEventCallback : public OperationCallbackData
+{
+public:
+    TransactionEventCallback(JSContextRef global_ctx, nfc_se_type_e type);
+    virtual ~TransactionEventCallback();
+
+    void setAppletId(const UCharVector& applet_id);
+    UCharVector getAppletId() const;
+
+    void setData(const UCharVector& data);
+    UCharVector getData() const;
+
+    static gboolean complete(void *data);
+private:
+    nfc_se_type_e m_type;
+    UCharVector m_applet_id;
+    UCharVector m_data;
+};
+
+typedef std::shared_ptr<TransactionEventCallback>
+    TransactionEventCallbackPtr;
+
+class ActiveSecureElementChangeCallback : public OperationCallbackData
+{
+public:
+    ActiveSecureElementChangeCallback(JSContextRef global_ctx);
+    virtual ~ActiveSecureElementChangeCallback();
+
+    void setActiveSecureElement(nfc_se_type_e type);
+    nfc_se_type_e getActiveSecureElement() const;
+
+    static gboolean complete(void *data);
+private:
+    nfc_se_type_e m_type;
+};
+
+typedef std::shared_ptr<ActiveSecureElementChangeCallback>
+    ActiveSecureElementChangeCallbackPtr;
+
+} // NFC
+} // DeviceAPI
+
+#endif // _NFCCALLBACKDATA_H_
diff --git a/src/NFC/NFCManager.cpp b/src/NFC/NFCManager.cpp
new file mode 100644 (file)
index 0000000..cff5268
--- /dev/null
@@ -0,0 +1,111 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NFCManager.h"
+#include "nfc.h"
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+NFCManager::NFCManager():
+        SecurityAccessor()
+{
+    LOGD("Entered");
+    initialize();
+}
+
+NFCManager::~NFCManager()
+{
+    LOGD("Entered");
+    deinitialize();
+}
+
+NFCManager&  NFCManager::getInstance(){
+    static NFCManager instance;
+    return instance;
+}
+
+void NFCManager::initialize()
+{
+    LOGD("Entered");
+    int result = nfc_manager_initialize();
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Could not initialize NFC Manager: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        m_initialized = false;
+    } else {
+        m_initialized = true;
+    }
+}
+
+void NFCManager::deinitialize() {
+    if(m_initialized == true)
+    {
+        if (m_adapter) {
+            m_adapter->unsetTagListener();
+            m_adapter->unsetPeerListener();
+        }
+        unsetExclusiveMode();
+        int ret = nfc_manager_deinitialize();
+        if (NFC_ERROR_NONE == ret) {
+            m_initialized = false;
+        }
+        else {
+            LOGE("Could not deinitialize NFC Manager: %d, %s", ret,
+                NFCUtil::getNFCErrorMessage(ret).c_str());
+        }
+    }
+}
+
+NFCAdapterPtr NFCManager::getDefaultAdapter()
+{
+    LOGD("Entered");
+    if (!m_adapter) {
+        m_adapter.reset(new NFCAdapter());
+    }
+    return m_adapter;
+}
+
+void NFCManager::setExclusiveMode(bool mode)
+{
+    LOGD("Entered");
+    if (!m_initialized) {
+        initialize();
+    }
+    int result = nfc_manager_set_system_handler_enable(!mode);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Failed to set exclusive mode: %d, %s",
+            result, NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Failed to set exclusive mode.");
+    }
+}
+
+void NFCManager::unsetExclusiveMode() {
+    LOGD("Entered");
+    if (m_initialized) {
+        int ret = nfc_manager_set_system_handler_enable(true);
+        if (NFC_ERROR_NONE != ret) {
+            LOGE("Failed to unset exclusive mode: %d, %s", ret,
+                NFCUtil::getNFCErrorMessage(ret).c_str());
+        }
+    }
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NFCManager.h b/src/NFC/NFCManager.h
new file mode 100644 (file)
index 0000000..0af52ff
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NFCMANAGER_H_
+#define __TIZEN_NFC_NFCMANAGER_H_
+
+#include "NFCAdapter.h"
+#include "NFCUtil.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NFCManager : public Common::SecurityAccessor {
+public:
+    enum nfcTNF{
+        NFC_RECORD_TNF_EMPTY = 0,
+        NFC_RECORD_TNF_WELL_KNOWN = 1,
+        NFC_RECORD_TNF_MIME_MEDIA = 2,
+        NFC_RECORD_TNF_URI = 3,
+        NFC_RECORD_TNF_EXTERNAL_RTD = 4,
+        NFC_RECORD_TNF_UNKNOWN = 5,
+        NFC_RECORD_TNF_UNCHANGED = 6
+    };
+
+    static NFCManager& getInstance();
+    virtual ~NFCManager();
+
+    void initialize();
+    void deinitialize();
+
+    NFCAdapterPtr getDefaultAdapter();
+    void setExclusiveMode(bool mode);
+    void unsetExclusiveMode();
+
+private:
+    NFCManager();
+    NFCManager(const NFCManager&);
+    NFCManager& operator=(const NFCManager&);
+    NFCAdapterPtr m_adapter;
+    bool m_initialized;
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_NFCMANAGER_H_
diff --git a/src/NFC/NFCPeer.cpp b/src/NFC/NFCPeer.cpp
new file mode 100644 (file)
index 0000000..1462ac7
--- /dev/null
@@ -0,0 +1,252 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSNdefMessage.h"
+#include "NdefMessage.h"
+#include "NFCPeer.h"
+#include "NFCUtil.h"
+#include <glib.h>
+#include <Logger.h>
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+NFCPeer::NFCPeer(nfc_p2p_target_h handle):
+        SecurityAccessor()
+{
+    LOGD("Entered");
+
+    if(NULL == handle) {
+        LOGE("Target handler is null.");
+        throw Common::UnknownException("Target handler is null.");
+    }
+
+    m_handle = handle;
+    m_callback = NULL;
+}
+
+NFCPeer::~NFCPeer()
+{
+    LOGD("Entered");
+    m_handle = NULL;
+    removePeerCallback();
+}
+
+bool NFCPeer::isConnected()
+{
+    nfc_p2p_target_h handle = NULL;
+    int ret = nfc_manager_get_connected_target(&handle);
+    if(NFC_ERROR_NONE != ret) {
+        LOGE("Failed to get connected target handle: %d, %s", ret,
+            NFCUtil::getNFCErrorMessage(ret).c_str());
+        throw Common::UnknownException("Failed to get connected target handle.");
+    }
+
+    if(m_handle == handle) {
+        return true;
+    }
+
+    return false;
+
+}
+
+void NFCPeer::setPeerCallback(Common::CallbackUserData *callback)
+{
+    LOGD("Entered");
+    m_callback = callback;
+}
+
+Common::CallbackUserData* NFCPeer::getPeerCallback() const
+{
+    LOGD("Entered");
+    return m_callback;
+}
+
+void NFCPeer::removePeerCallback()
+{
+    LOGD("Entered");
+    delete m_callback;
+    m_callback = NULL;
+}
+
+static void targetReceivedCallback(nfc_p2p_target_h target, nfc_ndef_message_h message,
+        void *data)
+{
+    LOGD("Entered");
+
+    auto *callback = static_cast<Common::CallbackUserData*>(data);
+
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        return;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return;
+    }
+
+    unsigned char *raw_data = NULL;
+    unsigned int size;
+    int ret = nfc_ndef_message_get_rawdata(message, &raw_data, &size);
+    if(NFC_ERROR_NONE != ret) {
+        LOGE("Unknown error while getting raw data of message: %d, %s",
+            ret, NFCUtil::getNFCErrorMessage(ret).c_str());
+        free(raw_data);
+        return;
+    }
+
+    NdefMessagePtr ndefmessage = NdefMessagePtr(new NdefMessage(raw_data, size));
+    JSValueRef js_object = JSNdefMessage::makeJSObject(context, ndefmessage);
+
+    callback->callSuccessCallback(js_object);
+
+    free(raw_data);
+}
+
+void NFCPeer::setReceiveNDEFListener(Common::CallbackUserData *callback)
+{
+    LOGD("Entered");
+
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    int result = nfc_p2p_set_data_received_cb(m_handle, targetReceivedCallback,
+            static_cast<void *>(callback));
+
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Failed to set callback: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Failed to set callback");
+    }
+
+}
+
+void NFCPeer::unsetReceiveNDEFListener()
+{
+    LOGD("Entered");
+
+    int result = nfc_p2p_unset_data_received_cb(m_handle);
+    if(NFC_ERROR_NONE != result) {
+        LOGE("Error while unsetting ReceiveNDEFListener: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Error while unsetting ReceiveNDEFListener");
+    }
+    this->removePeerCallback();
+}
+
+
+static gboolean sendNDEFCompleteCB(void* data)
+{
+    LOGD("Entered");
+
+    NdefMessageCallbackData* callback =
+            static_cast<NdefMessageCallbackData*>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const Common::BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Send NDEFMessage failed");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+static void peerSentCallback(nfc_error_e result, void *user_data) {
+    LOGD("Entered PeerSentCallback.");
+
+    NdefMessageCallbackData* callback =
+            static_cast<NdefMessageCallbackData*>(user_data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return;
+    }
+
+    if (NFC_ERROR_NONE != result){
+        std::string log_msg =
+                "Unknown error while nfc_p2p_send: " + std::to_string(result);
+        LOGE("%s", log_msg.c_str());
+        callback->setError(Common::JSWebAPIErrorFactory::UNKNOWN_ERROR, log_msg.c_str() );
+    }
+    if (!g_idle_add(sendNDEFCompleteCB, static_cast<void*>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+void NFCPeer::sendNDEF(NdefMessageCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if(!callback){
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+    NdefMessagePtr ndef_message = callback->getMessage();
+
+    nfc_ndef_message_h message = ndef_message->toStruct();
+    if(message){
+        nfc_p2p_send(m_handle, message,
+                peerSentCallback, static_cast<void*>(callback));
+        NdefRecord::removeMessageHandle(message);
+    } else {
+        callback->setError(Common::JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                "Message is not correct");
+        if (!g_idle_add(sendNDEFCompleteCB, static_cast<void*>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    }
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NFCPeer.h b/src/NFC/NFCPeer.h
new file mode 100644 (file)
index 0000000..352a691
--- /dev/null
@@ -0,0 +1,60 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NFCPEER_H_
+#define __TIZEN_NFC_NFCPEER_H_
+
+#include <nfc.h>
+#include <memory>
+
+#include <CallbackUserData.h>
+#include "NFCCallbackData.h"
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NFCPeer;
+typedef std::shared_ptr<NFCPeer> NFCPeerPtr;
+
+class CallbackUserData;
+
+class NFCPeer : public Common::SecurityAccessor
+{
+public:
+    NFCPeer(nfc_p2p_target_h handle);
+    virtual  ~NFCPeer();
+
+    bool isConnected();
+    void setPeerCallback(Common::CallbackUserData *callback);
+    Common::CallbackUserData* getPeerCallback() const;
+    void removePeerCallback();
+
+    void setReceiveNDEFListener(Common::CallbackUserData *callback);
+    void unsetReceiveNDEFListener();
+    void sendNDEF(NdefMessageCallbackData* callback);
+
+protected:
+    nfc_p2p_target_h m_handle;
+    Common::CallbackUserData *m_callback;
+};
+
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_NFCPEER_H_
diff --git a/src/NFC/NFCPeerDetectCallback.cpp b/src/NFC/NFCPeerDetectCallback.cpp
new file mode 100644 (file)
index 0000000..4f2d594
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "NFCPeerDetectCallback.h"
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include "JSNFCPeer.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace NFC {
+
+namespace {
+const char* PEER_ON_ATTACH = "onattach";
+const char* PEER_ON_DETACH = "ondetach";
+}
+
+NFCPeerDetectCallback::NFCPeerDetectCallback(JSContextRef global_ctx,
+        JSObjectRef onattach_obj,
+        JSObjectRef ondetach_obj):
+        m_callback(global_ctx)
+{
+    LOGD("Entered");
+
+    m_callback.setCallback(PEER_ON_ATTACH, onattach_obj);
+    m_callback.setCallback(PEER_ON_DETACH, ondetach_obj);
+}
+
+NFCPeerDetectCallback::~NFCPeerDetectCallback()
+{
+    LOGD("Entered");
+}
+
+void NFCPeerDetectCallback::onAttach(NFCPeerPtr nfc_peer)
+{
+    JSValueRef js_object = JSNFCPeer::makeJSObject(m_callback.getContext(), nfc_peer);
+    m_callback.invokeCallback(PEER_ON_ATTACH, js_object);
+}
+
+void NFCPeerDetectCallback::onDetach()
+{
+    m_callback.invokeCallback(PEER_ON_DETACH);
+}
+
+JSContextRef NFCPeerDetectCallback::getContext() const
+{
+    return m_callback.getContext();
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NFCPeerDetectCallback.h b/src/NFC/NFCPeerDetectCallback.h
new file mode 100644 (file)
index 0000000..2657e16
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NFCPEERDETECTCALLBACK_H__
+#define __TIZEN_NFC_NFCPEERDETECTCALLBACK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include "NFCPeer.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NFCPeerDetectCallback {
+public:
+    NFCPeerDetectCallback(JSContextRef globalCtx,
+            JSObjectRef onattach_obj,
+            JSObjectRef ondetach_obj);
+
+    virtual ~NFCPeerDetectCallback();
+
+    void onAttach(NFCPeerPtr nfc_peer);
+    void onDetach();
+
+    JSContextRef getContext() const;
+private:
+    Common::MultiCallbackUserData m_callback;
+
+};
+
+} // NFC
+} // DeviceAPI
+
+
+#endif // __TIZEN_NFC_NFCPEERDETECTCALLBACK_H__
diff --git a/src/NFC/NFCTag.cpp b/src/NFC/NFCTag.cpp
new file mode 100755 (executable)
index 0000000..480b300
--- /dev/null
@@ -0,0 +1,446 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NFCTag.h"
+#include "JSUtil.h"
+#include "NFCUtil.h"
+#include "JSNdefMessage.h"
+#include <glib.h>
+#include <Logger.h>
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+bool NFCTag::transceive_idle = true;
+
+NFCTag::NFCTag(nfc_tag_h handle):m_handle(handle),
+        SecurityAccessor()
+{
+    LOGD("Entered");
+}
+
+NFCTag::~NFCTag()
+{
+    LOGD("Entered");
+    m_handle = NULL;
+}
+
+nfc_tag_type_e NFCTag::getType()
+{
+    nfc_tag_type_e type = NFC_UNKNOWN_TARGET;
+    int result = nfc_tag_get_type(m_handle, &type);
+    if(NFC_ERROR_NONE != result) {
+        LOGE("Unknown error while getting tag type: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Unknown error while getting tag type.");
+    }
+
+    return type;
+}
+
+std::string NFCTag::getTypeString()
+{
+    return(NFCUtil::toStringNFCTag(getType()));
+}
+
+bool NFCTag::isSupportedNDEF()
+{
+    bool is_supported_NDEF = false;
+    int result = nfc_tag_is_support_ndef(m_handle, &is_supported_NDEF);
+    if(NFC_ERROR_NONE != result) {
+        LOGE("Unknown error while getting is NDEF supported flag: %d, %s",
+            result, NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result,
+                "Unknown error while getting is NDEF supported flag.");
+    }
+
+    return is_supported_NDEF;
+}
+
+long NFCTag::getNdefSize()
+{
+    unsigned int ndef_size;
+    int result = nfc_tag_get_ndef_size(m_handle, &ndef_size);
+    if(NFC_ERROR_NONE != result) {
+        LOGE("Unknown error while getting is NDEF size: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result,
+                "Unknown error while getting is NDEF size.");
+    }
+
+    return static_cast<long>(ndef_size);
+}
+
+static bool tagPropertyCallback(const char *key,
+        const unsigned char *value,
+        int value_size,
+        void *user_data)
+{
+    if (user_data) {
+        UCharVector tag_info = NFCUtil::toVector(value, value_size);
+        (static_cast<NFCTag*>(user_data))->addTagProperty(key, tag_info);
+        return true;
+    }
+
+    return false;
+}
+
+void NFCTag::addTagProperty(const char *key, UCharVector &value)
+{
+    m_properties.push_back(std::make_pair(key,value));
+}
+
+std::vector<PropertyPair> NFCTag::getProperties()
+{
+    m_properties.clear();
+    int result = nfc_tag_foreach_information(m_handle, tagPropertyCallback, this);
+    if(NFC_ERROR_NONE != result) {
+        LOGE("Unknown error while getting tag's properties: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result,
+                "Unknown error while getting tag's properties.");
+    }
+
+    return m_properties;
+}
+
+bool NFCTag::isConnected()
+{
+    nfc_tag_h handle = NULL;
+    int result = nfc_manager_get_connected_tag(&handle);
+    if(NFC_ERROR_NONE != result) {
+        LOGE("Unknown error while getting tag's is connected flag: %d, %s",
+            result, NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result,
+                "Unknown error while getting tag's is connected flag.");
+    }
+
+    if(m_handle == handle) {
+        return true;
+    }
+
+    return false;
+}
+
+static gboolean readNDEFCompleteCB(void *data)
+{
+    LOGD("Entered");
+
+    auto callback = static_cast<NdefMessageCallbackData*>(data);
+    if(NULL == callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if(callback->isError()) {
+            JSObjectRef error_obj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                    context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(error_obj);
+        }
+        else {
+            JSValueRef js_value = JSNdefMessage::makeJSObject(context,
+                    callback->getMessage());
+            callback->callSuccessCallback(js_value);
+        }
+    } catch (const Common::BasePlatformException &error) {
+        LOGE("%s (%s)", (error.getName()).c_str(), (error.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Unknown error when calling readNDEF.");
+    }
+
+    delete callback;
+    callback = NULL;
+    return false;
+}
+
+static void tagReadCallback(nfc_error_e result , nfc_ndef_message_h message , void *data)
+{
+    LOGD("Entered");
+
+    if(NULL == data) {
+        LOGE("Callback is null");
+        return;
+    }
+
+    auto *callback = static_cast<NdefMessageCallbackData*>(data);
+
+    if(NFC_ERROR_NONE != result) {
+        callback->setError(NFCUtil::getNFCErrorString(result),
+                NFCUtil::getNFCErrorMessage(result));
+
+        if(0 == g_idle_add(readNDEFCompleteCB, static_cast<void *>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+        return;
+    }
+
+    unsigned char *raw_data = NULL;
+    unsigned int size;
+    int ret = nfc_ndef_message_get_rawdata(message, &raw_data, &size);
+    if(NFC_ERROR_NONE != ret) {
+        LOGE("Couldn't get record's raw data: %d, %s", ret,
+            NFCUtil::getNFCErrorMessage(ret).c_str());
+        callback->setError(Common::JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "Couldn't get record's raw data");
+
+        if(0 == g_idle_add(readNDEFCompleteCB, static_cast<void *>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+
+        free(raw_data);
+        return;
+    }
+
+    NdefMessagePtr ndefmessage = NdefMessagePtr(new NdefMessage(raw_data, size));
+    callback->setMessage(ndefmessage);
+
+    if(0 == g_idle_add(readNDEFCompleteCB, static_cast<void *>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+
+    free(raw_data);
+}
+
+void NFCTag::readNDEF(NdefMessageCallbackData *callback)
+{
+    LOGD("Entered");
+
+    if(NULL == callback) {
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+
+    int result = nfc_tag_read_ndef(m_handle, tagReadCallback, static_cast<void *>(callback));
+    if(NFC_ERROR_NONE != result) {
+        std::string errName = NFCUtil::getNFCErrorString(result);
+        std::string errMessage = NFCUtil::getNFCErrorMessage(result);
+        LOGE("%s: %s", errName.c_str(), errMessage.c_str());
+
+        JSObjectRef err_obj = Common::JSWebAPIErrorFactory::makeErrorObject(
+                callback->getContext(), errName.c_str(), errMessage.c_str());
+        callback->callErrorCallback(err_obj);
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean writeNDEFCompleteCB(void* data)
+{
+    LOGD("Entered");
+
+    NdefMessageCallbackData* callback =
+            static_cast<NdefMessageCallbackData*>(data);
+    if (!callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            LOGD("Calling error callback");
+            JSObjectRef errobj = Common::JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        } else {
+            LOGD("Calling success callback");
+            callback->callSuccessCallback();
+        }
+    } catch (const Common::BasePlatformException& err) {
+        LOGE("%s (%s)", (err.getName()).c_str(), (err.getMessage()).c_str());
+    } catch (...) {
+        LOGE("Write NDEFMessage failed");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void NFCTag::writeNDEF(NdefMessageCallbackData* callback)
+{
+    LOGD("Entered");
+
+    if(!callback){
+        LOGE("Callback is null");
+        throw Common::UnknownException("Callback is null");
+    }
+    NdefMessagePtr ndef_message = callback->getMessage();
+
+    nfc_ndef_message_h message = ndef_message->toStruct();
+    if(message){
+        int result = nfc_tag_write_ndef(m_handle, message, NULL, NULL);
+        //nfc_tag_write_ndef function does not call callback when result is an error
+        //it is needed to check it and manually call callback
+        NdefRecord::removeMessageHandle(message);
+        if (NFC_ERROR_NONE != result){
+            std::string errName = NFCUtil::getNFCErrorString(result);
+            std::string errMessage = NFCUtil::getNFCErrorMessage(result);
+            LOGE("%s: %s", errName.c_str(), errMessage.c_str());
+            callback->setError(errName.c_str(), errMessage.c_str());
+        }
+    } else {
+        callback->setError(Common::JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                "Message is not correct");
+    }
+    if (!g_idle_add(writeNDEFCompleteCB, static_cast<void*>(callback))) {
+        LOGE("g_idle addition failed");
+        delete callback;
+        callback = NULL;
+    }
+}
+
+static gboolean transceiveCompleteCB(void* data)
+{
+    ByteArraySuccessCallback *callback =
+        static_cast<ByteArraySuccessCallback*>(data);
+    if (NULL == callback) {
+        LOGE("Callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    try {
+        if (!callback->isError()) {
+            callback->callSuccessCallback(Common::JSUtil::toJSValueRef_(
+                        context, callback->getOutputData()));
+        } else {
+            JSObjectRef errobj =
+                Common::JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(errobj);
+        }
+    }
+    catch (const Common::BasePlatformException& err) {
+        LOGE("Error while calling transceive callback: %s (%s)",
+                (err.getName()).c_str(),(err.getMessage()).c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error when calling transceive callback.");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void NFCTag::transceiveCB(nfc_error_e result,
+        unsigned char* buffer,
+        int buffer_size,
+        void* user_data)
+{
+    // release idle flag
+    NFCTag::transceive_idle = true;
+
+    ByteArraySuccessCallback* callback =
+        static_cast<ByteArraySuccessCallback*>(user_data);
+    if (!callback) {
+        LOGE("argument user_data is NULL");
+        return;
+    }
+
+    if (NFC_ERROR_NONE != result) {
+        callback->setError("NFC transceive error",
+                NFCUtil::getNFCErrorMessage(result));
+    }
+    else {
+        UCharVector data = NFCUtil::toVector(buffer, buffer_size);
+        callback->setOutputData(data);
+    }
+
+    transceiveCompleteCB(static_cast<void *>(callback));
+}
+
+void NFCTag::transceive(ByteArraySuccessCallback* callback)
+{
+    if (!callback) {
+        LOGE("argument callback is null");
+        return;
+    }
+
+    // check if transceive is not busy
+    if (transceive_idle) {
+        transceive_idle = false;
+
+        UCharVector buffer = callback->getInputData();
+
+        int result = nfc_tag_transceive(m_handle, buffer.data(), buffer.size(),
+                transceiveCB, static_cast<void*>(callback));
+
+        if (NFC_ERROR_NONE != result) {
+            transceive_idle = true;
+            LOGE("NFC transceive error: %d, %s", result,
+                NFCUtil::getNFCErrorMessage(result).c_str());
+            callback->setError("NFC transceive error",
+                    NFCUtil::getNFCErrorMessage(result));
+        }
+    }
+    else {
+        callback->setError("NFC transceive error",
+                NFCUtil::getNFCErrorMessage(NFC_ERROR_DEVICE_BUSY));
+    }
+
+    if (callback->isError()) {
+        if (0 == g_idle_add(transceiveCompleteCB,
+                static_cast<void *>(callback))) {
+            LOGE("g_idle addition failed");
+            delete callback;
+            callback = NULL;
+        }
+    }
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NFCTag.h b/src/NFC/NFCTag.h
new file mode 100755 (executable)
index 0000000..e784d42
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NFCTAG_H_
+#define __TIZEN_NFC_NFCTAG_H_
+
+#include <nfc.h>
+#include <memory>
+#include <vector>
+#include "NdefRecord.h"
+#include "NdefMessage.h"
+#include "NFCCallbackData.h"
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NFCTag;
+typedef std::shared_ptr<NFCTag> NFCTagPtr;
+typedef std::pair<std::string, UCharVector> PropertyPair;
+
+class NFCTag : public Common::SecurityAccessor
+{
+public:
+    NFCTag(nfc_tag_h handle);
+    virtual ~NFCTag();
+
+    nfc_tag_type_e getType();
+    std::string getTypeString();
+    bool isSupportedNDEF();
+    long getNdefSize();
+    std::vector<PropertyPair> getProperties();
+    bool isConnected();
+    void writeNDEF(NdefMessageCallbackData* callback);
+    void readNDEF(NdefMessageCallbackData *callback);
+
+    void addTagProperty(const char *key, UCharVector &value);
+
+    void transceive(ByteArraySuccessCallback* callback);
+
+protected:
+    nfc_tag_h m_handle;
+    std::vector<PropertyPair> m_properties;
+    // idle (i.e. not-busy) transceive flag
+    static bool transceive_idle;
+    static void transceiveCB(nfc_error_e result, unsigned char* buffer,
+        int buffer_size, void* user_data);
+};
+
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_NFCTAG_H_
diff --git a/src/NFC/NFCTagDetectCallback.cpp b/src/NFC/NFCTagDetectCallback.cpp
new file mode 100644 (file)
index 0000000..6627d29
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include "NFCTagDetectCallback.h"
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include "JSNFCTag.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace NFC {
+
+namespace {
+const char* TAG_ON_ATTACH = "onattach";
+const char* TAG_ON_DETACH = "ondetach";
+}
+
+NFCTagDetectCallback::NFCTagDetectCallback(JSContextRef globalCtx,
+    JSObjectRef onattach_obj,
+    JSObjectRef ondetach_obj):
+    m_callback(globalCtx)
+{
+    LOGD("Entered");
+
+    m_callback.setCallback(TAG_ON_ATTACH, onattach_obj);
+    m_callback.setCallback(TAG_ON_DETACH, ondetach_obj);
+
+}
+
+NFCTagDetectCallback::~NFCTagDetectCallback()
+{
+    LOGD("Entered");
+}
+
+void NFCTagDetectCallback::onAttach(NFCTagPtr nfc_tag)
+{
+    LOGD("Entered");
+    JSValueRef js_object = JSNFCTag::makeJSObject(m_callback.getContext(), nfc_tag);
+    m_callback.invokeCallback(TAG_ON_ATTACH, js_object);
+}
+
+void NFCTagDetectCallback::onDetach()
+{
+    LOGD("Entered");
+    m_callback.invokeCallback(TAG_ON_DETACH);
+}
+
+void NFCTagDetectCallback::setFilterValue (std::vector <nfc_tag_type_e> & tag_filter)
+{
+    m_tag_filter = tag_filter;
+}
+
+std::vector <nfc_tag_type_e> & NFCTagDetectCallback::getFilterValue()
+{
+    return m_tag_filter;
+}
+
+JSContextRef NFCTagDetectCallback::getContext() const
+{
+    return m_callback.getContext();
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NFCTagDetectCallback.h b/src/NFC/NFCTagDetectCallback.h
new file mode 100644 (file)
index 0000000..5c7dcdb
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NFCTAGDETECTCALLBACK_H__
+#define __TIZEN_NFC_NFCTAGDETECTCALLBACK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include "NFCTag.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NFCTagDetectCallback {
+public:
+    NFCTagDetectCallback(JSContextRef globalCtx,
+            JSObjectRef onattach_obj,
+            JSObjectRef ondetach_obj);
+    virtual ~NFCTagDetectCallback();
+
+    void onAttach(NFCTagPtr nfc_tag);
+    void onDetach();
+
+    void setFilterValue (std::vector <nfc_tag_type_e> & tag_filter);
+    std::vector <nfc_tag_type_e> & getFilterValue();
+
+    JSContextRef getContext() const;
+private:
+    Common::MultiCallbackUserData m_callback;
+    std::vector <nfc_tag_type_e> m_tag_filter;
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_NFCTAGDETECTCALLBACK_H__
diff --git a/src/NFC/NFCUtil.cpp b/src/NFC/NFCUtil.cpp
new file mode 100644 (file)
index 0000000..34c9e49
--- /dev/null
@@ -0,0 +1,293 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NFCUtil.h"
+
+#include <nfc.h>
+#include <Logger.h>
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+UCharVector NFCUtil::toVector(const unsigned char *ch, const int size)
+{
+    UCharVector vec(ch, ch + size / sizeof(char));
+    return vec;
+}
+
+void NFCUtil::throwNFCException(const int errorCode, const char* message)
+{
+    switch(errorCode) {
+        case NFC_ERROR_INVALID_PARAMETER:
+        case NFC_ERROR_INVALID_NDEF_MESSAGE:
+        case NFC_ERROR_INVALID_RECORD_TYPE:
+        case NFC_ERROR_NOT_NDEF_FORMAT:
+            throw Common::InvalidValuesException(message);
+            break;
+        case NFC_ERROR_SECURITY_RESTRICTED:
+            throw Common::SecurityException(message);
+            break;
+        case NFC_ERROR_NOT_ACTIVATED:
+        case NFC_ERROR_NOT_SUPPORTED:
+        case NFC_ERROR_OPERATION_FAILED:
+        case NFC_ERROR_DEVICE_BUSY:
+        case NFC_ERROR_NO_DEVICE:
+        case NFC_ERROR_TIMED_OUT:
+        case NFC_ERROR_OUT_OF_MEMORY:
+        default:
+            throw Common::UnknownException(message);
+            break;
+    }
+}
+
+std::string NFCUtil::getNFCErrorString(const int error_code)
+{
+    switch(error_code) {
+        case NFC_ERROR_ALREADY_ACTIVATED:
+        case NFC_ERROR_ALREADY_DEACTIVATED:
+            return "";
+        case NFC_ERROR_INVALID_PARAMETER:
+        case NFC_ERROR_INVALID_NDEF_MESSAGE:
+        case NFC_ERROR_INVALID_RECORD_TYPE:
+        case NFC_ERROR_NOT_NDEF_FORMAT:
+            return Common::JSWebAPIErrorFactory::INVALID_VALUES_ERROR;
+        case NFC_ERROR_NO_DEVICE:
+        case NFC_ERROR_OUT_OF_MEMORY:
+        case NFC_ERROR_OPERATION_FAILED:
+        case NFC_ERROR_DEVICE_BUSY:
+            return Common::JSWebAPIErrorFactory::UNKNOWN_ERROR;
+        case NFC_ERROR_NOT_ACTIVATED:
+            return Common::JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR;
+        case NFC_ERROR_NOT_SUPPORTED:
+            return Common::JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR;
+        case NFC_ERROR_TIMED_OUT:
+            return Common::JSWebAPIErrorFactory::TIMEOUT_ERROR;
+    }
+    return Common::JSWebAPIErrorFactory::UNKNOWN_ERROR;
+}
+
+std::string NFCUtil::getNFCErrorMessage(const int error_code)
+{
+    switch(error_code) {
+        case NFC_ERROR_ALREADY_ACTIVATED:
+        case NFC_ERROR_ALREADY_DEACTIVATED:
+            return "";
+        case NFC_ERROR_INVALID_PARAMETER:
+            return "Invalid Parameter";
+        case NFC_ERROR_INVALID_NDEF_MESSAGE:
+            return "Invalid NDEF Message";
+        case NFC_ERROR_INVALID_RECORD_TYPE:
+            return "Invalid Record Type";
+        case NFC_ERROR_NO_DEVICE:
+            return "No Device";
+        case NFC_ERROR_OUT_OF_MEMORY:
+            return "Out Of Memory";
+        case NFC_ERROR_NOT_SUPPORTED:
+            return "NFC Not Supported";
+        case NFC_ERROR_OPERATION_FAILED:
+            return "Operation Failed";
+        case NFC_ERROR_DEVICE_BUSY:
+            return "Device Busy";
+        case NFC_ERROR_NOT_ACTIVATED:
+            return "NFC Not Activated";
+        case NFC_ERROR_TIMED_OUT:
+            return "Time Out";
+        case NFC_ERROR_READ_ONLY_NDEF:
+            return "Read Only NDEF";
+        case NFC_ERROR_NO_SPACE_ON_NDEF:
+            return "No Space On NDEF";
+        case NFC_ERROR_NO_NDEF_MESSAGE:
+            return "No NDEF Message";
+        case NFC_ERROR_NOT_NDEF_FORMAT:
+            return "Not NDEF Format";
+        case NFC_ERROR_SECURITY_RESTRICTED:
+            return "Security Restricted";
+    }
+    return "UnknownError";
+}
+
+std::string NFCUtil::toStringNFCTag(nfc_tag_type_e tag_type)
+{
+    switch (tag_type) {
+        case NFC_GENERIC_PICC:
+            return GENERIC_TARGET;
+        case NFC_ISO14443_A_PICC:
+            return ISO14443_A;
+        case NFC_ISO14443_4A_PICC:
+            return ISO14443_4A;
+        case NFC_ISO14443_3A_PICC:
+            return ISO14443_3A;
+        case NFC_MIFARE_MINI_PICC:
+            return MIFARE_MINI;
+        case NFC_MIFARE_1K_PICC:
+            return MIFARE_1K;
+        case NFC_MIFARE_4K_PICC:
+            return MIFARE_4K;
+        case NFC_MIFARE_ULTRA_PICC:
+           return MIFARE_ULTRA;
+        case NFC_MIFARE_DESFIRE_PICC:
+            return MIFARE_DESFIRE;
+        case NFC_ISO14443_B_PICC:
+            return ISO14443_B;
+        case NFC_ISO14443_4B_PICC:
+            return ISO14443_4B;
+        case NFC_ISO14443_BPRIME_PICC:
+            return ISO14443_BPRIME;
+        case NFC_FELICA_PICC:
+            return FELICA;
+        case NFC_JEWEL_PICC:
+            return JEWEL;
+        case NFC_ISO15693_PICC:
+            return ISO15693;
+        case NFC_UNKNOWN_TARGET:
+        default:
+            return UNKNOWN_TARGET;
+    }
+}
+
+nfc_tag_type_e NFCUtil::toNfcTagString(const std::string& type_string)
+{
+    if (GENERIC_TARGET == type_string) {
+        return NFC_GENERIC_PICC;
+    }
+    else if (ISO14443_A == type_string) {
+        return NFC_ISO14443_A_PICC;
+    }
+    else if (ISO14443_4A == type_string) {
+        return NFC_ISO14443_4A_PICC;
+    }
+    else if (ISO14443_3A == type_string) {
+        return NFC_ISO14443_3A_PICC;
+    }
+    else if (MIFARE_MINI == type_string) {
+        return NFC_MIFARE_MINI_PICC;
+    }
+    else if (MIFARE_1K == type_string) {
+        return NFC_MIFARE_1K_PICC;
+    }
+    else if (MIFARE_4K == type_string) {
+        return NFC_MIFARE_4K_PICC;
+    }
+    else if (MIFARE_ULTRA == type_string) {
+        return NFC_MIFARE_ULTRA_PICC;
+    }
+    else if (MIFARE_DESFIRE == type_string) {
+        return NFC_MIFARE_DESFIRE_PICC;
+    }
+    else if (ISO14443_B == type_string) {
+        return NFC_ISO14443_B_PICC;
+    }
+    else if (ISO14443_4B == type_string) {
+        return NFC_ISO14443_4B_PICC;
+    }
+    else if (ISO14443_BPRIME == type_string) {
+        return NFC_ISO14443_BPRIME_PICC;
+    }
+    else if (FELICA == type_string) {
+        return NFC_FELICA_PICC;
+    }
+    else if (JEWEL == type_string) {
+        return NFC_JEWEL_PICC;
+    }
+    else if (ISO15693 == type_string) {
+        return NFC_ISO15693_PICC;
+    }
+    else if (UNKNOWN_TARGET == type_string) {
+        return NFC_UNKNOWN_TARGET;
+    }
+    else {
+      throw Common::TypeMismatchException("No Match Tag Type");
+    }
+}
+
+std::string NFCUtil::toStringCardEmulationMode(
+    const nfc_se_card_emulation_mode_type_e mode)
+{
+    switch (mode)
+    {
+        case NFC_SE_CARD_EMULATION_MODE_OFF:
+            return OFF;
+        case NFC_SE_CARD_EMULATION_MODE_ON:
+            return ALWAYS_ON;
+        default:
+            LOGE("No Match Card Emulation mode: %x", mode);
+            throw Common::TypeMismatchException("No Match Card Emulation mode");
+    }
+}
+
+nfc_se_card_emulation_mode_type_e NFCUtil::toCardEmulationMode(
+    const std::string &mode_string)
+{
+    if (mode_string == ALWAYS_ON) {
+        return NFC_SE_CARD_EMULATION_MODE_ON;
+    } else if (mode_string == OFF) {
+        return NFC_SE_CARD_EMULATION_MODE_OFF;
+    } else {
+        LOGE("No Match Card Emulation mode: %s", mode_string.c_str());
+        throw Common::TypeMismatchException("No Match Card Emulation mode");
+    }
+}
+
+std::string NFCUtil::toStringSecureElementType(const nfc_se_type_e type)
+{
+    switch (type) {
+        case NFC_SE_TYPE_ESE:
+            return ESE;
+        case NFC_SE_TYPE_UICC:
+            return UICC;
+        default:
+            LOGE("No Match Secure Element Type: %x", type);
+            throw Common::TypeMismatchException("No Match Secure Element Type");
+    }
+}
+
+nfc_se_type_e NFCUtil::toSecureElementType(const std::string &type_string)
+{
+    if (type_string == ESE) {
+        return NFC_SE_TYPE_ESE;
+    } else if (type_string == UICC) {
+        return NFC_SE_TYPE_UICC;
+    } else {
+        LOGE("No Match Secure Element Type: %s", type_string.c_str());
+        throw Common::TypeMismatchException("No Match Secure Element Type");
+    }
+}
+
+void NFCUtil::setDefaultFilterValues(std::vector<nfc_tag_type_e>& filter)
+{
+   filter.push_back(NFC_GENERIC_PICC);
+   filter.push_back(NFC_ISO14443_A_PICC);
+   filter.push_back(NFC_ISO14443_3A_PICC);
+   filter.push_back(NFC_ISO14443_3A_PICC);
+   filter.push_back(NFC_MIFARE_MINI_PICC);
+   filter.push_back(NFC_MIFARE_1K_PICC);
+   filter.push_back(NFC_MIFARE_4K_PICC);
+   filter.push_back(NFC_MIFARE_ULTRA_PICC);
+   filter.push_back(NFC_MIFARE_DESFIRE_PICC);
+   filter.push_back(NFC_ISO14443_B_PICC);
+   filter.push_back(NFC_ISO14443_4B_PICC);
+   filter.push_back(NFC_ISO14443_BPRIME_PICC);
+   filter.push_back(NFC_FELICA_PICC);
+   filter.push_back(NFC_JEWEL_PICC);
+   filter.push_back(NFC_ISO15693_PICC);
+   filter.push_back(NFC_UNKNOWN_TARGET);
+}
+
+} // NFC
+} // DeviceApi
diff --git a/src/NFC/NFCUtil.h b/src/NFC/NFCUtil.h
new file mode 100644 (file)
index 0000000..dd8ce64
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef __TIZEN_NFC_NFCUTIL_H_
+#define __TIZEN_NFC_NFCUTIL_H_
+
+#include <vector>
+#include <string>
+#include <nfc.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+namespace {
+const std::string GENERIC_TARGET = "GENERIC_TARGET";
+const std::string ISO14443_A = "ISO14443_A";
+const std::string ISO14443_4A = "ISO14443_4A";
+const std::string ISO14443_3A = "ISO14443_3A";
+const std::string MIFARE_MINI = "MIFARE_MINI";
+const std::string MIFARE_1K = "MIFARE_1K";
+const std::string MIFARE_4K = "MIFARE_4K";
+const std::string MIFARE_ULTRA = "MIFARE_ULTRA";
+const std::string MIFARE_DESFIRE = "MIFARE_DESFIRE";
+const std::string ISO14443_B = "ISO14443_B";
+const std::string ISO14443_4B = "ISO14443_4B";
+const std::string ISO14443_BPRIME  = "ISO14443_BPRIME";
+const std::string FELICA  = "FELICA";
+const std::string JEWEL  = "JEWEL";
+const std::string ISO15693  = "ISO15693";
+const std::string UNKNOWN_TARGET = "UNKNOWN_TARGET";
+
+const std::string ALWAYS_ON = "ALWAYS_ON";
+const std::string OFF = "OFF";
+
+const std::string ESE = "ESE";
+const std::string UICC = "UICC";
+}
+
+typedef std::vector<unsigned char> UCharVector;
+
+class NFCUtil
+{
+public:
+    static UCharVector toVector(const unsigned char *ch, const int size);
+    static void throwNFCException(const int errorCode, const char * message);
+    static std::string getNFCErrorString(const int error_code);
+    static std::string getNFCErrorMessage(const int error_code);
+    static std::string toStringNFCTag(const nfc_tag_type_e tag_type);
+    static nfc_tag_type_e toNfcTagString(const std::string& type_string);
+    static std::string toStringCardEmulationMode(
+        const nfc_se_card_emulation_mode_type_e mode);
+    static nfc_se_card_emulation_mode_type_e toCardEmulationMode(
+        const std::string& mode_string);
+    static std::string toStringSecureElementType(const nfc_se_type_e type);
+    static nfc_se_type_e toSecureElementType(const std::string& type_string);
+    static void setDefaultFilterValues(std::vector<nfc_tag_type_e>& filter);
+};
+
+} // NFC
+} // DeviceApi
+
+#endif // __TIZEN_NFC_NFCUTIL_H_
diff --git a/src/NFC/NdefMessage.cpp b/src/NFC/NdefMessage.cpp
new file mode 100644 (file)
index 0000000..67cf099
--- /dev/null
@@ -0,0 +1,200 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NdefMessage.h"
+#include "NFCManager.h"
+#include "NFCUtil.h"
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+namespace {
+const int RECORD_TYPE_TEXT = 0x54;
+const int RECORD_TYPE_URI = 0x55;
+}
+
+NdefMessage::NdefMessage()
+{
+    LOGD("Entered");
+}
+
+NdefMessage::NdefMessage(unsigned char* data, unsigned long size)
+{
+    LOGD("Entered");
+    nfc_ndef_message_h message = NULL;
+
+    int result = nfc_ndef_message_create_from_rawdata(&message, data, size);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't create Ndef Message from data");
+        NFCUtil::throwNFCException(result, "Can't create Ndef Message from data");
+    }
+    toNdefRecords(message);
+
+    if (message) {
+        result = nfc_ndef_message_destroy(message);
+        if (NFC_ERROR_NONE != result) {
+            LOGE("Can't destroy NdefMessage: %d, %s", result,
+                NFCUtil::getNFCErrorMessage(result).c_str());
+        }
+    }
+    message = NULL;
+}
+
+NdefMessage::NdefMessage(NdefRecordPtrVector &records)
+{
+    m_records = records;
+}
+
+NdefMessage::~NdefMessage()
+{
+    LOGD("Entered");
+}
+
+void NdefMessage::toNdefRecords(const nfc_ndef_message_h message)
+{
+    if (NULL != message) {
+        int count;
+        int result = nfc_ndef_message_get_record_count(message, &count);
+        if (NFC_ERROR_NONE != result) {
+            LOGE("Can't get record count: %d, %s", result,
+                NFCUtil::getNFCErrorMessage(result).c_str());
+            NdefRecord::removeMessageHandle(message);
+            NFCUtil::throwNFCException(result, "Can't get record count");
+        }
+        for (int i = 0; i < count; ++i) {
+            NdefRecordPtr record = NdefRecord::getNdefRecord(message, i);
+
+            if (NFCManager::NFC_RECORD_TNF_MIME_MEDIA == record->getTnf()) {
+                NdefRecordPtr media = NdefRecordMedia::getNdefRecord(message, i);
+                m_records.push_back(media);
+                continue;
+            } else if (NFCManager::NFC_RECORD_TNF_WELL_KNOWN == record->getTnf()) {
+                if (!record->getType().empty()) {
+                    if (RECORD_TYPE_TEXT == record->getType()[0]) {
+                        NdefRecordPtr text = NdefRecordText::getNdefRecord(message, i);
+                        m_records.push_back(text);
+                        continue;
+                    }
+                    if (RECORD_TYPE_URI == record->getType()[0]) {
+                        NdefRecordPtr uri = NdefRecordURI::getNdefRecord(message, i);
+                        m_records.push_back(uri);
+                        continue;
+                    }
+                }
+            }
+            m_records.push_back(record);
+        }
+    }
+}
+
+NdefRecordPtrVector NdefMessage::getRecords() const
+{
+    return m_records;
+}
+
+JSObjectRef NdefMessage::getJSRecords(JSContextRef global_ctx)
+{
+    return m_records.getJSArray(global_ctx);
+}
+
+void NdefMessage::setRecords(const NdefRecordPtrVector &records)
+{
+    m_records = records;
+}
+
+long NdefMessage::getRecordsCount()
+{
+    return m_records.size();
+}
+
+nfc_ndef_message_h NdefMessage::toStruct()
+{
+    LOGD("Entered");
+    size_t size = m_records.size();
+
+    if (!size) {
+        LOGE("No records in message");
+        return NULL;
+    }
+
+    nfc_ndef_message_h message = NULL;
+    int result = nfc_ndef_message_create(&message);
+
+    if (NFC_ERROR_NONE != result) {
+        NdefRecord::removeMessageHandle(message);
+        LOGE("Can't create Ndef Message: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Can't create Ndef Message");
+    }
+
+    NdefRecordPtrVector records_vec = m_records;
+    for(size_t i = 0; i < size; ++i) {
+        if (INVALID_STATE == records_vec[i]->getRecordState()) {
+            NdefRecord::removeMessageHandle(message);
+            LOGE("Invalid record state");
+            throw Common::TypeMismatchException("Invalid record state");
+        }
+        nfc_ndef_record_h record_handle = NdefRecord::getHandle(records_vec[i]);
+
+        result = nfc_ndef_message_append_record(message, record_handle);
+        if (NFC_ERROR_NONE != result) {
+            LOGE("%d record can't be inserted: %d, %s", i, result,
+                NFCUtil::getNFCErrorMessage(result).c_str());
+            NdefRecord::removeRecordHandle(record_handle);
+            NdefRecord::removeMessageHandle(message);
+            NFCUtil::throwNFCException(result, "Invalid NDEF Message");
+        }
+    }
+    return message;
+}
+
+UCharVector NdefMessage::toByte()
+{
+    LOGD("Entered");
+
+    nfc_ndef_message_h message = toStruct();
+    if (!message) {
+        return NFCUtil::toVector(NULL,0);
+    }
+
+    unsigned char *raw_data = NULL;
+
+    unsigned int raw_data_size = 0;
+    int result = nfc_ndef_message_get_rawdata(message, &raw_data, &raw_data_size);
+
+    NdefRecord::removeMessageHandle(message);
+    message = NULL;
+
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get serial bytes of NDEF message: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Can't get serial bytes of NDEF message");
+    }
+
+    UCharVector byte_data = NFCUtil::toVector(raw_data, raw_data_size);
+
+    if (raw_data) {
+        free(raw_data);
+    }
+
+    return byte_data;
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NdefMessage.h b/src/NFC/NdefMessage.h
new file mode 100644 (file)
index 0000000..c756e72
--- /dev/null
@@ -0,0 +1,64 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#ifndef __TIZEN_NFC_NDEFMESSAGE_H_
+#define __TIZEN_NFC_NDEFMESSAGE_H_
+
+#include "NdefRecord.h"
+#include "NdefRecordMedia.h"
+#include "NdefRecordText.h"
+#include "NdefRecordURI.h"
+
+#include <nfc.h>
+#include <memory>
+#include <PlatformException.h>
+#include "JSNdefRecord.h"
+#include "JSNdefRecordVector.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NdefMessage;
+typedef std::shared_ptr<NdefMessage> NdefMessagePtr;
+
+class NdefMessage
+{
+public:
+    NdefMessage();
+    NdefMessage(unsigned char* data, unsigned long size);
+    NdefMessage(NdefRecordPtrVector &records);
+    virtual  ~NdefMessage();
+
+    NdefRecordPtrVector getRecords() const;
+    JSObjectRef getJSRecords(JSContextRef global_ctx);
+    void setRecords(const NdefRecordPtrVector &records);
+
+    long getRecordsCount();
+
+    UCharVector toByte();
+    nfc_ndef_message_h toStruct();
+    void toNdefRecords(nfc_ndef_message_h message);
+private:
+    JSNdefRecordVector m_records;
+};
+
+}
+}
+
+#endif /* __TIZEN_NFC_NDEFMESSAGE_H_ */
diff --git a/src/NFC/NdefRecord.cpp b/src/NFC/NdefRecord.cpp
new file mode 100644 (file)
index 0000000..2a157d2
--- /dev/null
@@ -0,0 +1,308 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NdefRecord.h"
+#include "NFCUtil.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+namespace {
+const int TNF_MIN = 0;
+const int TNF_MAX = 6;
+}
+
+NdefRecord::NdefRecord():
+        m_tnf(NFC_RECORD_TNF_UNKNOWN),
+        m_record_type(NFC_RECORD_UNKNOWN),
+        m_record_state(INVALID_STATE)
+{
+    LOGD("Entered");
+}
+
+NdefRecord::NdefRecord(const unsigned char* data,
+        const unsigned long size)
+{
+    LOGD("Entered");
+
+    nfc_ndef_message_h message_handle = NULL;
+
+    int result = nfc_ndef_message_create_from_rawdata(&message_handle, data, size);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't create NdefMessage from data: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Can't create NdefMessage from data");
+    }
+
+    int count;
+    result = nfc_ndef_message_get_record_count(message_handle, &count);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record count: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        removeMessageHandle(message_handle);
+        NFCUtil::throwNFCException(result, "Can't get record count");
+    }
+
+    nfc_ndef_record_h record_handle = NULL;
+    result = nfc_ndef_message_get_record(message_handle, 0, &record_handle);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get NdefRecord: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        removeMessageHandle(message_handle);
+        NFCUtil::throwNFCException(result, "Can't get NdefRecord");
+    }
+
+    m_tnf = getTnfFromHandle(record_handle, message_handle);
+    m_type_name = getTypeNameFromHandle(record_handle, message_handle);
+    m_id = getIdFromHandle(record_handle, message_handle);
+    m_payload = getPayloadFromHandle(record_handle, message_handle);
+    m_record_state = VALID_STATE;
+
+    removeMessageHandle(message_handle);
+}
+
+NdefRecord::NdefRecord(const short tnf,
+        const UCharVector &type,
+        const UCharVector &payload,
+        const UCharVector &id):
+        m_tnf(tnf),
+        m_type_name(type),
+        m_id(id),
+        m_payload(payload),
+        m_record_state(VALID_STATE)
+{
+    LOGD("Entered");
+}
+
+NdefRecord::~NdefRecord()
+{
+    LOGD("Entered");
+}
+
+void NdefRecord::removeMessageHandle(nfc_ndef_message_h message_handle)
+{
+    if (message_handle) {
+        int result = nfc_ndef_message_destroy(message_handle);
+        if (NFC_ERROR_NONE != result) {
+            LOGE("Can't destroy NdefMessage: %d, %s", result,
+                NFCUtil::getNFCErrorMessage(result).c_str());
+        }
+        message_handle = NULL;
+    }
+}
+
+void NdefRecord::removeRecordHandle(nfc_ndef_record_h record_handle)
+{
+    if (record_handle) {
+        int result = nfc_ndef_record_destroy(record_handle);
+        if (NFC_ERROR_NONE != result) {
+            LOGE("Can't destroy NdefMessage: %d, %s", result,
+                NFCUtil::getNFCErrorMessage(result).c_str());
+        }
+        record_handle = NULL;
+    }
+}
+
+short NdefRecord::getTnfFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle)
+{
+    nfc_record_tnf_e tnf;
+    int result = nfc_ndef_record_get_tnf(handle, &tnf);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record's tnf: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        //once record handle must be released - from inherited classes constructors
+        //once record handle cannot be released - from base class constructor
+        if (NULL == message_handle) {
+            removeRecordHandle(handle);
+        }
+        else {
+            removeMessageHandle(message_handle);
+        }
+        NFCUtil::throwNFCException(result, "Can't get record's tnf");
+    }
+
+    return static_cast<short>(tnf);
+}
+
+UCharVector NdefRecord::getTypeNameFromHandle(
+        nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle)
+{
+    unsigned char *type_name;
+    int type_size, result;
+
+    result = nfc_ndef_record_get_type(handle, &type_name, &type_size);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record's type: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        //once record handle must be released - from inherited classes constructors
+        //once record handle cannot be released - from base class constructor
+        if (NULL == message_handle) {
+            removeRecordHandle(handle);
+        }
+        else {
+            removeMessageHandle(message_handle);
+        }
+        NFCUtil::throwNFCException(result, "Can't get record's type");
+    }
+    return NFCUtil::toVector(type_name, type_size);
+}
+
+UCharVector NdefRecord::getIdFromHandle(
+        nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle)
+{
+    unsigned char *id;
+    int id_size, result;
+
+    result = nfc_ndef_record_get_id(handle, &id, &id_size);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record's id: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        //once record handle must be released - from inherited classes constructors
+        //once record handle cannot be released - from base class constructor
+        if (NULL == message_handle) {
+            removeRecordHandle(handle);
+        }
+        else {
+            removeMessageHandle(message_handle);
+        }
+        NFCUtil::throwNFCException(result, "Can't get record's id");
+    }
+
+    return NFCUtil::toVector(id, id_size);
+}
+
+UCharVector NdefRecord::getPayloadFromHandle(
+        nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle)
+{
+    unsigned char *payload;
+    unsigned int payload_size;
+    int result;
+
+    result = nfc_ndef_record_get_payload(handle, &payload, &payload_size);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record's payload: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        //once record handle must be released - from inherited classes constructors
+        //once record handle cannot be released - from base class constructor
+        if (NULL == message_handle) {
+            removeRecordHandle(handle);
+        }
+        else {
+            removeMessageHandle(message_handle);
+        }
+        NFCUtil::throwNFCException(result, "Can't get record's payload");
+    }
+
+    return NFCUtil::toVector(payload, payload_size);
+}
+
+short NdefRecord::getTnf() const
+{
+    return m_tnf;
+}
+
+UCharVector NdefRecord::getType() const
+{
+    return m_type_name;
+}
+
+UCharVector NdefRecord::getPayload() const
+{
+    return m_payload;
+}
+
+UCharVector NdefRecord::getId() const
+{
+    return m_id;
+}
+
+nfc_recordtype_e NdefRecord::getRecordType() const
+{
+    return m_record_type;
+}
+
+nfc_recordstate_e NdefRecord::getRecordState() const
+{
+    return m_record_state;
+}
+
+NdefRecordPtr NdefRecord::getNdefRecord(nfc_ndef_message_h message, const int index)
+{
+    nfc_ndef_record_h record_handle = NULL;
+    int result = nfc_ndef_message_get_record(message, index, &record_handle);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get Ndef Record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        removeMessageHandle(message);
+        NFCUtil::throwNFCException(result, "Can't get Ndef Record");
+    }
+
+    short tnf = getTnfFromHandle(record_handle, message);
+    UCharVector type = getTypeNameFromHandle(record_handle, message);
+    UCharVector payload = getPayloadFromHandle(record_handle, message);
+    UCharVector id = getIdFromHandle(record_handle, message);
+
+    NdefRecordPtr record(new (std::nothrow) NdefRecord(tnf, type, payload, id));
+
+    return record;
+}
+
+nfc_ndef_record_h NdefRecord::getHandle(NdefRecordPtr record_ptr)
+{
+    if ((record_ptr->getTnf() < TNF_MIN) || (record_ptr->getTnf() > TNF_MAX)) {
+        LOGE("Not supported tnf");
+        throw Common::TypeMismatchException("Type mismatch");
+    }
+
+    const int BYTE_ARRAY_MAX = 255;
+
+    nfc_ndef_record_h record_handle = NULL;
+
+    nfc_record_tnf_e tnf = static_cast<nfc_record_tnf_e>(record_ptr->getTnf());
+
+    int type_size = static_cast<int>(record_ptr->getType().size());
+    unsigned int payload_size = record_ptr->getPayload().size();
+    int id_size = static_cast<int>(record_ptr->getId().size());
+
+    int result = nfc_ndef_record_create(&record_handle,
+        tnf,
+        &record_ptr->getType()[0],
+        type_size > BYTE_ARRAY_MAX ? BYTE_ARRAY_MAX : type_size,
+        &record_ptr->getId()[0],
+        id_size > BYTE_ARRAY_MAX ? BYTE_ARRAY_MAX : id_size,
+        &record_ptr->getPayload()[0],
+        payload_size);
+
+    if (NFC_ERROR_NONE != result) {
+        removeRecordHandle(record_handle);
+        LOGE("Can't create Ndef Record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Can't create Ndef Record");
+    }
+    return record_handle;
+}
+
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NdefRecord.h b/src/NFC/NdefRecord.h
new file mode 100644 (file)
index 0000000..f31579a
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NDEFRECORD_H_
+#define __TIZEN_NFC_NDEFRECORD_H_
+
+#include <nfc.h>
+#include <memory>
+#include <vector>
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NdefRecord;
+typedef std::shared_ptr<NdefRecord> NdefRecordPtr;
+typedef std::vector<NdefRecordPtr> NdefRecordPtrVector;
+typedef std::vector<unsigned char> UCharVector;
+
+typedef enum {
+    NFC_RECORD_UNKNOWN,
+    NFC_RECORD_TEXT,
+    NFC_RECORD_URI,
+    NFC_RECORD_MEDIA
+} nfc_recordtype_e;
+
+typedef enum {
+    VALID_STATE,
+    INVALID_STATE
+} nfc_recordstate_e;
+
+class NdefRecord
+{
+public:
+    NdefRecord();
+    NdefRecord(const unsigned char* data, const unsigned long size);
+    NdefRecord(const short tnf,
+            const UCharVector &type,
+            const UCharVector &payload,
+            const UCharVector &id);
+    virtual ~NdefRecord();
+
+    short getTnf() const;
+    UCharVector getType() const;
+    UCharVector getPayload() const;
+    UCharVector getId() const;
+    // function used for checking type of inherited record class
+    nfc_recordtype_e getRecordType() const;
+    nfc_recordstate_e getRecordState() const;
+
+    static NdefRecordPtr getNdefRecord(nfc_ndef_message_h message, const int index);
+    static nfc_ndef_record_h getHandle(NdefRecordPtr record_ptr);
+    static short getTnfFromHandle(nfc_ndef_record_h handle,
+            nfc_ndef_message_h message_handle = NULL);
+    static UCharVector getTypeNameFromHandle(
+            nfc_ndef_record_h handle, nfc_ndef_message_h message_handle = NULL);
+    static UCharVector getIdFromHandle(
+            nfc_ndef_record_h handle, nfc_ndef_message_h message_handle = NULL);
+    static UCharVector getPayloadFromHandle(
+            nfc_ndef_record_h handle, nfc_ndef_message_h message_handle = NULL);
+    static void removeMessageHandle(nfc_ndef_message_h message_handle);
+    static void removeRecordHandle(nfc_ndef_record_h record_handle);
+
+protected:
+    short m_tnf;
+    UCharVector m_type_name;
+    UCharVector m_id;
+    UCharVector m_payload;
+    nfc_recordtype_e m_record_type;
+    nfc_recordstate_e m_record_state;
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_NDEFRECORD_H_
diff --git a/src/NFC/NdefRecordMedia.cpp b/src/NFC/NdefRecordMedia.cpp
new file mode 100644 (file)
index 0000000..1878030
--- /dev/null
@@ -0,0 +1,126 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NdefRecordMedia.h"
+#include "NFCUtil.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+NdefRecordMedia::NdefRecordMedia()
+{
+    LOGD("Entered");
+    m_record_type = NFC_RECORD_MEDIA;
+    m_record_state = INVALID_STATE;
+}
+
+NdefRecordMedia::NdefRecordMedia(const std::string& mime_type, const UCharVector data)
+{
+    LOGD("Entered");
+    m_mime_type = mime_type;
+    m_record_type = NFC_RECORD_MEDIA;
+
+    nfc_ndef_record_h handle = NULL;
+
+    int result = nfc_ndef_record_create_mime(&handle, mime_type.c_str(), &data[0],
+            static_cast<int>(data.size()));
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Unknown error while getting mimeType: %s - %d: %s",
+            mime_type.c_str(), result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Unknown error while getting mimeType");
+    }
+
+    m_tnf = getTnfFromHandle(handle);
+    m_type_name = getTypeNameFromHandle(handle);
+    m_id = getIdFromHandle(handle);
+    m_payload = getPayloadFromHandle(handle);
+    m_record_state = VALID_STATE;
+
+    if (handle) {
+        NdefRecord::removeRecordHandle(handle);
+    }
+}
+
+NdefRecordMedia::~NdefRecordMedia()
+{
+    LOGD("Entered");
+}
+
+std::string NdefRecordMedia::getMimeType()
+{
+    return m_mime_type;
+}
+
+void NdefRecordMedia::setMimeType(std::string mime_type)
+{
+    m_mime_type = mime_type;
+}
+
+std::string NdefRecordMedia::getMimeTypeFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle)
+{
+    char* mime_type = NULL;
+    int result = nfc_ndef_record_get_mime_type(handle, &mime_type);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record's mime_type: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NdefRecord::removeMessageHandle(message_handle);
+        NFCUtil::throwNFCException(result, "Can't get record's mime_type");
+    }
+
+    std::string mime_string(mime_type);
+    free(mime_type);
+    mime_type = NULL;
+    return mime_string;
+}
+
+NdefRecordMediaPtr NdefRecordMedia::getNdefRecord(nfc_ndef_message_h message, const int index)
+{
+    nfc_ndef_record_h record_handle = NULL;
+    //This function just return the pointer of record.
+    int result = nfc_ndef_message_get_record(message, index, &record_handle);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get Ndef Record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        removeMessageHandle(message);
+        NFCUtil::throwNFCException(result, "Can't get Ndef Record");
+    }
+
+    std::string mime_type = getMimeTypeFromHandle(record_handle, message);
+
+    NdefRecordMediaPtr record(new (std::nothrow) NdefRecordMedia());
+
+    if (!record) {
+        LOGE("Can't create NdefRecordMedia: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NdefRecord::removeMessageHandle(message);
+        NFCUtil::throwNFCException(result, "Can't create NdefRecordMedia.");
+    }
+
+    record->setMimeType(mime_type);
+    record->m_tnf = getTnfFromHandle(record_handle, message);
+    record->m_type_name = getTypeNameFromHandle(record_handle, message);
+    record->m_id = getIdFromHandle(record_handle, message);
+    record->m_payload = getPayloadFromHandle(record_handle, message);
+    record->m_record_state = VALID_STATE;
+    return record;
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NdefRecordMedia.h b/src/NFC/NdefRecordMedia.h
new file mode 100644 (file)
index 0000000..ed5d3f9
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NDEFRECORD_MEDIA_H_
+#define __TIZEN_NFC_NDEFRECORD_MEDIA_H_
+
+#include "NdefRecord.h"
+#include <string>
+#include <memory>
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NdefRecordMedia;
+typedef std::shared_ptr<NdefRecordMedia> NdefRecordMediaPtr;
+
+class NdefRecordMedia : public NdefRecord
+{
+public:
+    NdefRecordMedia();
+    NdefRecordMedia(const std::string& mimeType, const UCharVector data);
+    virtual ~NdefRecordMedia();
+
+    std::string getMimeType();
+
+    static NdefRecordMediaPtr getNdefRecord(nfc_ndef_message_h message,
+        const int index);
+    static std::string getMimeTypeFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle = NULL);
+
+protected:
+    void setMimeType(std::string mime_type);
+
+private:
+    std::string m_mime_type;
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_NDEFRECORD_MEDIA_H_
diff --git a/src/NFC/NdefRecordText.cpp b/src/NFC/NdefRecordText.cpp
new file mode 100755 (executable)
index 0000000..19747a5
--- /dev/null
@@ -0,0 +1,199 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NdefRecordText.h"
+#include "NFCUtil.h"
+#include <Logger.h>
+#include <PlatformException.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace NFC {
+
+namespace {
+    const char* NFC_TEXT_UTF16 = "UTF16";
+    const char* NFC_TEXT_UTF8 = "UTF8";
+}
+
+NdefRecordText::NdefRecordText()
+{
+    LOGD("Entered");
+    m_record_type = NFC_RECORD_TEXT;
+    m_record_state = INVALID_STATE;
+}
+
+NdefRecordText::NdefRecordText(const std::string &text,
+        const std::string &language_code,
+        const nfc_encode_type_e encoding)
+{
+    LOGD("Entered");
+
+    m_text = text;
+    m_language_code = language_code;
+    m_encoding = encoding;
+    m_record_type = NFC_RECORD_TEXT;
+
+    nfc_ndef_record_h handle = NULL;
+
+    int result = nfc_ndef_record_create_text(&handle, text.c_str(),
+            language_code.c_str(), encoding);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Unknown error while getting text record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result,"Can't create text record");
+    }
+
+    m_tnf = getTnfFromHandle(handle);
+    m_type_name = getTypeNameFromHandle(handle);
+    m_id = getIdFromHandle(handle);
+    m_payload = getPayloadFromHandle(handle);
+    m_record_state = VALID_STATE;
+
+    if (handle) {
+        NdefRecord::removeRecordHandle(handle);
+    }
+}
+
+NdefRecordText::~NdefRecordText()
+{
+    LOGD("Entered");
+}
+
+std::string NdefRecordText::getText() const
+{
+    return m_text;
+}
+
+std::string NdefRecordText::getLanguageCode() const
+{
+    return m_language_code;
+}
+
+nfc_encode_type_e NdefRecordText::getEncoding() const
+{
+    return m_encoding;
+}
+
+std::string NdefRecordText::convertToTextNfcEncodeUTF(
+    const nfc_encode_type_e type) const
+{
+    switch(type) {
+        case NFC_ENCODE_UTF_16:
+            return NFC_TEXT_UTF16;
+        case NFC_ENCODE_UTF_8:
+            return NFC_TEXT_UTF8;
+        default:
+            LOGE("Invalid encoding type");
+            throw TypeMismatchException("Error while converting encoding");
+    }
+}
+
+nfc_encode_type_e NdefRecordText::convertToNfcEncodeUTF(
+    const std::string& encode_string)
+{
+    if (NFC_TEXT_UTF16 == encode_string) {
+        return NFC_ENCODE_UTF_16;
+    }
+    else {
+        return NFC_ENCODE_UTF_8;
+    }
+}
+
+std::string NdefRecordText::getTextFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle)
+{
+    char* text = NULL;
+    int result = nfc_ndef_record_get_text(handle, &text);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record's text: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NdefRecord::removeMessageHandle(message_handle);
+        NFCUtil::throwNFCException(result, "Can't get record's text");
+    }
+
+    std::string text_string(text);
+    free(text);
+    text = NULL;
+    return text_string;
+}
+
+std::string NdefRecordText::getLanguageCodeFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle)
+{
+    char* language_code = NULL;
+    int result = nfc_ndef_record_get_langcode(handle, &language_code);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record's languageCode: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NdefRecord::removeMessageHandle(message_handle);
+        NFCUtil::throwNFCException(result, "Can't get record's languageCode");
+    }
+
+    std::string language_string(language_code);
+    free(language_code);
+    language_code = NULL;
+    return language_string;
+}
+
+nfc_encode_type_e NdefRecordText::getEncodingFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle)
+{
+    nfc_encode_type_e encoding;
+    int result = nfc_ndef_record_get_encode_type(handle, &encoding);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record's encoding: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NdefRecord::removeMessageHandle(message_handle);
+        NFCUtil::throwNFCException(result, "Can't get record's encoding");
+    }
+
+    return encoding;
+}
+
+NdefRecordTextPtr NdefRecordText::getNdefRecord(nfc_ndef_message_h message, const int index)
+{
+    nfc_ndef_record_h record_handle = NULL;
+    //This function just return the pointer of record.
+    int result = nfc_ndef_message_get_record(message, index, &record_handle);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get Ndef Record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        removeMessageHandle(message);
+        NFCUtil::throwNFCException(result, "Can't get Ndef Record");
+    }
+
+    std::string text = getTextFromHandle(record_handle, message);
+    std::string language_code = getLanguageCodeFromHandle(record_handle, message);
+    nfc_encode_type_e encoding = getEncodingFromHandle(record_handle, message);
+
+
+    NdefRecordTextPtr record(new (std::nothrow) NdefRecordText(text,
+        language_code, encoding));
+
+    if (!record) {
+        LOGE("Can't create NdefRecordText: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NdefRecord::removeMessageHandle(message);
+        NFCUtil::throwNFCException(result, "Can't create NdefRecordText.");
+    }
+
+    return record;
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NdefRecordText.h b/src/NFC/NdefRecordText.h
new file mode 100755 (executable)
index 0000000..41aaedc
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NDEFRECORD_TEXT_H_
+#define __TIZEN_NFC_NDEFRECORD_TEXT_H_
+
+#include "NdefRecord.h"
+#include <string>
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NdefRecordText;
+
+typedef std::shared_ptr<NdefRecordText> NdefRecordTextPtr;
+
+class NdefRecordText : public NdefRecord
+{
+public:
+    NdefRecordText();
+    NdefRecordText(const std::string &text, const std::string &language_code,
+        const nfc_encode_type_e encoding);
+    virtual ~NdefRecordText();
+
+    std::string getText() const;
+    std::string getLanguageCode() const;
+    nfc_encode_type_e getEncoding() const;
+    std::string convertToTextNfcEncodeUTF(const nfc_encode_type_e type) const;
+    static nfc_encode_type_e convertToNfcEncodeUTF(const std::string& encode_string);
+
+    static NdefRecordTextPtr getNdefRecord(nfc_ndef_message_h message,
+        const int index);
+    static std::string getTextFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle = NULL);
+    static std::string getLanguageCodeFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle = NULL);
+    static nfc_encode_type_e getEncodingFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle = NULL);
+private:
+    std::string m_text;
+    std::string m_language_code;
+    nfc_encode_type_e m_encoding;
+
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_NDEFRECORD_TEXT_H_
diff --git a/src/NFC/NdefRecordURI.cpp b/src/NFC/NdefRecordURI.cpp
new file mode 100644 (file)
index 0000000..8a44095
--- /dev/null
@@ -0,0 +1,116 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NdefRecordURI.h"
+#include "NFCUtil.h"
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSWebAPIError.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace NFC {
+
+NdefRecordURI::NdefRecordURI(const std::string &uri)
+{
+    LOGD("Entered");
+
+    m_uri = uri;
+    m_record_type = NFC_RECORD_URI;
+
+    nfc_ndef_record_h handle = NULL;
+
+    int result = nfc_ndef_record_create_uri(&handle, uri.c_str());
+    if(NFC_ERROR_NONE != result) {
+        LOGE("Unknown error while creating NdefRecordURI: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NFCUtil::throwNFCException(result, "Unknown error while creating NdefRecordURI");
+    }
+
+    m_tnf = getTnfFromHandle(handle);
+    m_type_name = getTypeNameFromHandle(handle);
+    m_id = getIdFromHandle(handle);
+    m_payload = getPayloadFromHandle(handle);
+    m_record_state = VALID_STATE;
+
+    if(handle) {
+        NdefRecord::removeRecordHandle(handle);
+    }
+}
+
+NdefRecordURI::~NdefRecordURI()
+{
+    LOGD("Entered");
+}
+
+std::string NdefRecordURI::getURI()
+{
+    return m_uri;
+}
+
+void NdefRecordURI::setURI(std::string uri)
+{
+    m_uri = uri;
+}
+
+std::string NdefRecordURI::getURIFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle)
+{
+    char* uri = NULL;
+    int result = nfc_ndef_record_get_uri(handle, &uri);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get record's uri: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NdefRecord::removeMessageHandle(message_handle);
+        NFCUtil::throwNFCException(result, "Can't get record's uri");
+    }
+
+    std::string uri_string(uri);
+    free(uri);
+    uri = NULL;
+    return uri_string;
+}
+
+NdefRecordURIPtr NdefRecordURI::getNdefRecord(nfc_ndef_message_h message, const int index)
+{
+    nfc_ndef_record_h record_handle = NULL;
+    //This function just return the pointer of record.
+    int result = nfc_ndef_message_get_record(message, index, &record_handle);
+    if (NFC_ERROR_NONE != result) {
+        LOGE("Can't get Ndef Record: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        removeMessageHandle(message);
+        NFCUtil::throwNFCException(result, "Can't get Ndef Record");
+    }
+
+    std::string uri = getURIFromHandle(record_handle, message);
+
+    NdefRecordURIPtr record(new (std::nothrow) NdefRecordURI(uri));
+
+    if (!record) {
+        LOGE("Can't create NdefRecordURI: %d, %s", result,
+            NFCUtil::getNFCErrorMessage(result).c_str());
+        NdefRecord::removeMessageHandle(message);
+        NFCUtil::throwNFCException(result, "Can't create NdefRecordURI.");
+    }
+
+    return record;
+}
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NFC/NdefRecordURI.h b/src/NFC/NdefRecordURI.h
new file mode 100644 (file)
index 0000000..3e2ec93
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NFC_NDEFRECORD_URI_H_
+#define __TIZEN_NFC_NDEFRECORD_URI_H_
+
+#include "NdefRecord.h"
+#include <string>
+#include <memory>
+
+namespace DeviceAPI {
+namespace NFC {
+
+class NdefRecordURI;
+
+typedef std::shared_ptr<NdefRecordURI> NdefRecordURIPtr;
+
+struct NdefRecordURIHolder {
+    NdefRecordURIPtr ptr;
+};
+
+class NdefRecordURI : public NdefRecord
+{
+public:
+    NdefRecordURI(const std::string &uri);
+    virtual ~NdefRecordURI();
+
+    std::string getURI();
+    void setURI(std::string uri);
+
+    static NdefRecordURIPtr getNdefRecord(nfc_ndef_message_h message,
+        const int index);
+    static std::string getURIFromHandle(nfc_ndef_record_h handle,
+        nfc_ndef_message_h message_handle = NULL);
+private:
+    std::string m_uri;
+};
+
+} // NFC
+} // DeviceAPI
+
+#endif // __TIZEN_NFC_NDEFRECORD_URI_H_
diff --git a/src/NFC/config.xml b/src/NFC/config.xml
new file mode 100755 (executable)
index 0000000..2aa1a9c
--- /dev/null
@@ -0,0 +1,32 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-nfc.so</library-name>
+    <feature-install-uri>nfc.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/nfc.common</name>
+        <device-capability>nfc.common</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/nfc.tag</name>
+        <device-capability>nfc.tag</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/nfc.p2p</name>
+        <device-capability>nfc.p2p</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/nfc.admin</name>
+        <device-capability>nfc.admin</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://developer.samsung.com/tizen/privilege/nfc.cardemulation</name>
+        <device-capability>nfc.cardemulation</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/NFC/plugin_config.cpp b/src/NFC/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..2deaac3
--- /dev/null
@@ -0,0 +1,179 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#include <map>
+#include <utility>
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include "plugin_config.h"
+
+#define NFC_FEATURE_API_COMMON "http://tizen.org/privilege/nfc.common"
+#define NFC_FEATURE_API_ADMIN "http://tizen.org/privilege/nfc.admin"
+#define NFC_FEATURE_API_TAG "http://tizen.org/privilege/nfc.tag"
+#define NFC_FEATURE_API_P2P "http://tizen.org/privilege/nfc.p2p"
+#define NFC_FEATURE_API_CARD_EMULATION "http://developer.samsung.com/tizen/privilege/nfc.cardemulation"
+
+#define NFC_DEVICE_CAP_COMMON "nfc.common"
+#define NFC_DEVICE_CAP_ADMIN "nfc.admin"
+#define NFC_DEVICE_CAP_TAG "nfc.tag"
+#define NFC_DEVICE_CAP_P2P "nfc.p2p"
+#define NFC_DEVICE_CAP_CARD_EMULATION "nfc.cardemulation"
+
+namespace DeviceAPI {
+namespace NFC {
+
+const char* NFC_FUNCTION_API_COMMON_FUNCS = "NFCCommonFunctions";
+const char* NFC_FUNCTION_API_ADMIN_FUNCS = "NFCAdminFunctions";
+const char* NFC_FUNCTION_API_TAG_FUNCS = "NFCTagFunctions";
+const char* NFC_FUNCTION_API_P2P_FUNCS = "NFCP2PFunctions";
+const char* NFC_FUNCTION_API_CARD_EMULATION_FUNCS ="NFCCardEmulationFunctions";
+
+static WrtDeviceApis::Commons::FunctionMapping createNFCFunctions();
+
+static WrtDeviceApis::Commons::FunctionMapping NFCFunctions =
+    createNFCFunctions();
+
+DEFINE_FUNCTION_GETTER(NFC, NFCFunctions);
+
+static WrtDeviceApis::Commons::FunctionMapping createNFCFunctions()
+{
+    using namespace WrtDeviceApis::Commons;
+
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_NFC_COMMON, NFC_DEVICE_CAP_COMMON);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_NFC_ADMIN, NFC_DEVICE_CAP_ADMIN);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_NFC_TAG, NFC_DEVICE_CAP_TAG);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_NFC_P2P, NFC_DEVICE_CAP_P2P);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_NFC_CARD_EMULATION, NFC_DEVICE_CAP_CARD_EMULATION);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_NFC_COMMON);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_NFC_COMMON, DEVICE_CAP_NFC_COMMON);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_NFC_ADMIN);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_NFC_ADMIN, DEVICE_CAP_NFC_ADMIN);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_NFC_TAG);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_NFC_TAG, DEVICE_CAP_NFC_TAG);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_NFC_P2P);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_NFC_P2P, DEVICE_CAP_NFC_P2P);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_NFC_CARD_EMULATION);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_NFC_CARD_EMULATION, DEVICE_CAP_NFC_CARD_EMULATION);
+
+    /**
+     * API features
+     */
+    ACE_CREATE_FEATURE(FEATURE_COMMON, NFC_FEATURE_API_COMMON);
+    ACE_CREATE_FEATURE(FEATURE_ADMIN, NFC_FEATURE_API_ADMIN);
+    ACE_CREATE_FEATURE(FEATURE_TAG, NFC_FEATURE_API_TAG);
+    ACE_CREATE_FEATURE(FEATURE_P2P, NFC_FEATURE_API_P2P);
+    ACE_CREATE_FEATURE(FEATURE_CARD_EMULATION, NFC_FEATURE_API_CARD_EMULATION);
+
+    ACE_CREATE_FEATURE_LIST(NFC_FEATURES_NFC_COMMON);
+    ACE_ADD_API_FEATURE(NFC_FEATURES_NFC_COMMON, FEATURE_COMMON);
+
+    ACE_CREATE_FEATURE_LIST(NFC_FEATURES_NFC_ADMIN);
+    ACE_ADD_API_FEATURE(NFC_FEATURES_NFC_ADMIN, FEATURE_ADMIN);
+
+    ACE_CREATE_FEATURE_LIST(NFC_FEATURES_NFC_TAG);
+    ACE_ADD_API_FEATURE(NFC_FEATURES_NFC_TAG, FEATURE_TAG);
+
+    ACE_CREATE_FEATURE_LIST(NFC_FEATURES_NFC_P2P);
+    ACE_ADD_API_FEATURE(NFC_FEATURES_NFC_P2P, FEATURE_P2P);
+
+    ACE_CREATE_FEATURE_LIST(NFC_FEATURES_NFC_CARD_EMULATION);
+    ACE_ADD_API_FEATURE(NFC_FEATURES_NFC_CARD_EMULATION, FEATURE_CARD_EMULATION);
+
+   /**
+     * Functions
+     */
+    FunctionMapping NFCMapping;
+
+    AceFunction nfcCommonFuncs = ACE_CREATE_FUNCTION(
+        FUNCTION_NFC_COMMON_FUNCTIONS,
+        NFC_FUNCTION_API_COMMON_FUNCS,
+        NFC_FEATURES_NFC_COMMON,
+        DEVICE_LIST_NFC_COMMON);
+
+    NFCMapping.insert(std::make_pair(
+        NFC_FUNCTION_API_COMMON_FUNCS,
+        nfcCommonFuncs));
+
+    AceFunction nfcAdminFuncs = ACE_CREATE_FUNCTION(
+        FUNCTION_NFC_ADMIN_FUNCTIONS,
+        NFC_FUNCTION_API_ADMIN_FUNCS,
+        NFC_FEATURES_NFC_ADMIN,
+        DEVICE_LIST_NFC_ADMIN);
+
+    NFCMapping.insert(std::make_pair(
+       NFC_FUNCTION_API_ADMIN_FUNCS,
+       nfcAdminFuncs));
+
+    AceFunction nfcTagFuncs = ACE_CREATE_FUNCTION(
+        FUNCTION_NFC_TAG_FUNCTIONS,
+        NFC_FUNCTION_API_TAG_FUNCS,
+        NFC_FEATURES_NFC_TAG,
+        DEVICE_LIST_NFC_TAG);
+
+    NFCMapping.insert(std::make_pair(
+        NFC_FUNCTION_API_TAG_FUNCS,
+        nfcTagFuncs));
+
+    AceFunction nfcP2PFuncs = ACE_CREATE_FUNCTION(
+        FUNCTION_NFC_P2P_FUNCTIONS,
+        NFC_FUNCTION_API_P2P_FUNCS,
+        NFC_FEATURES_NFC_P2P,
+        DEVICE_LIST_NFC_P2P);
+
+    NFCMapping.insert(std::make_pair(
+        NFC_FUNCTION_API_P2P_FUNCS,
+        nfcP2PFuncs));
+
+    AceFunction nfcCardEmulationFuncs = ACE_CREATE_FUNCTION(
+        FUNCTION_NFC_CARD_EMULATION_FUNCTIONS,
+        NFC_FUNCTION_API_CARD_EMULATION_FUNCS,
+        NFC_FEATURES_NFC_CARD_EMULATION,
+        DEVICE_LIST_NFC_CARD_EMULATION);
+
+    NFCMapping.insert(std::make_pair(
+        NFC_FUNCTION_API_CARD_EMULATION_FUNCS,
+        nfcCardEmulationFuncs));
+
+    return NFCMapping;
+}
+
+} // namespace NFC
+} // namespace DeviceAPI
+
+#undef NFC_FEATURE_API_COMMON
+#undef NFC_FEATURE_API_ADMIN
+#undef NFC_FEATURE_API_TAG
+#undef NFC_FEATURE_API_P2P
+#undef NFC_FEATURE_API_CARD_EMULATION
+#undef NFC_DEVICE_CAP_COMMON
+#undef NFC_DEVICE_CAP_ADMIN
+#undef NFC_DEVICE_CAP_TAG
+#undef NFC_DEVICE_CAP_P2P
+#undef NFC_DEVICE_CAP_CARD_EMULATION
diff --git a/src/NFC/plugin_config.h b/src/NFC/plugin_config.h
new file mode 100755 (executable)
index 0000000..b7b6a4c
--- /dev/null
@@ -0,0 +1,45 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _NFC_PLUGIN_CONFIG_H_
+#define _NFC_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace NFC {
+
+extern const char* NFC_FUNCTION_API_COMMON_FUNCS;
+extern const char* NFC_FUNCTION_API_ADMIN_FUNCS;
+extern const char* NFC_FUNCTION_API_TAG_FUNCS;
+extern const char* NFC_FUNCTION_API_P2P_FUNCS;
+extern const char* NFC_FUNCTION_API_CARD_EMULATION_FUNCS;
+
+DECLARE_FUNCTION_GETTER(NFC);
+
+#define NFC_CHECK_ACCESS(functionName)                       \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(                \
+        getNFCFunctionData,             \
+        functionName)
+}
+}
+
+#endif //  _NFC_PLUGIN_CONFIG_H_
diff --git a/src/NFC/plugin_config_impl.h b/src/NFC/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..b5885af
--- /dev/null
@@ -0,0 +1,28 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _NFC_PLUGIN_CONFIG_IMPL_H_
+#define _NFC_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_NFC_NFC_MANAGER_CLASS "nfc"
+#define TIZEN_NFC_NDEF_MESSAGE_INTERFACE "NDEFMessage"
+#define TIZEN_NFC_NDEF_RECORD_INTERFACE "NDEFRecord"
+#define TIZEN_NFC_NDEF_RECORD_TEXT_INTERFACE "NDEFRecordText"
+#define TIZEN_NFC_NDEF_RECORD_URI_INTERFACE "NDEFRecordURI"
+#define TIZEN_NFC_NDEF_RECORD_MEDIA_INTERFACE "NDEFRecordMedia"
+
+#endif // _NFC_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/NFC/plugin_initializer.cpp b/src/NFC/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..61009b1
--- /dev/null
@@ -0,0 +1,150 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+#include <JSStringRefWrapper.h>
+#include <Logger.h>
+#include <Security.h>
+#include <TimeTracer.h>
+
+#include "JSNdefMessage.h"
+#include "JSNdefRecord.h"
+#include "JSNdefRecordText.h"
+#include "JSNdefRecordURI.h"
+#include "JSNdefRecordMedia.h"
+#include "JSNFCManager.h"
+#include "NFCManager.h"
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace NFC {
+
+AceSecurityStatus nfcAceCheckAccessFunction(const char* functionName)
+{
+    return NFC_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerNfcSetter, NFCManager, gSecurityAccessor);
+DEFINE_JSOBJECT_SECURITY_ACCESSOR_SETTER(AceCheckerNfcConstructorSetter, gSecurityAccessor);
+
+class_definition_options_t ClassOptions =
+{
+    JS_CLASS,
+    CREATE_INSTANCE,
+    ALWAYS_NOTICE,
+    USE_OVERLAYED, //ignored
+    AceCheckerNfcSetter,
+    NULL,
+    NULL
+};
+
+class_definition_options_t ConstructorClassOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    ALWAYS_NOTICE,
+    USE_OVERLAYED, //ignored
+    AceCheckerNfcConstructorSetter, //JSWidget::acquireGlobalContext
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[TIZEN\\NFC ] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch(...) {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, nfcAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[TIZEN\\NFC ] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "NFC";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch(...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\NFC] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\NFC] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_NFC_NFC_MANAGER_CLASS,
+        (js_class_template_getter)JSNFCManager::getClassRef,
+        &ClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_NFC_NDEF_MESSAGE_INTERFACE,
+        (js_class_template_getter)JSNdefMessage::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSNdefMessage::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_NFC_NDEF_RECORD_INTERFACE,
+        (js_class_template_getter)JSNdefRecord::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSNdefRecord::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_NFC_NDEF_RECORD_TEXT_INTERFACE,
+        (js_class_template_getter)JSNdefRecordText::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSNdefRecordText::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_NFC_NDEF_RECORD_URI_INTERFACE,
+        (js_class_template_getter)JSNdefRecordURI::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSNdefRecordURI::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_NFC_NDEF_RECORD_MEDIA_INTERFACE,
+        (js_class_template_getter)JSNdefRecordMedia::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSNdefRecordMedia::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_END
+
+} // NFC
+} // DeviceAPI
diff --git a/src/NetworkBearerSelection/CMakeLists.txt b/src/NetworkBearerSelection/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..afda291
--- /dev/null
@@ -0,0 +1,37 @@
+SET(TARGET_NAME ${networkbearerselection_target})
+SET(DESTINATION_NAME ${networkbearerselection_dest})
+
+IF(ENABLE_OPTIONAL_NBS)
+PKG_CHECK_MODULES(platform_pkgs_networkbearerselection REQUIRED capi-network-connection)
+
+INCLUDE_DIRECTORIES(
+    ${TOP}/Common
+    ${platform_pkgs_networkbearerselection_INCLUDE_DIRS}
+)
+
+SET(SRCS
+    NetworkBearerSelectionUtil.cpp
+    INetworkBearerSelection.cpp
+    NetworkBearerSelectionFactory.cpp
+    NetworkBearerSelection.cpp
+    plugin_initializer.cpp
+    plugin_config.cpp
+    JSNetworkBearerSelection.cpp
+    JSNetworkBearerSelectionCallbackManager.cpp
+    NetworkBearerSelectionResponseDispatcher.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${LIBS_COMMON}
+    ${platform_pkgs_networkbearerselection_LIBRARIES}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_NBS)
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/networkbearerselection
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/NetworkBearerSelection/EventNetworkBearerRelease.h b/src/NetworkBearerSelection/EventNetworkBearerRelease.h
new file mode 100755 (executable)
index 0000000..19eef3e
--- /dev/null
@@ -0,0 +1,65 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_NETWORK_BEAR_RELEASE_EVENT_H_
+#define WRTPLUGINS_API_NETWORK_BEAR_RELEASE_EVENT_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+class EventNetworkBearerRelease :
+    public WrtDeviceApis::Commons::IEvent<EventNetworkBearerRelease>
+{
+public:
+    void setNetworkType(const std::string &value)
+    {
+        m_networkType = value;
+    }
+
+    std::string getNetworkType() const
+    {
+        return m_networkType;
+    }
+
+    void setDomainName(const std::string &value)
+    {
+        m_domainName = value;
+    }
+
+    std::string getDomainName() const
+    {
+        return m_domainName;
+    }
+
+    EventNetworkBearerRelease(){}
+
+    ~EventNetworkBearerRelease(){}
+
+private:
+    std::string m_networkType;
+    std::string m_domainName;
+};
+
+typedef std::shared_ptr<EventNetworkBearerRelease> EventNetworkBearerReleasePtr;
+
+}
+}
+
+#endif
diff --git a/src/NetworkBearerSelection/EventNetworkBearerSelection.h b/src/NetworkBearerSelection/EventNetworkBearerSelection.h
new file mode 100755 (executable)
index 0000000..823c1ce
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_NETWORK_BEAR_SELECTION_EVENT_H_
+#define WRTPLUGINS_API_NETWORK_BEAR_SELECTION_EVENT_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include "OnNetworkBearerSelectionStateChanged.h"
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+class EventNetworkBearerSelection :
+    public WrtDeviceApis::Commons::IEvent<EventNetworkBearerSelection>
+{
+public:
+
+    void setNetworkType(const std::string &value)
+    {
+        m_networkType = value;
+    }
+
+    std::string getNetworkType() const
+    {
+        return m_networkType;
+    }
+
+    void setDomainName(const std::string &value)
+    {
+        m_domainName = value;
+    }
+
+    std::string getDomainName() const
+    {
+        return m_domainName;
+    }
+
+    void setEmitter(OnNetworkBearerSelectionStateChangedEmitterPtr value)
+    {
+        m_emitter = value;
+    }
+
+    OnNetworkBearerSelectionStateChangedEmitterPtr getEmitter() const
+    {
+        return m_emitter;
+    }
+
+    EventNetworkBearerSelection(){}
+
+    ~EventNetworkBearerSelection(){}
+
+private:
+    std::string m_networkType;
+    std::string m_domainName;
+    OnNetworkBearerSelectionStateChangedEmitterPtr m_emitter;
+};
+
+typedef std::shared_ptr<EventNetworkBearerSelection> EventNetworkBearerSelectionPtr;
+
+}
+}
+
+#endif
diff --git a/src/NetworkBearerSelection/INetworkBearerSelection.cpp b/src/NetworkBearerSelection/INetworkBearerSelection.cpp
new file mode 100755 (executable)
index 0000000..96dc43d
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "INetworkBearerSelection.h"
+#include "EventNetworkBearerSelection.h"
+#include "EventNetworkBearerRelease.h"
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+using namespace WrtDeviceApis::Commons;
+
+INetworkBearerSelection::INetworkBearerSelection() :
+    EventRequestReceiver<EventNetworkBearerSelection>(ThreadEnum::NULL_THREAD),
+    EventRequestReceiver<EventNetworkBearerRelease>(ThreadEnum::NULL_THREAD)
+{
+}
+
+INetworkBearerSelection::~INetworkBearerSelection()
+{
+}
+
+}
+}
diff --git a/src/NetworkBearerSelection/INetworkBearerSelection.h b/src/NetworkBearerSelection/INetworkBearerSelection.h
new file mode 100755 (executable)
index 0000000..8acfaa4
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_INETWORKBEARERSELECTION_H_
+#define WRTPLUGINS_API_INETWORKBEARERSELECTION_H_
+
+#include <memory>
+#include <Commons/ThreadPool.h>
+#include "EventNetworkBearerSelection.h"
+#include "EventNetworkBearerRelease.h"
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+class EventNetworkBearerSelection;
+class EventNetworkBearerRelease;
+
+typedef std::shared_ptr<EventNetworkBearerSelection> EventNetworkBearerSelectionPtr;
+typedef std::shared_ptr<EventNetworkBearerRelease> EventNetworkBearerReleasePtr;
+
+
+class INetworkBearerSelection :
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventNetworkBearerSelection>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventNetworkBearerRelease>
+{
+  public:
+    virtual ~INetworkBearerSelection();
+    INetworkBearerSelection();
+
+    virtual void requestRouteToHost(const EventNetworkBearerSelectionPtr &event) = 0;
+    virtual void releaseRouteToHost(const EventNetworkBearerReleasePtr &event) = 0;
+    virtual bool checkCellularNetworkEnable() = 0;
+
+  protected:
+    virtual void OnRequestReceived(const EventNetworkBearerSelectionPtr &event) = 0;
+    virtual void OnRequestReceived(const EventNetworkBearerReleasePtr &event) = 0;
+};
+
+typedef std::shared_ptr<INetworkBearerSelection> INetworkBearerSelectionPtr;
+
+}
+}
+
+#endif
diff --git a/src/NetworkBearerSelection/JSNetworkBearerSelection.cpp b/src/NetworkBearerSelection/JSNetworkBearerSelection.cpp
new file mode 100755 (executable)
index 0000000..920cf5a
--- /dev/null
@@ -0,0 +1,350 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <CommonsJavaScript/Converter.h>
+#include "NetworkBearerSelectionFactory.h"
+#include "INetworkBearerSelection.h"
+#include "EventNetworkBearerSelection.h"
+#include "EventNetworkBearerRelease.h"
+#include "OnNetworkBearerSelectionStateChanged.h"
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include "JSNetworkBearerSelection.h"
+#include "JSNetworkBearerSelectionCallbackManager.h"
+#include "NetworkBearerSelectionResponseDispatcher.h"
+#include "plugin_config.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+using namespace std;
+
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+JSClassDefinition JSNetworkBearerSelection::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "NetworkBearerSelection",
+    NULL,
+    NULL,
+    m_function,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+JSStaticFunction JSNetworkBearerSelection::m_function[] = {
+    {
+        "requestRouteToHost",
+        JSNetworkBearerSelection::requestRouteToHost,
+        kJSPropertyAttributeNone
+    },
+    {
+        "releaseRouteToHost",
+        JSNetworkBearerSelection::releaseRouteToHost,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSNetworkBearerSelection::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNetworkBearerSelection::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSNetworkBearerSelection::m_jsClassRef =
+    JSClassCreate(JSNetworkBearerSelection::getClassInfo());
+
+void JSNetworkBearerSelection::initialize(JSContextRef context,
+    JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        INetworkBearerSelectionPtr NetworkBearers(
+            NetworkBearerSelectionFactory::getInstance().getNetworkBearerSelections());
+        JSNetworkBearerSelectionPriv* priv =
+            new JSNetworkBearerSelectionPriv(context, NetworkBearers);
+
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            LOGE("Object can't store private data.");
+            delete priv;
+        }
+        LOGD("JSNetworkBearerSelection::initialize ");
+    } else {
+        LOGD("Private object already set.");
+    }
+}
+
+void JSNetworkBearerSelection::finalize(JSObjectRef object)
+{
+    JSNetworkBearerSelectionPriv* priv =
+        static_cast<JSNetworkBearerSelectionPriv*>(JSObjectGetPrivate(object));
+
+    JSObjectSetPrivate(object, NULL);
+    LOGD("Deleting gallery");
+    delete priv;
+}
+
+JSValueRef JSNetworkBearerSelection::requestRouteToHost(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("enter");
+    JSNetworkBearerSelectionPriv *priv =
+        static_cast<JSNetworkBearerSelectionPriv*>(JSObjectGetPrivate(thisObject));
+
+    Converter converter(context);
+    Validator check(context, exception);
+
+    AceSecurityStatus status =
+        NETWORKBEARERSELECTION_CHECK_ACCESS(
+            NETWORKBEARERSELECTION_FUNCTION_API_REQUEST_ROUTE_TO_HOST);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    if (!priv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Wrong Object");
+    }
+
+    if (argumentCount < 3) {
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type missmatch error");
+    }
+    if (argumentCount == 4) {
+        if (check.isCallback(arguments[3])) {
+            LOGD("arguments 3 is callback");
+        } else if (!JSValueIsNull(context, arguments[3])) {
+            return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type missmatch error");
+        }
+    }
+
+    JSValueRef onsuccess = NULL;
+    JSValueRef onpaused = NULL;
+    JSValueRef onresumed = NULL;
+    JSValueRef ondisconnected = NULL;
+
+    Try {
+        JSObjectRef callbackObject = converter.toJSObjectRef(arguments[2]);
+
+        onsuccess = JSUtils::getJSPropertyOrUndefined(context, callbackObject,
+            "onsuccess");
+        if (check.isNullOrUndefined(onsuccess))
+            onsuccess = NULL;
+        else if (!check.isCallback(onsuccess)) {
+            ThrowMsg(ConversionException,
+                "2nd argument's onsuccess attribute is not a 'function'");
+        }
+
+        onpaused = JSUtils::getJSPropertyOrUndefined(context, callbackObject,
+            "onpaused");
+        if (check.isNullOrUndefined(onpaused))
+            onpaused = NULL;
+        else if (!check.isCallback(onpaused)) {
+            ThrowMsg(ConversionException,
+                "2nd argument's onsuccess attribute is not a 'function'");
+        }
+
+        onresumed = JSUtils::getJSPropertyOrUndefined(context, callbackObject,
+            "onresumed");
+        if (check.isNullOrUndefined(onresumed))
+            onresumed = NULL;
+        else if (!check.isCallback(onresumed)) {
+            ThrowMsg(ConversionException,
+                "2nd argument's onsuccess attribute is not a 'function'");
+        }
+
+        ondisconnected = JSUtils::getJSPropertyOrUndefined(context,
+            callbackObject, "ondisconnected");
+        if (check.isNullOrUndefined(ondisconnected))
+            ondisconnected = NULL;
+        else if (!check.isCallback(ondisconnected)) {
+            ThrowMsg(ConversionException,
+                "2nd argument's onsuccess attribute is not a 'function'");
+        }
+
+        if( onsuccess == NULL && onpaused == NULL && onresumed == NULL &&
+            ondisconnected == NULL ) {
+            ThrowMsg(ConversionException, "2nd argument is not a callback'");
+        }
+
+    } Catch(ConversionException) {
+        LOGE("Error on conversion : %s", _rethrown_exception.GetMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR,
+            _rethrown_exception.GetMessage());
+    }
+
+    JSNetworkBearerSelectionCallbackManagerPtr callbackManager =
+        JSNetworkBearerSelectionCallbackManager::createObject(priv->getContext());
+
+    std::string networkType = converter.toString(arguments[0]);
+    std::string domainName = converter.toString(arguments[1]);
+    if (strcmp(networkType.c_str(), "CELLULAR") != 0) {
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type missmatch error");
+    }
+
+    callbackManager->setOnSuccess(onsuccess);
+    callbackManager->setOnPaused(onpaused);
+    callbackManager->setOnResumed(onresumed);
+    callbackManager->setOnDisconneced(ondisconnected);
+    if(argumentCount > 3)
+        callbackManager->setOnError(arguments[3]);
+
+    Try {
+        INetworkBearerSelectionPtr NetworkBearerSelections(priv->getObject());
+
+        EventNetworkBearerSelectionPtr dplEvent(
+            new EventNetworkBearerSelection());
+        OnNetworkBearerSelectionStateChangedEmitterPtr emitter(
+            new OnNetworkBearerSelectionStateChangedEmitter());
+
+        emitter->setEventPrivateData(std::static_pointer_cast<IEventPrivateData>(
+            callbackManager));
+        emitter->setListener(
+            &NetworkBearerSelectionResponseDispatcher::getInstance());
+
+        if (NetworkBearerSelections->checkCellularNetworkEnable()) {
+
+            dplEvent->setNetworkType(networkType);
+            dplEvent->setDomainName(domainName);
+            dplEvent->setEmitter(emitter);
+            dplEvent->setForAsynchronousCall(
+                &NetworkBearerSelectionResponseDispatcher::getInstance());
+
+            NetworkBearerSelections->requestRouteToHost(dplEvent);
+        } else {
+            callbackManager->callOnError(
+                JSWebAPIErrorFactory::makeErrorObject(context,
+                    JSWebAPIErrorFactory::NETWORK_ERROR, "Network error"));
+        }
+    }
+
+    Catch(WrtDeviceApis::Commons::Exception) {
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSNetworkBearerSelection::releaseRouteToHost(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef thisObject,
+    size_t argumentCount,
+    const JSValueRef arguments[],
+    JSValueRef* exception)
+{
+    LOGD("enter");
+    JSNetworkBearerSelectionPriv *priv =
+        static_cast<JSNetworkBearerSelectionPriv*>(JSObjectGetPrivate(thisObject));
+    Converter converter(context);
+    Validator check(context, exception);
+
+    AceSecurityStatus status = NETWORKBEARERSELECTION_CHECK_ACCESS(
+        NETWORKBEARERSELECTION_FUNCTION_API_RELEASE_ROUTE_TO_HOST);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    if (!priv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Wrong Object");
+    }
+    if (argumentCount < 3) {
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR,
+            "Type missmatch error");
+    }
+    if (!check.isCallback(arguments[2])) {
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR,
+            "Type missmatch error");
+    }
+
+    std::string networkType = converter.toString(arguments[0]);
+    std::string domainName = converter.toString(arguments[1]);
+    if (strcmp(networkType.c_str(), "CELLULAR") != 0) {
+        return JSWebAPIErrorFactory::postException(context, exception,
+            JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR,
+            "Type missmatch error");
+    }
+
+    JSValueRef onSuccessForCbm = NULL, onErrorForCbm = NULL;
+    onSuccessForCbm = arguments[2];
+    if (argumentCount > 3) {
+        if (check.isCallback(arguments[3])) {
+            onErrorForCbm = arguments[3];
+        } else if (!JSValueIsNull(context, arguments[3])) {
+            return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR,
+                "Type missmatch error");
+        }
+    }
+    JSCallbackManagerPtr callbackManager(JSCallbackManager::createObject(
+        priv->getContext(), onSuccessForCbm, onErrorForCbm, true, true));
+    callbackManager->setObject(thisObject);
+
+    Try {
+        INetworkBearerSelectionPtr NetworkBearerSelections(priv->getObject());
+        EventNetworkBearerReleasePtr dplEvent(new EventNetworkBearerRelease());
+        dplEvent->setNetworkType(networkType);
+        dplEvent->setDomainName(domainName);
+        dplEvent->setPrivateData(
+            std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        dplEvent->setForAsynchronousCall(
+            &NetworkBearerSelectionResponseDispatcher::getInstance());
+
+        NetworkBearerSelections->releaseRouteToHost(dplEvent);
+    }
+
+    Catch(WrtDeviceApis::Commons::Exception) {
+        return JSWebAPIErrorFactory::postException(
+            context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR,
+            "Unknown error");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+}
+}
diff --git a/src/NetworkBearerSelection/JSNetworkBearerSelection.h b/src/NetworkBearerSelection/JSNetworkBearerSelection.h
new file mode 100755 (executable)
index 0000000..83664c2
--- /dev/null
@@ -0,0 +1,56 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_TIZEN1_0_JS_NETWORK_BEARER_SELECTION_H_
+#define WRTPLUGINS_TIZEN1_0_JS_NETWORK_BEARER_SELECTION_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "INetworkBearerSelection.h"
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObjectT<INetworkBearerSelectionPtr>::Type
+JSNetworkBearerSelectionPriv;
+
+class JSNetworkBearerSelection
+{
+  public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+  private:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef requestRouteToHost(JSContextRef context, JSObjectRef object, JSObjectRef thisObject,
+            size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+    static JSValueRef releaseRouteToHost(JSContextRef context, JSObjectRef object, JSObjectRef thisObject,
+            size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+    static JSClassDefinition m_classInfo;
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+}
+}
+
+#endif
diff --git a/src/NetworkBearerSelection/JSNetworkBearerSelectionCallbackManager.cpp b/src/NetworkBearerSelection/JSNetworkBearerSelectionCallbackManager.cpp
new file mode 100644 (file)
index 0000000..9554405
--- /dev/null
@@ -0,0 +1,297 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSNetworkBearerSelectionCallbackManager.h"
+#include <WebKitProxy.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+JSNetworkBearerSelectionCallbackManagerPtr
+JSNetworkBearerSelectionCallbackManager::createObject(JSContextRef context)
+{
+    return JSNetworkBearerSelectionCallbackManagerPtr(
+        new JSNetworkBearerSelectionCallbackManager(context));
+}
+
+JSNetworkBearerSelectionCallbackManager::JSNetworkBearerSelectionCallbackManager(
+    JSContextRef context,
+    JSObjectRef onSuccess,
+    JSObjectRef onPaused,
+    JSObjectRef onResumed,
+    JSObjectRef onDisconnected,
+    JSObjectRef onError ) :
+    m_onSuccess(NULL),
+    m_onPaused(NULL),
+    m_onResumed(NULL),
+    m_onDisconnected(NULL),
+    m_onError(NULL),
+    m_context(context),
+    m_object(NULL)
+{
+    setOnSuccess(onSuccess);
+    setOnPaused(onPaused);
+    setOnResumed(onResumed);
+    setOnDisconneced(onDisconnected);
+    setOnError(onError);
+}
+
+JSNetworkBearerSelectionCallbackManager::~JSNetworkBearerSelectionCallbackManager()
+{
+    if(m_onSuccess)
+    {
+        JSValueUnprotect(m_context, m_onSuccess);
+    }
+
+    if(m_onPaused)
+    {
+        JSValueUnprotect(m_context, m_onPaused);
+    }
+
+    if(m_onResumed)
+    {
+        JSValueUnprotect(m_context, m_onResumed);
+    }
+
+    if(m_onDisconnected)
+    {
+        JSValueUnprotect(m_context, m_onDisconnected);
+    }
+
+    if(m_onError)
+    {
+        JSValueUnprotect(m_context, m_onError);
+    }
+}
+
+void JSNetworkBearerSelectionCallbackManager::setOnSuccess(JSValueRef onSuccess)
+{
+    if (onSuccess)
+    {
+        if (m_onSuccess != NULL)
+        {
+            JSValueUnprotect(m_context, m_onSuccess);
+        }
+
+        m_onSuccess = JSValueToObject( m_context, onSuccess, NULL );
+
+        if (m_onSuccess != NULL)
+        {
+            JSValueProtect(m_context, m_onSuccess);
+        }
+    }
+}
+
+JSValueRef JSNetworkBearerSelectionCallbackManager::getOnSuccess() const
+{
+    return m_onSuccess;
+}
+
+void JSNetworkBearerSelectionCallbackManager::setOnPaused(JSValueRef onPaused)
+{
+    if (onPaused)
+    {
+        if (m_onPaused != NULL)
+        {
+            JSValueUnprotect(m_context, m_onPaused);
+        }
+
+        m_onPaused = JSValueToObject( m_context, onPaused, NULL );
+
+        if (m_onPaused != NULL)
+        {
+            JSValueProtect(m_context, m_onPaused);
+        }
+    }
+}
+
+JSValueRef JSNetworkBearerSelectionCallbackManager::getOnPaused() const
+{
+    return m_onPaused;
+}
+
+void JSNetworkBearerSelectionCallbackManager::setOnResumed(JSValueRef onResumed)
+{
+    if (onResumed)
+    {
+        if (m_onResumed != NULL)
+        {
+            JSValueUnprotect(m_context, m_onResumed);
+        }
+
+        m_onResumed = JSValueToObject( m_context, onResumed, NULL );
+
+        if (m_onResumed != NULL)
+        {
+            JSValueProtect(m_context, m_onResumed);
+        }
+    }
+}
+
+JSValueRef JSNetworkBearerSelectionCallbackManager::getOnResumed() const
+{
+    return m_onResumed;
+}
+
+void JSNetworkBearerSelectionCallbackManager::setOnDisconneced(
+    JSValueRef onDisconnected)
+{
+    if (onDisconnected)
+    {
+        if (m_onDisconnected != NULL)
+        {
+            JSValueUnprotect(m_context, m_onDisconnected);
+        }
+
+        m_onDisconnected = JSValueToObject( m_context, onDisconnected, NULL );
+
+        if (m_onDisconnected != NULL)
+        {
+            JSValueProtect(m_context, m_onDisconnected);
+        }
+    }
+}
+
+JSValueRef JSNetworkBearerSelectionCallbackManager::getOnDisconneced() const
+{
+    return m_onDisconnected;
+}
+
+void JSNetworkBearerSelectionCallbackManager::setOnError(JSValueRef onError)
+{
+    if (onError)
+    {
+        if (m_onError != NULL)
+        {
+            JSValueUnprotect(m_context, m_onError);
+        }
+
+        m_onError = JSValueToObject(m_context, onError, NULL);
+
+        if (m_onError != NULL)
+        {
+            JSValueProtect(m_context, m_onError);
+        }
+    }
+}
+
+JSValueRef JSNetworkBearerSelectionCallbackManager::getOnError() const
+{
+    return m_onError;
+}
+
+void JSNetworkBearerSelectionCallbackManager::setContext(JSContextRef context)
+{
+    m_context = context;
+}
+
+void JSNetworkBearerSelectionCallbackManager::setObject(JSObjectRef object)
+{
+    m_object = object;
+}
+
+JSObjectRef JSNetworkBearerSelectionCallbackManager::getObject() const
+{
+    return m_object;
+}
+
+void JSNetworkBearerSelectionCallbackManager::callOnSuccess()
+{
+    if (m_onSuccess == NULL)
+    {
+        return;
+    }
+
+    makeCallback(m_context, NULL, m_onSuccess, "onsuccess", NULL, 0);
+}
+
+void JSNetworkBearerSelectionCallbackManager::callOnPaused()
+{
+    if (m_onPaused == NULL)
+    {
+        return;
+    }
+
+    makeCallback(m_context, NULL, m_onPaused, "onpaused", NULL, 0);
+}
+
+void JSNetworkBearerSelectionCallbackManager::callOnResumed()
+{
+    if (m_onResumed == NULL)
+    {
+        return;
+    }
+
+    makeCallback(m_context, NULL, m_onResumed, "onresumed", NULL, 0);
+}
+
+void JSNetworkBearerSelectionCallbackManager::callOnDisconnected()
+{
+    if (m_onDisconnected == NULL)
+    {
+        return;
+    }
+
+    makeCallback(m_context, NULL, m_onDisconnected, "ondisconnected", NULL, 0);
+}
+
+void JSNetworkBearerSelectionCallbackManager::callOnError(JSValueRef error)
+{
+    if (m_onError == NULL)
+    {
+        return;
+    }
+    JSValueRef objParam[1] = { error };
+    makeCallback(m_context, NULL, m_onError, "onError", objParam, 1);
+}
+
+void JSNetworkBearerSelectionCallbackManager::makeCallback(JSContextRef context,
+    JSObjectRef object,
+    JSObjectRef callback,
+    const char *szName,
+    JSValueRef argv[],
+    unsigned argc)
+{
+    if (callback == NULL)
+    {
+        LOGE("callback is NULL");
+        return;
+    }
+
+    if (JSObjectIsFunction(context, callback))
+    {
+        JSValueRef exception = NULL;
+
+        if (argc == 0)
+        {
+            JSObjectCallAsFunction(context, callback, object, 0, NULL, &exception);
+        }
+        else
+        {
+            JSObjectCallAsFunction(context, callback, object, argc, argv, &exception);
+        }
+
+        if (exception)
+            DeviceAPI::Common::WebKitProxy::reportException(context, exception);
+
+        return;
+    }
+}
+
+}
+}
diff --git a/src/NetworkBearerSelection/JSNetworkBearerSelectionCallbackManager.h b/src/NetworkBearerSelection/JSNetworkBearerSelectionCallbackManager.h
new file mode 100755 (executable)
index 0000000..3534f8e
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_CONTACT_JS_NETWORK_BEARER_SELECTION_CALLBACK_MANAGER_H_
+#define _TIZEN_CONTACT_JS_NETWORK_BEARER_SELECTION_CALLBACK_MANAGER_H_
+
+#include <memory>
+#include <Commons/IEvent.h>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+class JSNetworkBearerSelectionCallbackManager;
+typedef std::shared_ptr<JSNetworkBearerSelectionCallbackManager> JSNetworkBearerSelectionCallbackManagerPtr;
+
+class JSNetworkBearerSelectionCallbackManager : public WrtDeviceApis::Commons::IEventPrivateData
+{
+private:
+    JSNetworkBearerSelectionCallbackManager() {}
+    JSNetworkBearerSelectionCallbackManager( JSContextRef context,
+            JSObjectRef onSuccess = NULL,
+            JSObjectRef onPaused = NULL,
+            JSObjectRef onResumed = NULL,
+            JSObjectRef onDisconnected = NULL,
+            JSObjectRef onError = NULL );
+
+public:
+    static JSNetworkBearerSelectionCallbackManagerPtr createObject(JSContextRef context);
+
+    virtual ~JSNetworkBearerSelectionCallbackManager();
+
+    void    setContext(JSContextRef context);
+    JSContextRef getContext() const { return m_context; }
+
+    void    setOnSuccess(JSValueRef onSuccess);
+    JSValueRef getOnSuccess() const;
+    void    setOnPaused(JSValueRef onPaused);
+    JSValueRef getOnPaused() const;
+    void    setOnResumed(JSValueRef onResumed);
+    JSValueRef getOnResumed() const;
+    void    setOnDisconneced(JSValueRef onDisconnected);
+    JSValueRef getOnDisconneced() const;
+    void    setOnError(JSValueRef onError);
+    JSValueRef getOnError() const;
+    void    setObject( JSObjectRef object );
+    JSObjectRef getObject() const;
+
+    void    callOnSuccess();
+    void    callOnPaused();
+    void    callOnResumed();
+    void    callOnDisconnected();
+    void    callOnError(JSValueRef error);
+
+private:
+    void    makeCallback(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef callback,
+            const char *szName,
+            JSValueRef argv[],
+            unsigned argc);
+
+    JSObjectRef  m_onSuccess;
+    JSObjectRef  m_onPaused;
+    JSObjectRef  m_onResumed;
+    JSObjectRef  m_onDisconnected;
+    JSObjectRef  m_onError;
+    JSContextRef m_context;
+    JSObjectRef  m_object;
+};
+
+}
+}
+
+#endif
diff --git a/src/NetworkBearerSelection/NetworkBearerSelection.cpp b/src/NetworkBearerSelection/NetworkBearerSelection.cpp
new file mode 100755 (executable)
index 0000000..a5d6d89
--- /dev/null
@@ -0,0 +1,528 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/Exception.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "OnNetworkBearerSelectionStateChanged.h"
+#include "NetworkBearerSelection.h"
+#include "NetworkBearerSelectionUtil.h"
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace WrtDeviceApis::Commons;
+
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+static void connection_state_changed_callback(
+    connection_profile_state_e state, void* user_data)
+{
+    LOGD("enter");
+    if(user_data != NULL) {
+        LOGD("Callback registration Succeeded");
+        if (state == CONNECTION_PROFILE_STATE_ASSOCIATION) {
+            LOGD("association state");
+            return;
+        }
+
+        NewtorkBearerSelectionPendingEvent *pendingEvent =
+            (NewtorkBearerSelectionPendingEvent *)user_data;
+        NetworkBearerSelection *networkBearerSelection =
+            (NetworkBearerSelection *)pendingEvent->getThisObject();
+        EventNetworkBearerSelectionPtr event = pendingEvent->getEvent();
+
+        if (state == CONNECTION_PROFILE_STATE_DISCONNECTED) {
+            networkBearerSelection->makeRequestCallback(event,
+                CONNECTION_STATE_DISCONNECTED);
+            delete pendingEvent;
+            pendingEvent = NULL;
+            user_data = NULL;
+        }
+
+        user_data = NULL;
+    }
+}
+
+static void connection_opened_callback(connection_error_e result,
+    void* user_data)
+{
+    LOGD("result : %d", result);
+    if (result != CONNECTION_ERROR_NONE) {
+        LOGE("%d: %s", result, NetworkBearerSelectionUtil::
+            getNetworkBearerSelectionErrorMessage(result).c_str());
+        return;
+    }
+
+    LOGD("Connection open Succeeded");
+    if(user_data != NULL) {
+        NewtorkBearerSelectionPendingEvent *pendingEvent =
+            (NewtorkBearerSelectionPendingEvent *)user_data;
+        NetworkBearerSelection *networkBearerSelection =
+            (NetworkBearerSelection *)pendingEvent->getThisObject();
+        EventNetworkBearerSelectionPtr event = pendingEvent->getEvent();
+
+        networkBearerSelection->registStateChangeListener(event);
+
+        delete pendingEvent;
+        pendingEvent = NULL;
+        user_data = NULL;
+    }
+}
+
+static void connection_closed_callback(connection_error_e result,
+    void* user_data)
+{
+    LOGD("result : %d", result);
+    if (result != CONNECTION_ERROR_NONE) {
+        LOGE("%d: %s", result, NetworkBearerSelectionUtil::
+            getNetworkBearerSelectionErrorMessage(result).c_str());
+        return;
+    }
+
+    LOGD("Connection close Succeeded");
+    if (user_data != NULL) {
+        NewtorkBearerReleasePendingEvent *pendingEvent =
+            (NewtorkBearerReleasePendingEvent *)user_data;
+        NetworkBearerSelection *networkBearerSelection =
+            (NetworkBearerSelection *)pendingEvent->getThisObject();
+        EventNetworkBearerReleasePtr event = pendingEvent->getEvent();
+
+        networkBearerSelection->deregistStateChangeListener(event);
+
+        delete pendingEvent;
+        pendingEvent = NULL;
+        user_data = NULL;
+    }
+}
+
+static void connection_closed_callback2(connection_error_e result,
+    void* user_data)
+{
+    LOGD("enter");
+    if (result != CONNECTION_ERROR_NONE) {
+        LOGE("%d: %s", result, NetworkBearerSelectionUtil::
+            getNetworkBearerSelectionErrorMessage(result).c_str());
+        return;
+    }
+    LOGD("Connection close Succeeded");
+}
+
+NetworkBearerSelection::NetworkBearerSelection() :
+    m_connectionHandle(NULL),
+    m_profileHandle(NULL),
+    m_connectionState(NETWORK_UNKNOWN),
+    m_isConnectionOpen(false)
+{
+    int ret = connection_create(&m_connectionHandle);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+            getNetworkBearerSelectionErrorMessage(ret).c_str());
+        m_connectionHandle = NULL;
+        return;
+    }
+
+    LOGD("Client registration success");
+}
+
+NetworkBearerSelection::~NetworkBearerSelection()
+{
+    int ret = 0;
+    if (m_profileHandle) {
+        ret = connection_profile_unset_state_changed_cb(m_profileHandle);
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                getNetworkBearerSelectionErrorMessage(ret).c_str());
+        }
+        ret = connection_profile_destroy(m_profileHandle);
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                getNetworkBearerSelectionErrorMessage(ret).c_str());
+        }
+        m_profileHandle = NULL;
+    }
+    if (m_connectionHandle) {
+        ret = connection_destroy(m_connectionHandle);
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                getNetworkBearerSelectionErrorMessage(ret).c_str());
+        }
+        m_connectionHandle = NULL;
+    }
+}
+
+void NetworkBearerSelection::requestRouteToHost(
+    const EventNetworkBearerSelectionPtr &event)
+{
+    EventRequestReceiver<EventNetworkBearerSelection>::PostRequest(event);
+}
+
+void NetworkBearerSelection::releaseRouteToHost(
+    const EventNetworkBearerReleasePtr &event)
+{
+    EventRequestReceiver<EventNetworkBearerRelease>::PostRequest(event);
+}
+
+void NetworkBearerSelection::OnRequestReceived(
+    const EventNetworkBearerSelectionPtr &event)
+{
+    LOGD("m_connectionState : %d", m_connectionState);
+    connection_profile_h profileHandle;
+    char* currentProfileName = NULL;
+    char* defaultProfileName = NULL;
+    int ret = 0;
+
+    if (m_connectionState == NETWORK_CONNECTED) {
+        LOGD("connection is already opened.");
+        for (auto it = m_domainName.begin(); it != m_domainName.end(); it++) {
+            if ((*it).compare(event->getDomainName()) == 0) {
+                LOGD("Same domain name is exist in list.");
+                makeRequestCallback(event, CONNECTION_STATE_CONNECTED);
+                return;
+            }
+        }
+    }
+
+    if (m_profileHandle) {
+        ret = connection_profile_destroy(m_profileHandle);
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                getNetworkBearerSelectionErrorMessage(ret).c_str());
+        }
+        m_profileHandle = NULL;
+    }
+
+    ret = connection_get_default_cellular_service_profile(m_connectionHandle,
+        CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET, &m_profileHandle);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+            getNetworkBearerSelectionErrorMessage(ret).c_str());
+        makeRequestCallback(event, CONNECTION_STATE_PLATFORM_ERROR);
+        return;
+    }
+
+    ret = connection_profile_get_name(m_profileHandle, &defaultProfileName);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+            getNetworkBearerSelectionErrorMessage(ret).c_str());
+    }
+
+    if (defaultProfileName == NULL) {
+        LOGE("default profile is not exist.");
+        makeRequestCallback(event, CONNECTION_STATE_PLATFORM_ERROR);
+        return;
+    }
+
+    ret = connection_get_current_profile(m_connectionHandle, &profileHandle);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+            getNetworkBearerSelectionErrorMessage(ret).c_str());
+        makeRequestCallback(event, CONNECTION_STATE_PLATFORM_ERROR);
+        return;
+    }
+    ret = connection_profile_get_name(profileHandle, &currentProfileName);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+            getNetworkBearerSelectionErrorMessage(ret).c_str());
+    }
+
+    if (currentProfileName == NULL) {
+        LOGE("current profile is not exist.");
+        makeRequestCallback(event, CONNECTION_STATE_PLATFORM_ERROR);
+        return;
+    }
+
+    if (strcmp(defaultProfileName, currentProfileName) != 0) {
+        NewtorkBearerSelectionPendingEvent *pendingEvent =
+            new NewtorkBearerSelectionPendingEvent((void *)this, event);
+
+        ret = connection_open_profile(m_connectionHandle, m_profileHandle,
+            connection_opened_callback, pendingEvent);
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                getNetworkBearerSelectionErrorMessage(ret).c_str());
+            makeRequestCallback(event, CONNECTION_STATE_PLATFORM_ERROR);
+
+            delete pendingEvent;
+            pendingEvent = NULL;
+        } else {
+            m_isConnectionOpen = true;
+        }
+    } else {
+        registStateChangeListener(event);
+    }
+
+    free(defaultProfileName);
+    free(currentProfileName);
+}
+
+void NetworkBearerSelection::OnRequestReceived(const EventNetworkBearerReleasePtr &event)
+{
+    LOGD("enter");
+    int ret = 0;
+    for (auto it = m_domainName.begin(); it != m_domainName.end(); it++) {
+        if ((*it).compare(event->getDomainName()) == 0) {
+            LOGD("Same domain name is exist in list.");
+            m_domainName.remove(*it);
+            LOGD("list size : %d", m_domainName.size());
+            if (m_domainName.size() != 0) {
+                continue;
+            }
+
+            if (!m_profileHandle) {
+                event->setExceptionCode(ExceptionCodes::AlreadyInUseException);
+                return;
+            }
+
+            event->switchToManualAnswer();
+
+            ret = connection_profile_unset_state_changed_cb(m_profileHandle);
+            if (ret != CONNECTION_ERROR_NONE) {
+                LOGD("%d: %s", ret, NetworkBearerSelectionUtil::
+                    getNetworkBearerSelectionErrorMessage(ret).c_str());
+
+                if (m_profileHandle) {
+                    connection_profile_destroy(m_profileHandle);
+                    m_profileHandle = NULL;
+                }
+                return;
+            }
+
+            if (!m_isConnectionOpen) {
+                EventRequestReceiver<EventNetworkBearerRelease>::ManualAnswer(event);
+                return;
+            }
+
+            NewtorkBearerReleasePendingEvent *pendingEvent =
+                new NewtorkBearerReleasePendingEvent((void *)this, event);
+
+            ret = connection_close_profile(m_connectionHandle, m_profileHandle,
+                connection_closed_callback, pendingEvent);
+            if (ret != CONNECTION_ERROR_NONE) {
+                LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                    getNetworkBearerSelectionErrorMessage(ret).c_str());
+
+                delete pendingEvent;
+                pendingEvent = NULL;
+                EventRequestReceiver<EventNetworkBearerRelease>::ManualAnswer(event);
+            } else {
+                m_isConnectionOpen = false;
+                deregistStateChangeListener(event);
+            }
+            return;
+        }
+    }
+
+    event->setExceptionCode(ExceptionCodes::InvalidArgumentException);
+}
+
+void NetworkBearerSelection::registStateChangeListener(
+    const EventNetworkBearerSelectionPtr &event)
+{
+    LOGD("enter");
+    char *interfaceName = NULL;
+    char *hostAddr = NULL;
+    struct hostent *host_entry;
+    int ret = 0;
+
+    ret = connection_profile_get_network_interface_name(m_profileHandle,
+        &interfaceName);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+            getNetworkBearerSelectionErrorMessage(ret).c_str());
+
+        if (m_profileHandle) {
+            ret = connection_profile_destroy(m_profileHandle);
+            if (ret != CONNECTION_ERROR_NONE) {
+                LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                    getNetworkBearerSelectionErrorMessage(ret).c_str());
+            }
+            m_profileHandle = NULL;
+        }
+        makeRequestCallback(event, CONNECTION_STATE_PLATFORM_ERROR);
+    }
+    else {
+        LOGD("Interface name : %s", interfaceName);
+    }
+
+    host_entry = gethostbyname(event->getDomainName().c_str());
+
+    if(!host_entry) {
+        LOGD("gethostbyname is failed");
+        makeRequestCallback(event, CONNECTION_STATE_UNKNOWN_ERROR);
+        ret = connection_close_profile(m_connectionHandle, m_profileHandle,
+            connection_closed_callback2, NULL);
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("connection close failed %d: %s", ret,
+                NetworkBearerSelectionUtil::getNetworkBearerSelectionErrorMessage(ret).c_str());
+            makeRequestCallback(event, CONNECTION_STATE_PLATFORM_ERROR);
+        }
+        if (m_profileHandle) {
+            ret = connection_profile_destroy(m_profileHandle);
+            if (ret != CONNECTION_ERROR_NONE) {
+                LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                    getNetworkBearerSelectionErrorMessage(ret).c_str());
+            }
+            m_profileHandle = NULL;
+        }
+        if (interfaceName != NULL) {
+            free(interfaceName);
+            interfaceName = NULL;
+        }
+        return;
+    }
+
+    hostAddr = inet_ntoa( *(struct in_addr*)host_entry->h_addr_list[0]);
+    LOGD("hostAddr : %s", hostAddr);
+
+    NewtorkBearerSelectionPendingEvent *pendingEvent =
+        new NewtorkBearerSelectionPendingEvent((void *)this, event);
+    ret = connection_profile_set_state_changed_cb(m_profileHandle,
+        connection_state_changed_callback, pendingEvent);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("Callback register is failed %d: %s", ret,
+           NetworkBearerSelectionUtil::getNetworkBearerSelectionErrorMessage(ret).c_str());
+        if (m_profileHandle) {
+            ret = connection_profile_destroy(m_profileHandle);
+            if (ret != CONNECTION_ERROR_NONE) {
+                LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                    getNetworkBearerSelectionErrorMessage(ret).c_str());
+            }
+        }
+        delete pendingEvent;
+        pendingEvent = NULL;
+
+        if (interfaceName != NULL) {
+            free(interfaceName);
+            interfaceName = NULL;
+        }
+    } else {
+        ret = connection_add_route(m_connectionHandle, interfaceName, hostAddr);
+        if (interfaceName != NULL) {
+            free(interfaceName);
+            interfaceName = NULL;
+        }
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("add route is failed %d: %s", ret,
+                NetworkBearerSelectionUtil::getNetworkBearerSelectionErrorMessage(ret).c_str());
+            makeRequestCallback(event, CONNECTION_STATE_PLATFORM_ERROR);
+        } else {
+            LOGD("add route is successed.");
+            makeRequestCallback(event, CONNECTION_STATE_CONNECTED);
+        }
+    }
+}
+
+void NetworkBearerSelection::deregistStateChangeListener(
+    const EventNetworkBearerReleasePtr &event)
+{
+    LOGD("enter");
+    int ret = 0;
+    if (m_profileHandle) {
+        ret = connection_profile_destroy(m_profileHandle);
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                getNetworkBearerSelectionErrorMessage(ret).c_str());
+        }
+        m_profileHandle = NULL;
+    }
+    m_connectionState = NETWORK_DISCONNECTED;
+        EventRequestReceiver<EventNetworkBearerRelease>::ManualAnswer(event);
+}
+
+void NetworkBearerSelection::makeRequestCallback(
+    const EventNetworkBearerSelectionPtr &event, connectionStateType state)
+{
+    LOGD("state : %d", state);
+    int ret = 0;
+    OnNetworkBearerSelectionStateChangedEmitterPtr emitter = event->getEmitter();
+    OnNetworkBearerSelectionStateChangedPtr listener(
+        new OnNetworkBearerSelectionStateChanged());
+
+    m_domainName.push_back(event->getDomainName());
+    LOGD("Domain name list size= %d", m_domainName.size());
+    listener->setConnectionStateType(state);
+
+    if (state == CONNECTION_STATE_INVALID_VALUES_ERROR) {
+        m_connectionState = NETWORK_CONNECTION_FAILED;
+        listener->setExceptionCode(ExceptionCodes::InvalidArgumentException);
+    } else if (state == CONNECTION_STATE_PLATFORM_ERROR) {
+        m_connectionState = NETWORK_CONNECTION_FAILED;
+        listener->setExceptionCode(ExceptionCodes::PlatformException);
+    } else if (state == CONNECTION_STATE_DISCONNECTED) {
+        m_connectionState = NETWORK_DISCONNECTED;
+        ret = connection_profile_unset_state_changed_cb(m_profileHandle);
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("unset callback is failed %d: %s", ret,
+                NetworkBearerSelectionUtil::getNetworkBearerSelectionErrorMessage(ret).c_str());
+        }
+        if (m_profileHandle) {
+            ret = connection_profile_destroy(m_profileHandle);
+            if (ret != CONNECTION_ERROR_NONE) {
+                LOGE("%d: %s", ret, NetworkBearerSelectionUtil::
+                    getNetworkBearerSelectionErrorMessage(ret).c_str());
+            }
+            m_profileHandle = NULL;
+        }
+    } else if (state == CONNECTION_STATE_CONNECTED) {
+        m_connectionState = NETWORK_CONNECTED;
+    } else if (state == CONNECTION_STATE_UNKNOWN_ERROR){
+        m_connectionState = NETWORK_CONNECTION_FAILED;
+        listener->setExceptionCode(ExceptionCodes::UnknownException);
+    }
+    emitter->emit(listener);
+}
+
+void NetworkBearerSelection::makeReleaseCallback(
+    const EventNetworkBearerReleasePtr &event)
+{
+    event->setExceptionCode(ExceptionCodes::AlreadyInUseException);
+}
+
+bool NetworkBearerSelection::checkProfileHandle()
+{
+    if(m_profileHandle == NULL) {
+        return true;
+    }
+    return false;
+}
+
+bool NetworkBearerSelection::checkCellularNetworkEnable()
+{
+    connection_cellular_state_e cellularState;
+
+    int ret = connection_get_cellular_state(m_connectionHandle, &cellularState);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("Fail to get Cellular state %d: %s", ret,
+            NetworkBearerSelectionUtil::getNetworkBearerSelectionErrorMessage(ret).c_str());
+        return false;
+    }
+
+    LOGD("celluar network state is %d", cellularState);
+
+    if (cellularState == CONNECTION_CELLULAR_STATE_AVAILABLE ||
+        cellularState == CONNECTION_CELLULAR_STATE_CONNECTED) {
+        return true;
+    }
+    return false;
+}
+
+}
+}
diff --git a/src/NetworkBearerSelection/NetworkBearerSelection.h b/src/NetworkBearerSelection/NetworkBearerSelection.h
new file mode 100755 (executable)
index 0000000..2383c5b
--- /dev/null
@@ -0,0 +1,120 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_PLATFORM_NETWORKBEARERSELECTION_H_
+#define WRTPLUGINS_PLATFORM_NETWORKBEARERSELECTION_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <memory>
+#include <dpl/noncopyable.h>
+#include "NetworkBearerSelectionFactory.h"
+#include "INetworkBearerSelection.h"
+#include "EventNetworkBearerSelection.h"
+#include "EventNetworkBearerRelease.h"
+#include "OnNetworkBearerSelectionStateChanged.h"
+#include <CommonsJavaScript/Converter.h>
+#include <net_connection.h>
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+enum {
+    NETWORK_UNKNOWN = 0,
+    NETWORK_CONNECTED = 1,
+    NETWORK_DISCONNECTED = 2,
+    NETWORK_CONNECTION_FAILED = 3
+};
+
+class NetworkBearerSelection : public INetworkBearerSelection
+{
+    friend class NetworkBearerSelectionFactory;
+    friend class EventNetworkBearerSelection;
+    friend class EventNetworkBearerRelease;
+
+  public:
+    NetworkBearerSelection();
+    virtual ~NetworkBearerSelection();
+    virtual void requestRouteToHost(const EventNetworkBearerSelectionPtr &event);
+    virtual void releaseRouteToHost(const EventNetworkBearerReleasePtr &event);
+    virtual bool checkCellularNetworkEnable();
+    void reLaunchConnection(const EventNetworkBearerSelectionPtr &event);;
+    void removeStateChangeListener(const EventNetworkBearerSelectionPtr &event);
+    void registStateChangeListener(const EventNetworkBearerSelectionPtr &event);
+    void deregistStateChangeListener(const EventNetworkBearerReleasePtr &event);
+    void makeRequestCallback(const EventNetworkBearerSelectionPtr &event, const connectionStateType state);
+    void makeReleaseCallback(const EventNetworkBearerReleasePtr &event);
+    bool checkProfileHandle();
+
+  protected:
+    virtual void OnRequestReceived(const EventNetworkBearerSelectionPtr &event);
+    virtual void OnRequestReceived(const EventNetworkBearerReleasePtr &event);
+
+  private:
+    connection_h m_connectionHandle;
+    connection_profile_h m_profileHandle;
+    std::list<std::string> m_domainName;
+    long m_connectionState;
+    bool m_isConnectionOpen;
+};
+
+class NewtorkBearerSelectionPendingEvent
+{
+  public:
+    NewtorkBearerSelectionPendingEvent(void *thisObject, const EventNetworkBearerSelectionPtr &event) :
+        m_thisObject(thisObject),
+        m_event(event)
+    {
+    }
+
+    virtual ~NewtorkBearerSelectionPendingEvent()
+    {
+    }
+
+    void* getThisObject() const { return m_thisObject; }
+    EventNetworkBearerSelectionPtr getEvent() const { return m_event; }
+
+  private:
+    void *m_thisObject;
+    EventNetworkBearerSelectionPtr m_event;
+};
+
+class NewtorkBearerReleasePendingEvent
+{
+  public:
+    NewtorkBearerReleasePendingEvent(void *thisObject, const EventNetworkBearerReleasePtr &event) :
+        m_thisObject(thisObject),
+        m_event(event)
+    {
+    }
+
+    virtual ~NewtorkBearerReleasePendingEvent()
+    {
+    }
+
+    void* getThisObject() const { return m_thisObject; }
+    EventNetworkBearerReleasePtr getEvent() const { return m_event; }
+
+  private:
+    void *m_thisObject;
+    EventNetworkBearerReleasePtr m_event;
+};
+
+
+}
+}
+
+#endif
diff --git a/src/NetworkBearerSelection/NetworkBearerSelectionFactory.cpp b/src/NetworkBearerSelection/NetworkBearerSelectionFactory.cpp
new file mode 100755 (executable)
index 0000000..ad77ff0
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NetworkBearerSelection.h"
+#include "NetworkBearerSelectionFactory.h"
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+INetworkBearerSelectionPtr
+NetworkBearerSelectionFactory::getNetworkBearerSelections()
+{
+    INetworkBearerSelectionPtr result(new NetworkBearerSelection());
+    return result;
+}
+
+NetworkBearerSelectionFactory&
+NetworkBearerSelectionFactory::getInstance()
+{
+    static NetworkBearerSelectionFactory theInstance;
+    return theInstance;
+}
+
+NetworkBearerSelectionFactory::NetworkBearerSelectionFactory()
+{
+}
+
+}
+}
diff --git a/src/NetworkBearerSelection/NetworkBearerSelectionFactory.h b/src/NetworkBearerSelection/NetworkBearerSelectionFactory.h
new file mode 100755 (executable)
index 0000000..617a1d5
--- /dev/null
@@ -0,0 +1,42 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_NETWORKBEARERSELECTION_FACTORY_H_
+#define WRTPLUGINS_API_NETWORKBEARERSELECTION_FACTORY_H_
+
+#include <dpl/noncopyable.h>
+#include "INetworkBearerSelection.h"
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+class NetworkBearerSelectionFactory : DPL::Noncopyable
+{
+  public:
+    INetworkBearerSelectionPtr getNetworkBearerSelections();
+
+    static NetworkBearerSelectionFactory& getInstance();
+
+  protected:
+    NetworkBearerSelectionFactory();
+};
+
+}
+}
+
+#endif
+
diff --git a/src/NetworkBearerSelection/NetworkBearerSelectionResponseDispatcher.cpp b/src/NetworkBearerSelection/NetworkBearerSelectionResponseDispatcher.cpp
new file mode 100755 (executable)
index 0000000..e00d5b3
--- /dev/null
@@ -0,0 +1,187 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NetworkBearerSelectionResponseDispatcher.h"
+#include "JSNetworkBearerSelectionCallbackManager.h"
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+NetworkBearerSelectionResponseDispatcher&
+NetworkBearerSelectionResponseDispatcher::getInstance()
+{
+    static NetworkBearerSelectionResponseDispatcher instance;
+    return instance;
+}
+
+NetworkBearerSelectionResponseDispatcher::
+NetworkBearerSelectionResponseDispatcher() :
+    NetworkBearerSelectionEventAnswerReceiverRequest(ThreadEnum::NULL_THREAD),
+    NetworkBearerReleaseEventAnswerReceiverRequest(ThreadEnum::NULL_THREAD),
+    OnNetworkBearerSelectionStateChangedListener(ThreadEnum::NULL_THREAD)
+{
+}
+
+NetworkBearerSelectionResponseDispatcher::
+~NetworkBearerSelectionResponseDispatcher()
+{
+}
+
+void NetworkBearerSelectionResponseDispatcher::OnAnswerReceived(
+    const EventNetworkBearerSelectionPtr &event)
+{
+    LOGD("entered");
+}
+
+void NetworkBearerSelectionResponseDispatcher::OnAnswerReceived(
+    const EventNetworkBearerReleasePtr &event)
+{
+    LOGD("entered");
+    JSCallbackManagerPtr callbackManager =
+        std::static_pointer_cast<JSCallbackManager >(event->getPrivateData());
+
+    if (!callbackManager) {
+        LOGE("No listener callback!");
+        return;
+    }
+
+    CHECK_CURRENT_CONTEXT_ALIVE(callbackManager->getContext());
+
+
+    JSContextRef gContext = callbackManager->getContext();
+    JSValueRef error = NULL;
+
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+            break;
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::NOT_FOUND_ERROR, "record not found");
+            break;
+        case ExceptionCodes::InvalidArgumentException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::INVALID_VALUES_ERROR,
+                "DomainName is not setted");
+            break;
+        case ExceptionCodes::ConversionException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong argument");
+            break;
+        case ExceptionCodes::AlreadyInUseException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::INVALID_STATE_ERROR,
+                "Connection is disconnected.");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        return;
+    }
+    callbackManager->callOnSuccess();
+}
+
+
+void NetworkBearerSelectionResponseDispatcher::onAnswerReceived(
+    const OnNetworkBearerSelectionStateChangedPtr& event)
+{
+    LOGD("entered");
+    JSNetworkBearerSelectionCallbackManagerPtr callbackManager =
+        std::static_pointer_cast<JSNetworkBearerSelectionCallbackManager>(
+            event->getPrivateData());
+
+    if (!callbackManager) {
+        LOGE("No listener callback!");
+        return;
+    }
+
+    CHECK_CURRENT_CONTEXT_ALIVE(callbackManager->getContext());
+
+    Try
+    {
+        switch (event->getConnectionStateType()) {
+            case CONNECTION_STATE_CONNECTED:
+                LOGD("success callback");
+                callbackManager->callOnSuccess();
+                break;
+            case CONNECTION_STATE_DISCONNECTED:
+                LOGD("disconnect callback");
+                callbackManager->callOnDisconnected();
+                break;
+            case CONNECTION_STATE_INVALID_VALUES_ERROR:
+            case CONNECTION_STATE_PLATFORM_ERROR:
+            case CONNECTION_STATE_UNKNOWN_ERROR:
+                JSContextRef gContext = callbackManager->getContext();
+                JSValueRef error = NULL;
+
+                if (ExceptionCodes::None != event->getExceptionCode())
+                {
+                    switch (event->getExceptionCode())
+                    {
+                    case ExceptionCodes::PlatformException:
+                        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+                        break;
+                    case ExceptionCodes::NotFoundException:
+                        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                            JSWebAPIErrorFactory::NOT_FOUND_ERROR, "record not found");
+                        break;
+                    case ExceptionCodes::InvalidArgumentException:
+                        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                            JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "Invalid values error");
+                        break;
+                    case ExceptionCodes::ConversionException:
+                        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                            JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong argument");
+                        break;
+                    default:
+                        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                            JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+                        break;
+                    }
+
+                    callbackManager->callOnError(error);
+                    return;
+                }
+                LOGD("error callback");
+                break;
+        }
+    }
+    Catch(Exception)
+    {
+        LOGE("Error during processing answer.");
+    }
+}
+
+}
+}
diff --git a/src/NetworkBearerSelection/NetworkBearerSelectionResponseDispatcher.h b/src/NetworkBearerSelection/NetworkBearerSelectionResponseDispatcher.h
new file mode 100755 (executable)
index 0000000..ff3e414
--- /dev/null
@@ -0,0 +1,61 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _NETWORK_BEARER_SELECTION_RESPONSE_DISPATCHER_H_
+#define _NETWORK_BEARER_SELECTION_RESPONSE_DISPATCHER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <Commons/EventReceiver.h>
+#include <Commons/EventListener.h>
+#include "EventNetworkBearerSelection.h"
+#include "EventNetworkBearerRelease.h"
+#include "OnNetworkBearerSelectionStateChanged.h"
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<EventNetworkBearerSelection>
+NetworkBearerSelectionEventAnswerReceiverRequest;
+
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<EventNetworkBearerRelease>
+NetworkBearerReleaseEventAnswerReceiverRequest;
+
+typedef WrtDeviceApis::Commons::EventListener<OnNetworkBearerSelectionStateChanged>
+OnNetworkBearerSelectionStateChangedListener;
+
+class NetworkBearerSelectionResponseDispatcher :
+    public NetworkBearerSelectionEventAnswerReceiverRequest,
+    public NetworkBearerReleaseEventAnswerReceiverRequest,
+    public OnNetworkBearerSelectionStateChangedListener
+{
+  public:
+    static NetworkBearerSelectionResponseDispatcher& getInstance();
+
+  private:
+    NetworkBearerSelectionResponseDispatcher();
+    virtual ~NetworkBearerSelectionResponseDispatcher();
+
+  protected:
+    void OnAnswerReceived(const EventNetworkBearerSelectionPtr &event);
+    void OnAnswerReceived(const EventNetworkBearerReleasePtr &event);
+    void onAnswerReceived(const OnNetworkBearerSelectionStateChangedPtr& event);
+};
+
+}
+}
+
+#endif
diff --git a/src/NetworkBearerSelection/NetworkBearerSelectionUtil.cpp b/src/NetworkBearerSelection/NetworkBearerSelectionUtil.cpp
new file mode 100644 (file)
index 0000000..3e4c819
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NetworkBearerSelectionUtil.h"
+
+#include <net_connection.h>
+#include <sstream>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+std::string NetworkBearerSelectionUtil::getNetworkBearerSelectionErrorMessage(
+    const int error_code)
+{
+    switch (error_code) {
+        case CONNECTION_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case CONNECTION_ERROR_OUT_OF_MEMORY:
+            return "Out of memory error";
+        case CONNECTION_ERROR_INVALID_OPERATION:
+            return "Invalid Operation";
+        case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
+            return "Address family not supported";
+        case CONNECTION_ERROR_OPERATION_FAILED:
+            return "Operation failed";
+        case CONNECTION_ERROR_ITERATOR_END:
+            return "End of iteration";
+        case CONNECTION_ERROR_NO_CONNECTION:
+            return "There is no connection";
+        case CONNECTION_ERROR_NOW_IN_PROGRESS:
+            return "Now in progress";
+        case CONNECTION_ERROR_ALREADY_EXISTS:
+            return "Already exists";
+        case CONNECTION_ERROR_OPERATION_ABORTED:
+            return "Operation is aborted";
+        case CONNECTION_ERROR_DHCP_FAILED:
+            return "DHCP failed";
+        case CONNECTION_ERROR_INVALID_KEY:
+            return "Invalid key";
+        case CONNECTION_ERROR_NO_REPLY:
+            return "No reply";
+        case CONNECTION_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case CONNECTION_ERROR_NOT_SUPPORTED:
+            return "Not Supported";
+        default:
+            return "Unknown Error";
+    }
+}
+
+}
+}
diff --git a/src/NetworkBearerSelection/NetworkBearerSelectionUtil.h b/src/NetworkBearerSelection/NetworkBearerSelectionUtil.h
new file mode 100644 (file)
index 0000000..a9704cf
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NETWORK_BEARER_SELECTION_UTIL_H_
+#define __TIZEN_NETWORK_BEARER_SELECTION_UTIL_H_
+
+#include <string>
+#include <account.h>
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+class NetworkBearerSelectionUtil {
+public:
+    static void throwNetworkBearerSelectionException(
+        const int error_code, const std::string &hint);
+    static std::string getNetworkBearerSelectionErrorMessage(
+        const int error_code);
+};
+
+} // NetworkBearerSelection
+} // DeviceAPI
+
+#endif // __TIZEN_NETWORK_BEARER_SELECTION_UTIL_H_
diff --git a/src/NetworkBearerSelection/OnNetworkBearerSelectionStateChanged.h b/src/NetworkBearerSelection/OnNetworkBearerSelectionStateChanged.h
new file mode 100755 (executable)
index 0000000..2b63c1a
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _ON_NETWORK_BEARER_SELECTION_STATE_CHANGED_H_
+#define _ON_NETWORK_BEARER_SELECTION_STATE_CHANGED_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+#include <Commons/ListenerEvent.h>
+#include <Commons/Emitters.h>
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+enum connectionStateType {
+    CONNECTION_STATE_DISCONNECTED = 0,
+    CONNECTION_STATE_CONNECTED = 1,
+    CONNECTION_STATE_INVALID_VALUES_ERROR = 2,
+    CONNECTION_STATE_PLATFORM_ERROR = 3,
+    CONNECTION_STATE_UNKNOWN_ERROR = 4
+};
+
+class OnNetworkBearerSelectionStateChanged :
+    public WrtDeviceApis::Commons::ListenerEvent<OnNetworkBearerSelectionStateChanged>
+{
+  public:
+
+    OnNetworkBearerSelectionStateChanged(){
+    }
+    ~OnNetworkBearerSelectionStateChanged() {
+    }
+
+    void setConnectionStateType(connectionStateType state) {
+        m_callbackType = state;
+    }
+
+    connectionStateType getConnectionStateType() {
+        return m_callbackType;
+    }
+
+  private:
+    connectionStateType m_callbackType;
+};
+
+typedef std::shared_ptr<OnNetworkBearerSelectionStateChanged>
+OnNetworkBearerSelectionStateChangedPtr;
+
+typedef WrtDeviceApis::Commons::ListenerEventEmitter<OnNetworkBearerSelectionStateChanged>
+OnNetworkBearerSelectionStateChangedEmitter;
+
+typedef std::shared_ptr<OnNetworkBearerSelectionStateChangedEmitter>
+OnNetworkBearerSelectionStateChangedEmitterPtr;
+
+}
+}
+
+#endif //_ON_POWER_STATE_CHANGED_H_
diff --git a/src/NetworkBearerSelection/config.xml b/src/NetworkBearerSelection/config.xml
new file mode 100755 (executable)
index 0000000..6a2471d
--- /dev/null
@@ -0,0 +1,15 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-networkbearerselection.so</library-name>
+    <feature-install-uri>networkbearerselection.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/networkbearerselection</name>
+        <device-capability>networkbearerselection</device-capability>
+        <Object name="networkbearerselection">
+            <Function name="requestRouteToHost"/>
+            <Function name="releaseRouteToHost"/>
+        </Object>
+    </api-feature>
+</plugin-properties>
diff --git a/src/NetworkBearerSelection/plugin_config.cpp b/src/NetworkBearerSelection/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..92f9455
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <map>
+#include <utility>
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include "plugin_config.h"
+
+#define NETWORKBEARERSELECTION_FEATURE_API "http://tizen.org/privilege/networkbearerselection"
+
+#define NETWORKBEARERSELECTION_DEVICE_CAP "networkbearerselection"
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+const char* NETWORKBEARERSELECTION_FUNCTION_API_REQUEST_ROUTE_TO_HOST = "requestRouteToHost";
+const char* NETWORKBEARERSELECTION_FUNCTION_API_RELEASE_ROUTE_TO_HOST = "releaseRouteToHost";
+
+static WrtDeviceApis::Commons::FunctionMapping createNetworkBearerSelectionFunctions();
+
+static WrtDeviceApis::Commons::FunctionMapping NetworkBearerSelectionFunctions =
+    createNetworkBearerSelectionFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(NetworkBearerSelection, NetworkBearerSelectionFunctions);
+
+#pragma GCC visibility pop
+
+static WrtDeviceApis::Commons::FunctionMapping createNetworkBearerSelectionFunctions()
+{
+    using namespace WrtDeviceApis::Commons;
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_NETWORKBEARERSELECTION, NETWORKBEARERSELECTION_DEVICE_CAP);
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_NETWORKBEARERSELECTION);
+
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_NETWORKBEARERSELECTION, DEVICE_CAP_NETWORKBEARERSELECTION);
+
+    ACE_CREATE_FEATURE(FEATURE_NETWORKBEARERSELECTION, NETWORKBEARERSELECTION_FEATURE_API);
+    ACE_CREATE_FEATURE_LIST(NETWORKBEARERSELECTION_FEATURES);
+
+    ACE_ADD_API_FEATURE(NETWORKBEARERSELECTION_FEATURES, FEATURE_NETWORKBEARERSELECTION);
+
+    FunctionMapping NetworkBearerSelectionFunctions;
+
+    AceFunction requestRouteToHostFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_REQUEST_ROUTE_TO_HOST,
+        NETWORKBEARERSELECTION_FUNCTION_API_REQUEST_ROUTE_TO_HOST,
+        NETWORKBEARERSELECTION_FEATURES,
+        DEVICE_LIST_NETWORKBEARERSELECTION);
+
+    NetworkBearerSelectionFunctions.insert(std::make_pair(
+        NETWORKBEARERSELECTION_FUNCTION_API_REQUEST_ROUTE_TO_HOST,
+        requestRouteToHostFunc));
+
+    AceFunction releaseRouteToHostFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_RELEASE_ROUTE_TO_HOST,
+        NETWORKBEARERSELECTION_FUNCTION_API_RELEASE_ROUTE_TO_HOST,
+        NETWORKBEARERSELECTION_FEATURES,
+        DEVICE_LIST_NETWORKBEARERSELECTION);
+
+    NetworkBearerSelectionFunctions.insert(std::make_pair(
+        NETWORKBEARERSELECTION_FUNCTION_API_RELEASE_ROUTE_TO_HOST,
+        releaseRouteToHostFunc));
+
+    return NetworkBearerSelectionFunctions;
+}
+}
+}
+
+#undef NETWORKBEARERSELECTION_FEATURE_API
diff --git a/src/NetworkBearerSelection/plugin_config.h b/src/NetworkBearerSelection/plugin_config.h
new file mode 100755 (executable)
index 0000000..a7c5c6c
--- /dev/null
@@ -0,0 +1,39 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _NETWORKBEARERSELECTION_PLUGIN_CONFIG_H_
+#define _NETWORKBEARERSELECTION_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+extern const char* NETWORKBEARERSELECTION_FUNCTION_API_REQUEST_ROUTE_TO_HOST;
+extern const char* NETWORKBEARERSELECTION_FUNCTION_API_RELEASE_ROUTE_TO_HOST;
+
+
+DECLARE_FUNCTION_GETTER(NetworkBearerSelection);
+
+#define NETWORKBEARERSELECTION_CHECK_ACCESS(functionName)               \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(             \
+                                            getNetworkBearerSelectionFunctionData,     \
+                                            functionName)
+}
+}
+
+#endif
diff --git a/src/NetworkBearerSelection/plugin_initializer.cpp b/src/NetworkBearerSelection/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..14d0bdd
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include "JSNetworkBearerSelection.h"
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+#define WRT_JS_EXTENSION_OBJECT_TIZEN "tizen"
+
+namespace DeviceAPI {
+namespace NetworkBearerSelection {
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\NetworkBearerSelection ] on_widget_start_callback (%d)", widgetId);
+    Try
+    {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\NetworkBearerSelection ] on_widget_stop_callback (%d)", widgetId);
+    Try
+    {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\NetworkBearerSelection] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(
+        static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\NetworkBearerSelection] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(
+        static_cast<JSContextRef>(context));
+}
+
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+    "networkbearerselection",
+    (js_class_template_getter)JSNetworkBearerSelection::getClassRef,
+    NULL)
+PLUGIN_CLASS_MAP_END
+
+}
+}
diff --git a/src/Notification/CMakeLists.txt b/src/Notification/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..ddd2c8b
--- /dev/null
@@ -0,0 +1,63 @@
+
+SET(TARGET_NAME ${notification_target})
+SET(DESTINATION_NAME ${notification_dest})
+SET(TARGET_IMPL_NAME ${notification_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_notification REQUIRED notification capi-appfw-application)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${TOP}/Application
+    ${TOP}/Filesystem
+    ${platform_pkgs_notification_INCLUDE_DIRS}
+    ${notification_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${application_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${filesystem_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSNotificationManager.cpp
+    JSStatusNotification.cpp
+    JSNotificationDetailInfo.cpp
+    NotificationManager.cpp
+    StatusNotification.cpp
+    NotificationDetailInfo.cpp
+    NotificationUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${notification_LIBRARIES}
+    ${application_impl}
+    ${filesystem_impl}
+    ${filesystem_config}
+    ${platform_pkgs_notification_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+        ${tizen_impl}
+    ${timeutil_impl}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/notification
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Notification/JSNotificationDetailInfo.cpp b/src/Notification/JSNotificationDetailInfo.cpp
new file mode 100755 (executable)
index 0000000..43e68a5
--- /dev/null
@@ -0,0 +1,300 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+
+#include "JSNotificationDetailInfo.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Notification {
+
+JSClassDefinition JSNotificationDetailInfo::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "NotificationDetailInfo",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSNotificationDetailInfo::m_property[] =
+{
+    {
+        NOTIFICATION_DETAIL_INFO_MAIN_TEXT,
+        JSNotificationDetailInfo::getProperty,
+        JSNotificationDetailInfo::setProperty,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSNotificationDetailInfo::m_jsClassRef =
+    JSClassCreate(JSNotificationDetailInfo::getClassInfo());
+
+const JSClassRef JSNotificationDetailInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNotificationDetailInfo::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSNotificationDetailInfo::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        NotificationDetailInfo *priv = new NotificationDetailInfo();
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    }
+}
+
+void JSNotificationDetailInfo::finalize(JSObjectRef object)
+{
+    NotificationDetailInfo *priv = static_cast<NotificationDetailInfo*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+bool JSNotificationDetailInfo::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+
+    NotificationDetailInfo *priv =
+        static_cast<NotificationDetailInfo*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("private object is NULL.");
+        throw TypeMismatchException("NotificationDetailInfo's private object is NULL.");
+    }
+
+    try {
+        std::string property;
+        size_t jsSize = JSStringGetMaximumUTF8CStringSize(propertyName);
+        if (jsSize > 0) {
+            jsSize = jsSize + 1;
+            char* buffer = new char[jsSize];
+            size_t written =
+                JSStringGetUTF8CString(propertyName, buffer, jsSize);
+            if (written > jsSize) {
+                LOGE("conversion could not be fully performed.");
+                throw InvalidValuesException("Conversion could not be fully performed.");
+            }
+            property = buffer;
+            delete[] buffer;
+        }
+
+        LOGI("property = %s", property.c_str());
+
+        if (property == NOTIFICATION_DETAIL_INFO_MAIN_TEXT)
+        {
+            std::string mainText = JSUtil::JSValueToString(context, value);
+            LOGI("mainText = %s", mainText.c_str());
+            priv->setMainText(mainText);
+        }
+
+    }
+    catch ( const BasePlatformException& err)
+    {
+        LOGW("notification convertion is failed %s: %s",
+            err.getName().c_str(), err.getMessage().c_str());
+    }
+
+    return false;
+}
+
+JSValueRef JSNotificationDetailInfo::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+
+    NotificationDetailInfo *priv =
+        static_cast<NotificationDetailInfo*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("private object is NULL");
+        throw TypeMismatchException("NotificationDetailInfo's private object is NULL.");
+    }
+
+    try {
+        std::string property;
+        size_t jsSize = JSStringGetMaximumUTF8CStringSize(propertyName);
+        if (jsSize > 0) {
+            jsSize = jsSize + 1;
+            char* buffer = new char[jsSize];
+            size_t written = JSStringGetUTF8CString(propertyName, buffer, jsSize);
+            if (written > jsSize) {
+                LOGE("conversion could not be fully performed.");
+                throw InvalidValuesException("Conversion could not be fully performed.");
+            }
+            property = buffer;
+            delete[] buffer;
+        }
+
+        LOGI("property = %s", property.c_str());
+        if (property == NOTIFICATION_DETAIL_INFO_MAIN_TEXT)
+        {
+            std::string main = priv->getMainText();
+
+            return JSUtil::toJSValueRef(context, main);
+        }
+
+    }
+    catch ( const BasePlatformException& err)
+    {
+        LOGW("notification convertion is failed, %s: %s",
+            err.getName().c_str(), err.getMessage().c_str());
+        return NULL;
+    }
+
+    return NULL;
+}
+
+JSObjectRef JSNotificationDetailInfo::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    NotificationDetailInfo *priv = new NotificationDetailInfo();
+
+    try {
+        priv->setMainText(validator.toString(0, false));
+    } catch (const BasePlatformException& err) {
+        LOGW("mainText convertion is failed. %s", err.getMessage().c_str());
+    }
+
+    try {
+
+        LOGI("argumentCount = %d", argumentCount);
+
+        if (argumentCount > 1) {
+            if (JSValueIsNull(context, arguments[1])) {
+                LOGI("subText is NULL");
+                priv->setSubTextNullFlag(true);
+            } else {
+                priv->setSubText(validator.toString(1, true));
+            }
+        }
+    } catch (const BasePlatformException& err) {
+        LOGW("subText convertion is failed. %s", err.getMessage().c_str());
+    }
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+    setPrivateObject(context, obj, priv);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, obj, ctorName, constructor,
+            kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    return obj;
+}
+
+NotificationDetailInfo* JSNotificationDetailInfo::getPrivateObject(
+    JSContextRef context, JSObjectRef object)
+{
+    NotificationDetailInfo *priv =
+        static_cast<NotificationDetailInfo*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("private object is NULL.");
+        throw TypeMismatchException("NotificationDetailInfo's private object is NULL.");
+    }
+
+    // mainText
+    JSValueRef mainText = JSUtil::getProperty(context, object,
+        NOTIFICATION_DETAIL_INFO_MAIN_TEXT);
+    priv->setMainText(JSUtil::JSValueToString(context, mainText));
+
+    // subText
+    JSValueRef subText = JSUtil::getProperty(context, object,
+        NOTIFICATION_DETAIL_INFO_SUB_TEXT);
+    if (JSValueIsNull(context, subText)||JSValueIsUndefined(context, subText))
+        priv->setSubTextNullFlag(true);
+    else
+        priv->setSubText(JSUtil::JSValueToString(context, subText));
+
+    if (!subText)
+        LOGI("Sub Text is NULL");
+
+    return priv;
+}
+
+void JSNotificationDetailInfo::setPrivateObject(JSContextRef context,
+    JSObjectRef object, NotificationDetailInfo *priv)
+{
+    if (priv) {
+        JSObjectSetPrivate(object, static_cast<void*>(priv));
+    } else {
+        LOGE("private object is NULL.");
+        throw TypeMismatchException("NotificationDetailInfo object is invaild.");
+    }
+
+    // mainText
+    JSUtil::setProperty(context, object, NOTIFICATION_DETAIL_INFO_MAIN_TEXT,
+            JSUtil::toJSValueRef(context, priv->getMainText()), kJSPropertyAttributeNone);
+
+    // subText
+    LOGI("us subtext null %d",  priv->isSubTexstNull());
+    if (priv->isSubTexstNull()) {
+        JSUtil::setProperty(context, object, NOTIFICATION_DETAIL_INFO_SUB_TEXT,
+                JSValueMakeNull(context), kJSPropertyAttributeNone);
+    } else {
+        std::string subText = priv->getSubText();
+        JSUtil::setProperty(context, object, NOTIFICATION_DETAIL_INFO_SUB_TEXT,
+                JSUtil::toJSValueRef(context, subText), kJSPropertyAttributeNone);
+    }
+
+}
+
+
+} // Notification
+} // DeviceAPI
diff --git a/src/Notification/JSNotificationDetailInfo.h b/src/Notification/JSNotificationDetailInfo.h
new file mode 100755 (executable)
index 0000000..e26808a
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_NOTIFICATION_DETAIL_INFO_H__
+#define __TIZEN_JS_NOTIFICATION_DETAIL_INFO_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "NotificationDetailInfo.h"
+
+namespace DeviceAPI {
+namespace Notification {
+
+class JSNotificationDetailInfo
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static NotificationDetailInfo* getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSContextRef context, JSObjectRef object, NotificationDetailInfo *priv);
+    static bool setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Notification
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Notification/JSNotificationManager.cpp b/src/Notification/JSNotificationManager.cpp
new file mode 100755 (executable)
index 0000000..cb88684
--- /dev/null
@@ -0,0 +1,413 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <TimeTracer.h>
+
+#include "plugin_config.h"
+#include "JSStatusNotification.h"
+#include "JSNotificationManager.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Notification {
+
+JSClassDefinition JSNotificationManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "NotificationManager",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSNotificationManager::m_function[] = {
+    {
+        NOTIFICATION_MANAGER_API_POST,
+        post,
+        kJSPropertyAttributeNone
+    },
+    {
+        NOTIFICATION_MANAGER_API_UPDATE,
+        update,
+        kJSPropertyAttributeNone
+    },
+    {
+        NOTIFICATION_MANAGER_API_REMOVE,
+        remove,
+        kJSPropertyAttributeNone
+    },
+    {
+        NOTIFICATION_MANAGER_API_REMOVE_ALL,
+        removeAll,
+        kJSPropertyAttributeNone
+    },
+    {
+        NOTIFICATION_MANAGER_API_GET,
+        get,
+        kJSPropertyAttributeNone
+    },
+    {
+        NOTIFICATION_MANAGER_API_GET_ALL,
+        getAll,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSNotificationManager::m_jsClassRef =
+    JSClassCreate(JSNotificationManager::getClassInfo());
+
+const JSClassRef JSNotificationManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSNotificationManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSNotificationManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        NotificationManager *priv = new NotificationManager();
+
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    }
+}
+
+void JSNotificationManager::finalize(JSObjectRef object)
+{
+    NotificationManager *priv =
+        static_cast<NotificationManager*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSNotificationManager::post(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    AceSecurityStatus status = NOTIFICATION_CHECK_ACCESS(NOTIFICATION_FUNC);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Private Object
+        NotificationManager *priv =
+            static_cast<NotificationManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // notification
+        JSObjectRef notificationObj =
+            validator.toObject(0, JSStatusNotification::getClassRef());
+        StatusNotification *notification =
+            JSStatusNotification::getPrivateObject(context, notificationObj);
+        if (!notification) {
+            LOGE("Notification private object is NULL.");
+            throw TypeMismatchException("Notification's private object is NULL.");
+        }
+
+        // perform
+        //notification ID
+        int id = priv->post(notification);
+        if (id >= 0) {
+            std::stringstream stream;
+            stream << id;
+
+            if (stream.fail()) {
+                LOGE("ID conversion failed.");
+                throw TypeMismatchException("Notification's ID conversion is failed.");
+            }
+
+            LOGI ("posted notification id : %s", stream.str().c_str());
+
+            // delete notificaiton ID
+            JSStringRef propertyIDName = JSStringCreateWithUTF8CString(NOTIFICATION_ID);
+            JSObjectDeleteProperty(context, notificationObj, propertyIDName, 0);
+            JSStringRelease(propertyIDName);
+
+            // sencond
+            JSUtil::setProperty(context, notificationObj, NOTIFICATION_ID,
+               JSUtil::toJSValueRef(context, stream.str()), kJSPropertyAttributeReadOnly);
+        } else {
+            LOGE("ID value is invalid: %d", id);
+            throw DeviceAPI::Common::UnknownException("Notification ID value is invalied.");
+        }
+
+        //delete posted time
+        JSStringRef propertyPostedTimeName = JSStringCreateWithUTF8CString(NOTIFICATION_POSTED_TIME);
+        JSObjectDeleteProperty(context, notificationObj, propertyPostedTimeName, 0);
+        JSStringRelease(propertyPostedTimeName);
+
+        //posted time
+        JSUtil::setProperty(context, notificationObj, NOTIFICATION_POSTED_TIME,
+                JSUtil::makeDateObject(context,notification->getPostedTime()), kJSPropertyAttributeReadOnly);
+
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in NotificationManager.post().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSNotificationManager::update(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    AceSecurityStatus status = NOTIFICATION_CHECK_ACCESS(NOTIFICATION_FUNC);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Private Objexct
+        NotificationManager *priv =
+            static_cast<NotificationManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // notification
+        JSObjectRef notificationObj =
+            validator.toObject(0, JSStatusNotification::getClassRef());
+        StatusNotification *notification =
+            JSStatusNotification::getPrivateObject(context, notificationObj);
+        if (!notification) {
+            LOGE("Notification private object is NULL.");
+            throw TypeMismatchException("Notification's private object is NULL.");
+        }
+
+        // perform
+        priv->update(notification);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in NotificationManager.update().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSNotificationManager::remove(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    AceSecurityStatus status = NOTIFICATION_CHECK_ACCESS(NOTIFICATION_FUNC);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    try {
+        // Private Object
+        NotificationManager *priv =
+            static_cast<NotificationManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // id
+        std::string id = validator.toString(0);
+
+        // perform
+        priv->remove(id);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in NotificationManager.remove().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSNotificationManager::removeAll(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    AceSecurityStatus status = NOTIFICATION_CHECK_ACCESS(NOTIFICATION_FUNC);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+
+    LOGI("remove All");
+    try {
+        // Private Object
+        NotificationManager *priv = static_cast<NotificationManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        // perform
+        priv->removeAll();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in NotificationManager.removeAll().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSNotificationManager::get(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        // Private Object
+        NotificationManager *priv =
+            static_cast<NotificationManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // id
+        std::string id = validator.toString(0);
+        LOGD("get notification id : %s", id.c_str());
+
+        // make object
+        JSObjectRef obj =
+            JSObjectMake(context, JSStatusNotification::getClassRef(), NULL);
+
+        // perform
+        StatusNotification* noti = priv->get(id);
+        JSStatusNotification::setPrivateObject(context, obj, noti);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return obj;
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in NotificationManager.get().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSNotificationManager::getAll(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    try {
+        // Private Object
+        NotificationManager *priv =
+            static_cast<NotificationManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        std::vector<StatusNotification*> notifications = priv->getAll();
+
+        JSObjectRef notiArray[notifications.size()];
+        for (unsigned int i = 0; i < notifications.size(); i++) {
+            notiArray[i] = JSObjectMake(GlobalContextManager::getInstance()->
+                    getGlobalContext(context), JSStatusNotification::getClassRef(), NULL);
+            JSStatusNotification::setPrivateObject(context, notiArray[i],
+                notifications[i]);
+        }
+
+        JSValueRef exception = NULL;
+        JSObjectRef jsResult =
+            JSObjectMakeArray(GlobalContextManager::getInstance()->
+                getGlobalContext(context), notifications.size(), notiArray, &exception);
+        if (exception != NULL) {
+            LOGE("exception occured");
+            throw DeviceAPI::Common::UnknownException(context, exception);
+        }
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return jsResult;
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in NotificationManager.getAll().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+} // Notification
+} // DeviceAPI
diff --git a/src/Notification/JSNotificationManager.h b/src/Notification/JSNotificationManager.h
new file mode 100644 (file)
index 0000000..cf68a81
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_NOTIFICATION_MANAGER_H__
+#define __TIZEN_JS_NOTIFICATION_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "NotificationManager.h"
+
+namespace DeviceAPI {
+namespace Notification {
+
+class JSNotificationManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef post(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef update(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef remove(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef removeAll(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef get(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getAll(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Notification
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Notification/JSStatusNotification.cpp b/src/Notification/JSStatusNotification.cpp
new file mode 100755 (executable)
index 0000000..abdc425
--- /dev/null
@@ -0,0 +1,1041 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+#include <FilesystemExternalUtils.h>
+#include <ApplicationConverter.h>
+#include "plugin_config.h"
+
+#include "JSStatusNotification.h"
+#include "JSNotificationDetailInfo.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Notification {
+
+#define NOTIFICATION_TYPE_VALUE "STATUS"
+
+JSClassDefinition JSStatusNotification::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "StatusNotification",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSStatusNotification::m_property[] =
+{
+    {
+        STATUS_NOTIFICATION_PROGRESS_TYPE,
+        JSStatusNotification::getProperty,
+        JSStatusNotification::setProperty,
+        kJSPropertyAttributeNone
+    },
+    {
+        STATUS_NOTIFICATION_PROGRESS_VALUE,
+        JSStatusNotification::getProperty,
+        JSStatusNotification::setProperty,
+        kJSPropertyAttributeNone
+    },
+    {
+        STATUS_NOTIFICATION_LIGHT_ONTIME,
+        JSStatusNotification::getProperty,
+        JSStatusNotification::setProperty,
+        kJSPropertyAttributeNone
+    },
+    {
+        STATUS_NOTIFICATION_LIGHT_OFFTIME,
+        JSStatusNotification::getProperty,
+        JSStatusNotification::setProperty,
+        kJSPropertyAttributeNone
+    },
+    {
+        STATUS_NOTIFICATION_VIBRATION,
+        JSStatusNotification::getProperty,
+        JSStatusNotification::setProperty,
+        kJSPropertyAttributeNone
+    },
+    {
+        NOTIFICATION_TITLE,
+        JSStatusNotification::getProperty,
+        JSStatusNotification::setProperty,
+        kJSPropertyAttributeNone
+    },
+    {0, 0, 0, 0}
+};
+
+bool JSStatusNotification::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+
+    StatusNotification *priv = static_cast<StatusNotification*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("private object is NULL");
+        throw TypeMismatchException("StatusNotification's private object is NULL.");
+    }
+
+    try {
+        std::string property;
+        size_t jsSize = JSStringGetMaximumUTF8CStringSize(propertyName);
+        if (jsSize > 0) {
+            jsSize = jsSize + 1;
+            char* buffer = new char[jsSize];
+            size_t written = JSStringGetUTF8CString(propertyName, buffer, jsSize);
+            if (written > jsSize) {
+                LOGE("conversion could not be fully performed.");
+                throw InvalidValuesException("Conversion could not be fully performed.");
+            }
+            property = buffer;
+            delete[] buffer;
+        }
+
+        LOGI("property = %s", property.c_str());
+
+        if (property == STATUS_NOTIFICATION_PROGRESS_TYPE)
+        {
+            std::string strProgressType = JSUtil::JSValueToString(context, value);
+            LOGI("Progress Type : %s", strProgressType.c_str());
+
+            NotificationProgressType progType = NOTI_PROGRESS_TYPE_NONE;
+            if (strProgressType.compare(TIZEN_NOTIFICATION_PROGRESS_TYPE_PERCENTAGE) == 0)
+                progType = NOTI_PROGRESS_TYPE_PERCENTAGE;
+            else if (strProgressType.compare(TIZEN_NOTIFICATION_PROGRESS_TYPE_BYTE) == 0)
+                progType = NOTI_PROGRESS_TYPE_SIZE;
+            else
+                throw InvalidValuesException("Invalid Progress Type.");
+
+            priv->setProgressType(progType);    //set progress Type
+
+            return true;
+        }
+        else if (property == STATUS_NOTIFICATION_PROGRESS_VALUE)
+        {
+            // progressValue
+            unsigned long progressVal = JSUtil::JSValueToULong(context, value);
+            LOGI("Progress Value : %d", progressVal);
+
+            if (priv->getProgressType() == NOTI_PROGRESS_TYPE_PERCENTAGE)
+            {
+                if (100 < progressVal) {
+                    LOGE("progress value must be between 0 and 100 : %d", progressVal);
+                    throw InvalidValuesException("The percentage progress value must be between 0 and 100");
+                }
+                priv->setProgressValue((double)progressVal/(double)100);
+            }
+            else
+            {
+                priv->setProgressValue((double)progressVal);
+            }
+
+            return true;
+        }
+        else if (property == STATUS_NOTIFICATION_LIGHT_ONTIME)
+        {
+            unsigned long onPeriod = JSUtil::JSValueToULong(context, value);
+            LOGI("    LEDonPeriod = %d", onPeriod);
+            priv->setLightOnTime(onPeriod);
+        }
+        else if (property == STATUS_NOTIFICATION_LIGHT_OFFTIME)
+        {
+            unsigned long offPeriod = JSUtil::JSValueToULong(context, value);
+            LOGI("    LEDoffPeriod = %d", offPeriod);
+            priv->setLightOffTime(offPeriod);
+        }
+        else if (property == STATUS_NOTIFICATION_VIBRATION)
+        {
+            bool vibration = JSUtil::JSValueToBoolean(context, value);
+            LOGI("    vibration = %d", vibration);
+            priv->setDefaultVibration(vibration);
+        }
+        else if (property == NOTIFICATION_TITLE)
+        {
+            std::string title = JSUtil::JSValueToString(context, value);
+            LOGI("    title = %s", title.c_str());
+            priv->setTitle(title);
+        }
+
+    }
+    catch ( const BasePlatformException& err)
+    {
+        LOGW("notification convertion is failed. %s: %s",
+            err.getName().c_str(), err.getMessage().c_str());
+    }
+
+
+    return false;
+}
+
+JSValueRef JSStatusNotification::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+
+    StatusNotification *priv = static_cast<StatusNotification*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("private object is NULL.");
+        throw TypeMismatchException("StatusNotification's private object is NULL.");
+    }
+
+    try {
+        std::string property;
+        size_t jsSize = JSStringGetMaximumUTF8CStringSize(propertyName);
+        if (jsSize > 0) {
+            jsSize = jsSize + 1;
+            char* buffer = new char[jsSize];
+            size_t written = JSStringGetUTF8CString(propertyName, buffer, jsSize);
+            if (written > jsSize) {
+                LOGE("conversion could not be fully performed.");
+                throw InvalidValuesException("Conversion could not be fully performed.");
+            }
+            property = buffer;
+            delete[] buffer;
+        }
+
+        LOGI("property = %s", property.c_str());
+        if (property == STATUS_NOTIFICATION_PROGRESS_TYPE)
+        {
+            std::string type;
+            if (NOTI_PROGRESS_TYPE_PERCENTAGE ==  priv->getProgressType())
+            {
+                type = TIZEN_NOTIFICATION_PROGRESS_TYPE_PERCENTAGE;
+            }
+            else if (NOTI_PROGRESS_TYPE_SIZE==   priv->getProgressType())
+            {
+                type = TIZEN_NOTIFICATION_PROGRESS_TYPE_BYTE;
+            }
+
+            return JSUtil::toJSValueRef(context, type);
+
+        }
+        else if (property == STATUS_NOTIFICATION_PROGRESS_VALUE)
+        {
+            // progressValue
+            LOGI("Progress Type = %d", priv->getProgressType());
+
+            // progressValue
+            unsigned long progressVal = 0;
+            if (NOTI_PROGRESS_TYPE_PERCENTAGE ==  priv->getProgressType())
+            {
+                progressVal = (unsigned long)( (priv->getProgressValue()*100) );
+            }
+            else if (NOTI_PROGRESS_TYPE_SIZE==   priv->getProgressType())
+            {
+                progressVal = (unsigned long)priv->getProgressValue();
+            }
+
+            LOGI("Progress Value = %d", progressVal);
+
+            if (priv->getNotiType() != NOTI_TYPE_PROGRESS && progressVal == 0)
+            {
+                return JSValueMakeNull(context);
+            }
+            else
+            {
+                return  JSUtil::toJSValueRef(context, progressVal);
+            }
+        }
+        else if (property == STATUS_NOTIFICATION_LIGHT_ONTIME)
+        {
+            unsigned long onTime = priv->getLightOnTime();
+            return  JSUtil::toJSValueRef(context, onTime);
+        }
+        else if (property == STATUS_NOTIFICATION_LIGHT_OFFTIME)
+        {
+            unsigned long offTime = priv->getLightOffTime();
+            return  JSUtil::toJSValueRef(context, offTime);
+        }
+        else if (property == STATUS_NOTIFICATION_VIBRATION)
+        {
+            bool vibration = priv->getDefaultVibration();
+            return  JSUtil::toJSValueRef(context, vibration);
+        }
+        else if (property == NOTIFICATION_TITLE)
+        {
+            std::string title = priv->getTitle();
+            return  JSUtil::toJSValueRef(context, title);
+        }
+    }
+    catch ( const BasePlatformException& err)
+    {
+        LOGW("notification convertion is failed. %s:%s ",
+            err.getName().c_str(), err.getMessage().c_str());
+        return NULL;
+    }
+
+    return NULL;
+}
+
+
+JSClassRef JSStatusNotification::m_jsClassRef =
+    JSClassCreate(JSStatusNotification::getClassInfo());
+
+const JSClassRef JSStatusNotification::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSStatusNotification::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSStatusNotification::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("JSStatusNotification::initialize, nothing ");
+}
+
+void JSStatusNotification::finalize(JSObjectRef object)
+{
+    StatusNotification *priv =
+        static_cast<StatusNotification*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSObjectRef JSStatusNotification::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    //get StatusType
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, obj, ctorName, constructor,
+            kJSPropertyAttributeReadOnly |
+            kJSPropertyAttributeDontDelete |
+            kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        //Status Notification Type.
+        NotificationType notiType = NOTI_TYPE_NONE;
+        std::string strStatusType = validator.toString(0, false, "");
+        LOGI("Notification Type : %s", strStatusType.c_str());
+
+        if (strStatusType.compare(TIZEN_STATUS_NOTIFICATION_TYPE_SIMPLE) == 0)
+            notiType = NOTI_TYPE_SIMPLE;
+        else if (strStatusType.compare(TIZEN_STATUS_NOTIFICATION_TYPE_THUMBNAIL) == 0)
+            notiType = NOTI_TYPE_THUMBNAIL;
+        else if (strStatusType.compare(TIZEN_STATUS_NOTIFICATION_TYPE_ONGOING) == 0)
+            notiType = NOTI_TYPE_ONGOING;
+        else if (strStatusType.compare(TIZEN_STATUS_NOTIFICATION_TYPE_PROGRESS) == 0)
+            notiType = NOTI_TYPE_PROGRESS;
+        else
+            notiType = NOTI_TYPE_NONE;
+
+        StatusNotification *priv = new StatusNotification(notiType);
+
+        // title
+        priv->setTitle(validator.toString(1, false, ""));
+
+        JSObjectRef notiInitDict = validator.toObject(2, true);
+
+        if (notiInitDict)
+        {
+            LOGI("Set Notification Init Dictionary");
+            //content
+            JSValueRef contentValue = JSUtil::getProperty(context, notiInitDict, NOTIFICATION_CONTENT);
+            if (!(JSValueIsUndefined(context, contentValue) || JSValueIsNull(context, contentValue)))
+            {
+                std::string contentStr = JSUtil::JSValueToString(context, contentValue);
+                priv->setContent(contentStr.c_str());
+            }
+
+            //icon
+            try {
+                JSValueRef iconValue = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_ICON_PATH);
+                if (!(JSValueIsUndefined(context, iconValue) || JSValueIsNull(context, iconValue)))
+                {
+                    const std::string srcPath = JSUtil::JSValueToString(context, iconValue);
+                    const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+                    priv->setIconPath(fullPath.c_str());
+                }
+            }
+            catch (...)
+            {
+                LOGW("Icon file path is invaild");
+            }
+
+            //sound
+            try {
+                JSValueRef soundValue   = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_SOUND_PATH);
+                if (!(JSValueIsUndefined(context, soundValue) || JSValueIsNull(context, soundValue)))
+                {
+                    const std::string srcPath = JSUtil::JSValueToString(context, soundValue);
+                    const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+                    priv->setSoundPath(fullPath.c_str());
+                }
+            }
+            catch (...)
+            {
+                LOGW("sound file path is invaild");
+            }
+
+            try {
+                //vibration
+                JSValueRef vibrationValue = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_VIBRATION);
+                priv->setDefaultVibration(JSUtil::JSValueToBoolean(context, vibrationValue));
+            }
+            catch (...)
+            {
+                LOGW("vibration value is invaild");
+            }
+
+            try {
+                //appControl
+                JSValueRef appControlValue  = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_APP_CONTROL);
+                if (!(JSValueIsUndefined(context, appControlValue) || JSValueIsNull(context, appControlValue)))
+                    priv->setApplicationControl(DeviceAPI::Application::JSApplicationControl::getApplicationControl(context, JSUtil::JSValueToObject(context, appControlValue)));
+            }
+            catch (...)
+            {
+                LOGW("appControl is invaild");
+            }
+
+            try {
+                //appID
+                JSValueRef appIdValue = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_APP_ID);
+                if (!(JSValueIsUndefined(context, appIdValue) || JSValueIsNull(context, appIdValue))) {
+                    std::string appIdStr = JSUtil::JSValueToString(context, appIdValue);
+                    priv->setApplicationId(appIdStr.c_str());
+                }
+            }
+            catch (...)
+            {
+                LOGW("appID is invaild");
+            }
+
+            try {
+                //Light
+                JSValueRef lightValue = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_LIGHT);
+                LOGI("Light : %s",  JSUtil::JSValueToString(context, lightValue).c_str());
+                if (!(JSValueIsUndefined(context, lightValue) || JSValueIsNull(context, lightValue)))
+                    priv->setLight(JSUtil::JSValueToString(context, lightValue));
+            }
+            catch (...)
+            {
+                LOGW("The LED value is invalid ");
+            }
+
+
+            try {
+                //onTime
+                JSValueRef onTimeValue = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_LIGHT_ONTIME);
+                if (!JSValueIsUndefined(context, onTimeValue))
+                    priv->setLightOnTime(JSUtil::JSValueToLong(context, onTimeValue));
+            }
+            catch (...)
+            {
+                LOGW("The LED on period value is invalid ");
+            }
+
+            try {
+                //offTime
+                JSValueRef offTimeValue = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_LIGHT_OFFTIME);
+                if (!JSValueIsUndefined(context, offTimeValue))
+                    priv->setLightOffTime(JSUtil::JSValueToLong(context, offTimeValue));
+
+            }
+            catch (...)
+            {
+                LOGW("The LED off period value is invalid ");
+            }
+
+            //progressType
+            NotificationProgressType progressType = NOTI_PROGRESS_TYPE_PERCENTAGE;
+
+            try {
+                JSStringRef propertyName = JSStringCreateWithUTF8CString(STATUS_NOTIFICATION_PROGRESS_TYPE);
+                bool has = JSObjectHasProperty(context, notiInitDict, propertyName);
+                JSStringRelease(propertyName);
+                if (has)
+                {
+                    JSValueRef progressTypeValue = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_PROGRESS_TYPE);
+                    std::string strProgressType = JSUtil::JSValueToString(context, progressTypeValue);
+                    LOGI("==Progress Type : %s", strProgressType.c_str());
+                    if (strProgressType.compare(TIZEN_NOTIFICATION_PROGRESS_TYPE_PERCENTAGE) == 0)
+                        progressType = NOTI_PROGRESS_TYPE_PERCENTAGE;
+                    else if (strProgressType.compare(TIZEN_NOTIFICATION_PROGRESS_TYPE_BYTE) == 0)
+                        progressType = NOTI_PROGRESS_TYPE_SIZE;
+                    else
+                        progressType = NOTI_PROGRESS_TYPE_NONE;
+                }
+                priv->setProgressType(progressType);
+            }
+            catch (...)
+            {
+                LOGW("The progress type is invalid ");
+            }
+
+            try {
+                //ProgressValue
+                JSValueRef progressValue    = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_PROGRESS_VALUE);
+                if (!JSValueIsUndefined(context, progressValue))
+                {
+                    if (progressType == NOTI_PROGRESS_TYPE_PERCENTAGE)
+                    {
+                        if (100 < JSUtil::JSValueToULong(context, progressValue))
+                        {
+                            LOGW("The percentage progress value must be between 0 and 100");
+                        }
+                        priv->setProgressValue((double)JSUtil::JSValueToULong(context, progressValue)/(double)100);
+                    }
+                    else
+                    {
+                        priv->setProgressValue((double)JSUtil::JSValueToULong(context, progressValue));
+                    }
+                }
+            }
+            catch (...)
+            {
+                LOGW("The progress value is invalid ");
+            }
+
+            //DetailInfo
+            JSValueRef detailInfoValue  = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_DETAIL_INFO);
+
+            std::vector<NotificationDetailInfo*> detailInfos;
+            if (JSIsArrayValue(context, detailInfoValue))
+            {
+                JSObjectRef arrayobj = JSUtil::JSValueToObject(context, detailInfoValue);
+                for (std::size_t i = 0; i < JSGetArrayLength(context, arrayobj); ++i)
+                {
+                    JSValueRef element = JSGetArrayElement(context, arrayobj, i);
+                    JSObjectRef object = JSUtil::JSValueToObject(context, element);
+                    if (object && JSValueIsObjectOfClass(context, element, JSNotificationDetailInfo::getClassRef()))
+                    {
+                        NotificationDetailInfo* item = static_cast<NotificationDetailInfo*>(JSObjectGetPrivate(object));
+                        if (item)
+                        {
+                            NotificationDetailInfo *detailinfo = NULL;
+                            std::string main = item->getMainText();
+
+                            if (item->isSubTexstNull())
+                            {
+                                detailinfo = new NotificationDetailInfo(NULL, (int)i, main);
+                            }
+                            else
+                            {
+                                std::string sub = item->getSubText();
+                                detailinfo = new NotificationDetailInfo(NULL, (int)i, main,  sub);
+                            }
+                            detailInfos.push_back(detailinfo);
+                        }
+                        else
+                        {
+                            //mainText
+                            NotificationDetailInfo *detailinfo = NULL;
+                            std::string main =  JSUtil::JSValueToString(context, JSUtil::getProperty(context, object, NOTIFICATION_DETAIL_INFO_MAIN_TEXT));
+
+                            JSStringRef propertyName = JSStringCreateWithUTF8CString(NOTIFICATION_DETAIL_INFO_SUB_TEXT);
+                            if (JSObjectHasProperty(context, object, propertyName))
+                            {
+                                JSValueRef subObj = JSUtil::getProperty(context, object, NOTIFICATION_DETAIL_INFO_SUB_TEXT);
+                                if (JSValueIsNull(context, subObj))
+                                {
+                                    detailinfo = new NotificationDetailInfo(NULL, (int)i, main);
+                                }
+                                else
+                                {
+                                    std::string sub =  JSUtil::JSValueToString(context, JSUtil::getProperty(context, object, NOTIFICATION_DETAIL_INFO_SUB_TEXT));
+                                    detailinfo = new NotificationDetailInfo(NULL, (int)i, main,  sub);
+                                }
+                            }
+                            else
+                            {
+                                detailinfo = new NotificationDetailInfo(NULL, (int)i, main);
+                            }
+
+                            JSStringRelease(propertyName);
+
+                            detailInfos.push_back(detailinfo);
+                        }
+
+                    }
+                }
+            }
+            priv->setDetailInfos(detailInfos);
+
+            //backgroundimage
+            try {
+                JSValueRef backgroundImageValue = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_BACKGROUND_IMAGE_PATH);
+                if (!(JSValueIsUndefined(context, backgroundImageValue) || JSValueIsNull(context, backgroundImageValue)))
+                {
+                    const std::string srcPath = JSUtil::JSValueToString(context, backgroundImageValue);
+                    const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+                    priv->setBackground(fullPath.c_str());
+                }
+            }
+            catch (...)
+            {
+                //throw TypeMismatchException("The backgound image path is invalid ");
+                LOGW("The backgound image path is invalid ");
+            }
+
+            try {
+                //number
+                JSValueRef numberValue  = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_NUMBER);
+                if (!JSValueIsUndefined(context, numberValue))
+                {
+                    priv->setNumber(JSUtil::JSValueToLong(context, numberValue));
+                }
+            }
+            catch (...) {
+                LOGW("The number is invalid ");
+            }
+
+            //thumbnail
+            try {
+                JSValueRef thumbnailsValue  = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_THUMBNAILS);
+                if (!JSValueIsUndefined(context, thumbnailsValue))
+                {
+
+                    std::vector<std::string> thumbnailPaths;
+                    if (JSIsArrayValue(context, thumbnailsValue)) {
+                        JSObjectRef arrayobj = JSUtil::JSValueToObject(context, thumbnailsValue);
+                        for (std::size_t i = 0; i < JSGetArrayLength(context, arrayobj); ++i) {
+                            JSValueRef element = JSGetArrayElement(context, arrayobj, i);
+                            const std::string srcPath = JSUtil::JSValueToString(context, element);
+                            const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+                            LOGI("thumbnail Path = %s", fullPath.c_str());
+                            thumbnailPaths.push_back(fullPath);
+                        }
+                    }
+                    priv->setThumbnails(thumbnailPaths);
+                }
+            }
+            catch ( ... )
+            {
+                //throw TypeMismatchException("thumbnail path convertion is failed.");
+                LOGW("thumbnail path convertion is failed.");
+            }
+
+            //subIconPath
+            try {
+                JSValueRef subIconPathValue = JSUtil::getProperty(context, notiInitDict, STATUS_NOTIFICATION_SUB_ICON_PATH);
+                if (!(JSValueIsUndefined(context, subIconPathValue) || JSValueIsNull(context, subIconPathValue)))
+                {
+                    const std::string srcPath = JSUtil::JSValueToString(context, subIconPathValue);
+                    const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+                    priv->setSubIconPath(fullPath.c_str());
+                }
+            }
+            catch (...)
+            {
+                //throw TypeMismatchException("subIcon path convertion is failed.");
+                LOGW("subIcon path convertion is failed.");
+            }
+
+        }
+
+        setPrivateObject(context, obj, priv);
+    }
+    catch ( const BasePlatformException& err)
+    {
+        LOGW("notification convertion is failed. %s: %s ",
+            err.getName().c_str(), err.getMessage().c_str());
+    }
+
+    return obj;
+
+}
+
+StatusNotification* JSStatusNotification::getPrivateObject(JSContextRef context, JSObjectRef object)
+{
+    StatusNotification *priv = static_cast<StatusNotification*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("private object is NULL");
+        throw TypeMismatchException("StatusNotification's private object is NULL.");
+    }
+
+    //type
+    JSValueRef type = JSUtil::getProperty(context, object, NOTIFICATION_TYPE);
+    if ((JSUtil::JSValueToString(context, type)).compare(NOTIFICATION_TYPE_VALUE))
+    {
+        LOGE("Status notification's type is mismatched");
+        throw TypeMismatchException("StatusNotification's type is mismatched");
+    }
+
+    //Title
+    JSValueRef title = JSUtil::getProperty(context, object, NOTIFICATION_TITLE);
+    priv->setTitle( JSUtil::JSValueToString(context, title));
+
+    //Content
+    JSValueRef contents = JSUtil::getProperty(context, object, NOTIFICATION_CONTENT);
+    if (!JSValueIsNull(context, contents))
+    {
+        std::string contentStr = JSUtil::JSValueToString(context, contents);
+        priv->setContent(contentStr.c_str());
+    }
+    else
+        priv->setContent(NULL);
+
+    // iconPath
+    JSValueRef iconPath = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_ICON_PATH);
+    if (!JSValueIsNull(context, iconPath))
+    {
+        const std::string srcPath = JSUtil::JSValueToString(context, iconPath);
+        const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+        priv->setIconPath(fullPath.c_str());
+    }
+    else
+        priv->setIconPath(NULL);
+
+    // subIconPath
+    JSValueRef subIconPath = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_SUB_ICON_PATH);
+    if (!JSValueIsNull(context, subIconPath))
+    {
+        const std::string srcPath = JSUtil::JSValueToString(context, subIconPath);
+        const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+        priv->setSubIconPath(fullPath.c_str());
+    }
+    else
+        priv->setSubIconPath(NULL);
+    // number
+    JSValueRef number = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_NUMBER);
+    priv->setNumber(JSUtil::JSValueToLong(context, number));
+
+    // detailInfo
+    JSValueRef detailInfo = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_DETAIL_INFO);
+    std::vector<NotificationDetailInfo*> detailInfos;
+    if (JSIsArrayValue(context, detailInfo))
+    {
+        JSObjectRef arrayobj = JSUtil::JSValueToObject(context, detailInfo);
+        for (std::size_t i = 0; i < JSGetArrayLength(context, arrayobj); ++i)
+        {
+            JSValueRef element = JSGetArrayElement(context, arrayobj, i);
+            JSObjectRef object = JSUtil::JSValueToObject(context, element);
+            if (object)
+            {
+                NotificationDetailInfo* detailinfo = static_cast<NotificationDetailInfo*>(JSObjectGetPrivate(object));
+                detailInfos.push_back(detailinfo);
+            }
+        }
+    }
+    priv->setDetailInfos(detailInfos);
+
+    // backgroundImagePath
+    JSValueRef backgroundImagePath = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_BACKGROUND_IMAGE_PATH);
+    if (!JSValueIsNull(context, backgroundImagePath))
+    {
+        const std::string srcPath = JSUtil::JSValueToString(context, backgroundImagePath);
+        const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+        priv->setBackground(fullPath.c_str());
+    }
+    else
+        priv->setBackground(NULL);
+    // thumbnails
+    JSValueRef thumbnails = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_THUMBNAILS);
+
+    std::vector<std::string> thumbnailPaths;
+    if (JSIsArrayValue(context, thumbnails)) {
+        JSObjectRef arrayobj = JSUtil::JSValueToObject(context, thumbnails);
+        for (std::size_t i = 0; i < JSGetArrayLength(context, arrayobj); ++i) {
+            JSValueRef element = JSGetArrayElement(context, arrayobj, i);
+            const std::string srcPath = JSUtil::JSValueToString(context, element);
+            const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+            LOGI("thumbnail Path = %s", fullPath.c_str());
+            thumbnailPaths.push_back(fullPath);
+        }
+    }
+    priv->setThumbnails(thumbnailPaths);
+
+    // soundPath
+    JSValueRef soundPath = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_SOUND_PATH);
+    if (!JSValueIsNull(context, soundPath))
+    {
+        const std::string srcPath = JSUtil::JSValueToString(context, soundPath);
+        const std::string fullPath = Filesystem::External::fromVirtualPath(srcPath, context);
+        priv->setSoundPath(fullPath.c_str());
+    }
+    else
+        priv->setSoundPath(NULL);
+
+    // vibration
+    JSValueRef vibration = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_VIBRATION);
+    priv->setDefaultVibration(JSUtil::JSValueToBoolean(context, vibration));
+
+    // appControl
+    JSValueRef appControl = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_APP_CONTROL);
+    if (!JSValueIsUndefined(context, appControl) && !JSValueIsNull(context, appControl))
+        priv->setApplicationControl(DeviceAPI::Application::JSApplicationControl::getApplicationControl(context, JSUtil::JSValueToObject(context,appControl)));
+    else
+        priv->setApplicationControl(DeviceAPI::Application::ApplicationControlPtr(new DeviceAPI::Application::ApplicationControl()));
+    // appId
+    JSValueRef appId = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_APP_ID);
+    if (!JSValueIsNull(context, appId)) {
+        std::string appIdStr = JSUtil::JSValueToString(context, appId);
+        priv->setApplicationId(appIdStr.c_str());
+    } else
+        priv->setApplicationId(NULL);
+
+    // light
+    JSValueRef light = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_LIGHT);
+    if (!JSValueIsNull(context, light))
+        priv->setLight(JSUtil::JSValueToString(context, light));
+    else
+        priv->setLight("#000000");//OFF
+    // onTime
+    JSValueRef onTime = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_LIGHT_ONTIME);
+    priv->setLightOnTime(JSUtil::JSValueToLong(context, onTime));
+
+    // offTime
+    JSValueRef offTime = JSUtil::getProperty(context, object, STATUS_NOTIFICATION_LIGHT_OFFTIME);
+    priv->setLightOffTime(JSUtil::JSValueToLong(context, offTime));
+
+    return priv;
+}
+
+void JSStatusNotification::setPrivateObject(JSContextRef context, JSObjectRef object, StatusNotification *priv)
+{
+    if (priv) {
+        JSObjectSetPrivate(object, static_cast<void*>(priv));
+    } else {
+        LOGE("private object is NULL");
+        throw TypeMismatchException("StatusNotification object is invaild.");
+    }
+
+    //type
+    std::string typeVal(NOTIFICATION_TYPE_VALUE);
+    JSUtil::setProperty(context, object, NOTIFICATION_TYPE,
+            JSUtil::toJSValueRef(context, typeVal), kJSPropertyAttributeReadOnly);
+
+    std::string type;
+
+    //statusType
+    if (NOTI_TYPE_SIMPLE ==  priv->getNotiType())
+        type = TIZEN_STATUS_NOTIFICATION_TYPE_SIMPLE;
+    else if (NOTI_TYPE_ONGOING ==  priv->getNotiType())
+        type = TIZEN_STATUS_NOTIFICATION_TYPE_ONGOING;
+    else if (NOTI_TYPE_PROGRESS ==  priv->getNotiType())
+        type = TIZEN_STATUS_NOTIFICATION_TYPE_PROGRESS;
+    else if (NOTI_TYPE_THUMBNAIL ==  priv->getNotiType())
+        type = TIZEN_STATUS_NOTIFICATION_TYPE_THUMBNAIL;
+    else {
+        LOGE("status type mismatch : %s", type.c_str());
+        throw TypeMismatchException("status type mismatch.");
+    }
+
+    JSUtil::setProperty(context, object, STATUS_NOTIFICATION_STATUS_TYPE,
+            JSUtil::toJSValueRef(context, type), kJSPropertyAttributeReadOnly);
+    //id
+    if (priv->getID() >= 0)
+    {
+        std::stringstream stream;
+        stream << priv->getID();
+
+        if (stream.fail()) {
+            LOGE("id conversion is failed %d", priv->getID());
+            throw TypeMismatchException("Notification's ID conversion is failed.");
+        }
+
+        JSUtil::setProperty(context, object, NOTIFICATION_ID,
+                JSUtil::toJSValueRef(context, stream.str()), kJSPropertyAttributeReadOnly);
+    }
+    else
+    {
+        JSUtil::setProperty(context, object, NOTIFICATION_ID,
+                JSValueMakeUndefined(context), kJSPropertyAttributeReadOnly);
+    }
+
+    //postedTime
+    if (priv->getPostedTime() > 0)
+    {
+        JSUtil::setProperty(context, object, NOTIFICATION_POSTED_TIME,
+                JSUtil::makeDateObject(context,priv->getPostedTime()), kJSPropertyAttributeReadOnly);
+    }
+    else
+    {
+        JSUtil::setProperty(context, object, NOTIFICATION_POSTED_TIME,
+                JSValueMakeUndefined(context), kJSPropertyAttributeReadOnly);
+    }
+
+    //title
+    JSUtil::setProperty(context, object, NOTIFICATION_TITLE,
+            JSUtil::toJSValueRef(context, priv->getTitle()), kJSPropertyAttributeNone);
+
+    //content
+    if (priv->getContent())
+        JSUtil::setProperty(context, object, NOTIFICATION_CONTENT,
+                JSUtil::toJSValueRef(context, std::string(priv->getContent())), kJSPropertyAttributeNone);
+    else
+        JSUtil::setProperty(context, object, NOTIFICATION_CONTENT, JSValueMakeNull(context), kJSPropertyAttributeNone);
+
+    //iconPath
+    if (priv->getIconPath())
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_ICON_PATH,
+                JSUtil::toJSValueRef(context, DeviceAPI::Filesystem::External::toVirtualPath(std::string(priv->getIconPath()), context)), kJSPropertyAttributeNone);
+    else
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_ICON_PATH, JSValueMakeNull(context), kJSPropertyAttributeNone);
+
+    //subIconPath
+    if (priv->getSubIconPath()) {
+        auto path = Filesystem::External::toVirtualPath(std::string(priv->getSubIconPath()), context);
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_SUB_ICON_PATH,
+                JSUtil::toJSValueRef(context, path), kJSPropertyAttributeNone);
+    }
+    else  {
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_SUB_ICON_PATH,  JSValueMakeNull(context), kJSPropertyAttributeNone);
+    }
+
+    //number
+    if (priv->getStrNumber()) {
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_NUMBER,
+                JSUtil::toJSValueRef(context, priv->getNumber()), kJSPropertyAttributeNone);
+    }
+    else {
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_NUMBER, JSValueMakeNull(context), kJSPropertyAttributeNone);
+    }
+
+    // backgroundImagePath
+    if (priv->getBackground()) {
+        auto path = Filesystem::External::toVirtualPath(std::string(priv->getBackground()), context);
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_BACKGROUND_IMAGE_PATH,
+                JSUtil::toJSValueRef(context, path), kJSPropertyAttributeNone);
+    }
+    else {
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_BACKGROUND_IMAGE_PATH, JSValueMakeNull(context), kJSPropertyAttributeNone);
+    }
+
+    // thumbnails
+    std::vector<std::string> thumbnails = priv->getThumbnails();
+    LOGI("Thumbnail Size : %d", thumbnails.size());
+    JSValueRef tumbnailvalueArray[thumbnails.size()];
+    for (unsigned int i = 0; i < thumbnails.size(); i++) {
+        if (!thumbnails[i].empty()) {
+            LOGI("Thumbnail : %s", thumbnails[i].c_str());
+            tumbnailvalueArray[i] = JSUtil::toJSValueRef(context,
+                DeviceAPI::Filesystem::External::toVirtualPath(thumbnails[i], context));
+        }
+    }
+
+    JSValueRef exception = NULL;
+    JSObjectRef jsThumbnails = JSObjectMakeArray(context, thumbnails.size(), tumbnailvalueArray, &exception);
+    if (exception != NULL) {
+        throw DeviceAPI::Common::UnknownException("Make Object Array failed.");
+    }
+
+    JSUtil::setProperty(context, object, STATUS_NOTIFICATION_THUMBNAILS,
+            jsThumbnails, kJSPropertyAttributeNone);
+
+    // soundPath
+    if (priv->getSoundPath()) {
+        auto path = Filesystem::External::toVirtualPath(std::string(priv->getSoundPath()), context);
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_SOUND_PATH,
+                JSUtil::toJSValueRef(context, path), kJSPropertyAttributeNone);
+    }
+    else {
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_SOUND_PATH, JSValueMakeNull(context), kJSPropertyAttributeNone);
+    }
+
+    // vibration
+    JSUtil::setProperty(context, object, STATUS_NOTIFICATION_VIBRATION,
+            JSUtil::toJSValueRef(context, priv->getDefaultVibration()), kJSPropertyAttributeNone);
+
+    // appId
+    if (!priv->isNullApplicationID())
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_APP_ID,
+                JSUtil::toJSValueRef(context, priv->getApplicationId()), kJSPropertyAttributeNone);
+    else
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_APP_ID, JSValueMakeNull(context), kJSPropertyAttributeNone);
+
+    //Light
+    if (!priv->getLight().empty())
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_LIGHT,
+                JSUtil::toJSValueRef(context, priv->getLight()), kJSPropertyAttributeNone);
+    else
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_LIGHT,
+                JSValueMakeNull(context), kJSPropertyAttributeNone);
+
+    JSUtil::setProperty(context, object, STATUS_NOTIFICATION_LIGHT_ONTIME,
+            JSUtil::toJSValueRef(context, priv->getLightOnTime()), kJSPropertyAttributeNone);
+
+    JSUtil::setProperty(context, object, STATUS_NOTIFICATION_LIGHT_OFFTIME,
+            JSUtil::toJSValueRef(context, priv->getLightOffTime()), kJSPropertyAttributeNone);
+
+    // detailInfo
+    std::vector<NotificationDetailInfo*> detailInfo = priv->getDetailInfos();
+    LOGI("detail Info Size : %d", detailInfo.size());
+    JSObjectRef valueArray[detailInfo.size()];
+    for (unsigned int i = 0; i < detailInfo.size(); i++) {
+        if (detailInfo[i])
+        {
+            LOGI("Main = %s, Sub = %s", detailInfo[i]->getMainText().c_str(),
+                detailInfo[i]->getSubText().c_str());
+            valueArray[i] = JSObjectMake(GlobalContextManager::getInstance()->getGlobalContext(context), JSNotificationDetailInfo::getClassRef(), static_cast<void*>(detailInfo[i]));
+            JSNotificationDetailInfo::setPrivateObject(context, valueArray[i], detailInfo[i]);
+        }
+    }
+
+    exception = NULL;
+    JSObjectRef jsResult = JSObjectMakeArray(GlobalContextManager::getInstance()->getGlobalContext(context), detailInfo.size(), valueArray, &exception);
+    if (exception != NULL) {
+        throw DeviceAPI::Common::UnknownException("Make Object Array failed.");
+    }
+
+    // detailInfo
+    JSUtil::setProperty(context, object, STATUS_NOTIFICATION_DETAIL_INFO,
+            jsResult, kJSPropertyAttributeNone);
+
+    // appControl
+    if (!(priv->getApplicationControl())->getOperation().empty())
+    {
+        DeviceAPI::Application::ApplicationConverter converter(GlobalContextManager::getInstance()->getGlobalContext(context));
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_APP_CONTROL,  converter.toJSValueRef(priv->getApplicationControl()), kJSPropertyAttributeNone);
+    }
+    else
+        JSUtil::setProperty(context, object, STATUS_NOTIFICATION_APP_CONTROL,   JSValueMakeNull(context), kJSPropertyAttributeNone);
+
+}
+
+
+} // Notification
+} // DeviceAPI
diff --git a/src/Notification/JSStatusNotification.h b/src/Notification/JSStatusNotification.h
new file mode 100755 (executable)
index 0000000..b685f92
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_STATUS_NOTIFICATION_H__
+#define __TIZEN_JS_STATUS_NOTIFICATION_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "StatusNotification.h"
+
+namespace DeviceAPI {
+namespace Notification {
+
+class JSStatusNotification
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static StatusNotification* getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSContextRef context, JSObjectRef object, StatusNotification *priv);
+    static bool setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Notification
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Notification/NotificationDetailInfo.cpp b/src/Notification/NotificationDetailInfo.cpp
new file mode 100755 (executable)
index 0000000..d53df9f
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "NotificationDetailInfo.h"
+
+namespace DeviceAPI {
+namespace Notification {
+
+NotificationDetailInfo::NotificationDetailInfo():
+    m_updated(false),
+    m_mainText(""),
+    m_subText(""),
+    m_index(-1),
+    m_notiHandle(NULL),
+    m_subTextNullFlag(true)
+{
+    LOGD("create by constructor");
+}
+
+NotificationDetailInfo::NotificationDetailInfo(notification_h noti):
+    m_updated(false),
+    m_mainText(""),
+    m_subText(""),
+    m_index(-1),
+    m_notiHandle(noti),
+    m_subTextNullFlag(true)
+{
+    LOGD("create by constructor");
+}
+
+NotificationDetailInfo::NotificationDetailInfo(std::string &mainText,
+    std::string &subText):
+    m_updated(false),
+    m_mainText(mainText),
+    m_subText(subText),
+    m_index(-1),
+    m_subTextNullFlag(false)
+{
+    LOGD("create DetilaInfo mainText: %s, subText: %s",
+       mainText.c_str(), subText.c_str());
+}
+
+NotificationDetailInfo::NotificationDetailInfo(notification_h noti, int index,
+    std::string &mainText) :
+    m_updated(false),
+    m_mainText(mainText),
+    m_index(index),
+    m_notiHandle(noti),
+    m_subTextNullFlag(true)
+{
+    LOGD("create DetilaInfo mainText: %s", mainText.c_str());
+    LOGD("handle: %p, m_index: %d", noti, index);
+}
+
+NotificationDetailInfo::NotificationDetailInfo(notification_h noti, int index,
+    std::string &mainText, std::string &subText) :
+    m_updated(false),
+    m_mainText(mainText),
+    m_subText(subText),
+    m_index(index),
+    m_notiHandle(noti),
+    m_subTextNullFlag(false)
+{
+    LOGD("create DetilaInfo mainText: %s, subText: %s", mainText.c_str(),
+        subText.c_str());
+    LOGD("handle: %p, m_index: %d", noti, index);
+}
+
+NotificationDetailInfo::~NotificationDetailInfo()
+{
+    LOGD("~NotificationDetailInfo");
+}
+
+std::string NotificationDetailInfo::getMainText() const
+{
+    LOGI("Main Text : %s", m_mainText.c_str());
+    return m_mainText;
+}
+
+void NotificationDetailInfo::setMainText(std::string mainText)
+{
+
+    LOGI("mainText : %s", mainText.c_str());
+    m_mainText = mainText;
+}
+
+std::string NotificationDetailInfo::getSubText() const
+{
+
+    LOGI("sub Text : %s", m_subText.c_str());
+    return m_subText;
+}
+
+void NotificationDetailInfo::setSubText(std::string subText)
+{
+    LOGD("subText : %s", subText.c_str());
+    m_subTextNullFlag = false;
+    m_subText = subText;
+}
+
+} // Notification
+} // DeviceAPI
diff --git a/src/Notification/NotificationDetailInfo.h b/src/Notification/NotificationDetailInfo.h
new file mode 100755 (executable)
index 0000000..bde46ef
--- /dev/null
@@ -0,0 +1,84 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NOTIFICATION_DETAIL_INFO_H__
+#define __TIZEN_NOTIFICATION_DETAIL_INFO_H__
+
+#include <MultiCallbackUserData.h>
+#include <string>
+#include <notification.h>
+#include "NotificationTypes.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Notification {
+
+class NotificationDetailInfo
+{
+public:
+    NotificationDetailInfo();
+    NotificationDetailInfo(notification_h noti);
+    NotificationDetailInfo(std::string &mainText, std::string &subText);
+    NotificationDetailInfo(notification_h noti, int index,
+        std::string &mainText);
+    NotificationDetailInfo(notification_h noti, int index,
+        std::string &mainText, std::string &subText);
+
+    virtual ~NotificationDetailInfo();
+
+    std::string getMainText() const;
+    void setMainText(std::string mainText);
+
+    std::string getSubText() const;
+    void setSubText(std::string subText);
+
+    void setUpdatedFlag(bool flag)
+    {
+        m_updated = flag;
+    }
+
+    bool getUpdatedFlag()
+    {
+        return m_updated;
+    }
+
+    bool isSubTexstNull()
+    {
+        return m_subTextNullFlag;
+    }
+
+    void setSubTextNullFlag(bool value)
+    {
+        m_subTextNullFlag = value;
+    }
+
+private:
+    bool m_updated;
+    std::string m_mainText;
+    std::string m_subText;
+
+    int m_index;
+    notification_h m_notiHandle;
+    bool m_subTextNullFlag;
+
+};
+
+} // Notification
+} // DeviceAPI
+
+#endif // __TIZEN_NOTIFICATION_DETAIL_INFO_H__
diff --git a/src/Notification/NotificationLine.cpp b/src/Notification/NotificationLine.cpp
new file mode 100755 (executable)
index 0000000..c7b6e99
--- /dev/null
@@ -0,0 +1,266 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NotificationLine.h"
+#include "NotificationUtil.h"
+
+#include <Commons/Exception.h>
+
+namespace DeviceAPI {
+namespace Notification {
+
+NotificationLine::NotificationLine() :
+    m_notiHandle(NULL),
+    m_index(-1)
+{
+    LOGD("created by constructor");
+}
+
+NotificationLine::~NotificationLine()
+{
+}
+
+NotificationLine::NotificationLine(notification_h noti, int index):
+    m_notiHandle(noti),
+    m_index(index)
+{
+    LOGD("create by notification");
+}
+
+NotificationLine::NotificationLine(notification_h noti, int index,
+    std::string &info, std::string &subInfo):
+    m_info(info),
+    m_subInfo(subInfo),
+    m_notiHandle(noti),
+    m_index(index)
+{
+    LOGD("create by notification with data");
+}
+
+std::string NotificationLine::getInformation() const
+{
+    if (m_notiHandle && m_index >= 0)
+    {
+        LOGD("index = %d", m_index);
+        int index = m_index;
+        notification_text_type_e type = NOTIFICATION_TEXT_TYPE_NONE;
+        switch (index)
+        {
+            case 0:
+                type = NOTIFICATION_TEXT_TYPE_INFO_1;
+                break;
+            case 1:
+                type = NOTIFICATION_TEXT_TYPE_INFO_2;
+                break;
+            case 2:
+                type = NOTIFICATION_TEXT_TYPE_INFO_3;
+                break;
+            default :
+                type = NOTIFICATION_TEXT_TYPE_NONE;
+        }
+
+        char *info = NULL;
+        int ret = notification_get_text(m_notiHandle, type, &info);
+
+        if (NOTIFICATION_TEXT_TYPE_NONE != type &&
+            ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("get notification information error: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            ThrowMsg(WrtDeviceApis::Commons::UnknownException,
+                "get notification information error");
+        }
+
+        std::string strInfo;
+        if (info)
+            strInfo = info;
+        LOGD("info %s", strInfo.c_str());
+
+        return strInfo;
+    }
+    else
+    {
+        return m_info;
+    }
+
+}
+
+void NotificationLine::setInformation(const std::string &info)
+{
+    if (m_notiHandle && m_index >= 0)
+    {
+        int idx = m_index;
+        LOGD("index : %d", idx);
+        LOGD("info : %s", info.c_str());
+        notification_text_type_e type = NOTIFICATION_TEXT_TYPE_NONE;
+
+        switch (idx)
+        {
+            case 0:
+                type = NOTIFICATION_TEXT_TYPE_INFO_1;
+                break;
+            case 1:
+                type = NOTIFICATION_TEXT_TYPE_INFO_2;
+                break;
+            case 2:
+                type = NOTIFICATION_TEXT_TYPE_INFO_3;
+                break;
+            default :
+                type = NOTIFICATION_TEXT_TYPE_NONE;
+        }
+
+        if (type == NOTIFICATION_TEXT_TYPE_NONE) {
+            LOGE("text type is invalid: %d", idx);
+            return;
+        }
+
+        if (!getInformation().compare(info)) {
+            LOGE("infos are not matched: %s, %s", getInformation().c_str(),
+                info.c_str());
+            return;
+        }
+
+        int ret = notification_set_text(m_notiHandle, type, info.c_str(),
+                    NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("set notification text error: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            ThrowMsg(WrtDeviceApis::Commons::UnknownException,
+                "set notification text error");
+        }
+        setUpdatedFlag(true);
+    }
+    else
+    {
+        m_info = info;
+    }
+}
+
+std::string NotificationLine::getSubInformation() const
+{
+    //return m_subInfo;
+    if (m_notiHandle && m_index >= 0)
+    {
+        int index = m_index;
+        LOGD("index : %d", index);
+
+        notification_text_type_e type = NOTIFICATION_TEXT_TYPE_NONE;
+        switch (index)
+        {
+            case 0:
+                type = NOTIFICATION_TEXT_TYPE_INFO_SUB_1;
+                break;
+            case 1:
+                type = NOTIFICATION_TEXT_TYPE_INFO_SUB_2;
+                break;
+            case 2:
+                type = NOTIFICATION_TEXT_TYPE_INFO_SUB_3;
+                break;
+            default :
+                type = NOTIFICATION_TEXT_TYPE_NONE;
+        }
+
+        char *subInfo = NULL;
+        int ret = notification_get_text(m_notiHandle, type, &subInfo);
+
+        if (NOTIFICATION_TEXT_TYPE_NONE != type &&
+                ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("get notification sub information error: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            ThrowMsg(WrtDeviceApis::Commons::UnknownException,
+                "get notification sub information error");
+        }
+
+        std::string strSubInfo;
+        if (subInfo)
+            strSubInfo = subInfo;
+        LOGD("sub info: %s", strSubInfo.c_str());
+        return strSubInfo;
+
+    }
+    else
+    {
+        return m_subInfo;
+    }
+}
+
+void NotificationLine::setSubInformation(const std::string &subInfo)
+{
+    if (m_notiHandle && m_index >= 0)
+    {
+        int idx = m_index;
+        LOGD("index : %d", idx);
+        LOGD("input value : %s", subInfo.c_str());
+        notification_text_type_e type = NOTIFICATION_TEXT_TYPE_NONE;
+
+        switch (idx)
+        {
+            case 0:
+                type = NOTIFICATION_TEXT_TYPE_INFO_SUB_1;
+                break;
+            case 1:
+                type = NOTIFICATION_TEXT_TYPE_INFO_SUB_2;
+                break;
+            case 2:
+                type = NOTIFICATION_TEXT_TYPE_INFO_SUB_3;
+                break;
+            default :
+                type = NOTIFICATION_TEXT_TYPE_NONE;
+        }
+
+        if (type == NOTIFICATION_TEXT_TYPE_NONE) {
+            LOGE("type is invalid: %d", idx);
+            return;
+        }
+
+        if (!getSubInformation().compare(subInfo)) {
+            LOGE("subInfos are not matched: %s, %s", getSubInformation().c_str(),
+                subInfo.c_str());
+            return;
+        }
+
+        int ret = notification_set_text(m_notiHandle, type, subInfo.c_str(),
+            NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("set notification text failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            ThrowMsg(WrtDeviceApis::Commons::UnknownException,
+                "set notification text error");
+        }
+        setUpdatedFlag(true);
+    }
+    else
+    {
+        m_subInfo = subInfo;
+    }
+}
+
+void NotificationLine::setUpdatedFlag(bool flag)
+{
+    m_updated = flag;
+}
+
+bool NotificationLine::getUpdatedFlag()
+{
+    return m_updated;
+}
+
+} // Notification
+} // DeviceAPI
diff --git a/src/Notification/NotificationManager.cpp b/src/Notification/NotificationManager.cpp
new file mode 100755 (executable)
index 0000000..6371539
--- /dev/null
@@ -0,0 +1,582 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <bundle.h>
+#include <appsvc/appsvc.h>
+
+#include "NotificationManager.h"
+#include "NotificationUtil.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Notification {
+
+extern "C" int app_control_to_bundle(app_control_h service, bundle **data);
+
+static bool notification_package_equal(notification_h handle)
+{
+    char* package = NULL;
+    char* handle_package = NULL;
+    char cmdline[512] = {0,};
+    char buf[64] = {0,};
+
+    if (notification_get_pkgname(handle, &handle_package))
+    {
+        return false;
+    }
+
+    LOGD("handle package = %s", handle_package);
+
+    if (app_get_id(&package))
+    {
+
+        int ret = 0;
+        int fd = -1;
+        int pid = getpid();
+
+        snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
+
+        fd = open(buf, O_RDONLY);
+        if (fd < 0) {
+            return false;
+        }
+
+        ret = read(fd, cmdline, sizeof(cmdline) - 1);
+        if (ret <= 0) {
+            close(fd);
+            return false;
+        }
+
+        cmdline[ret] = 0;
+        close(fd);
+
+        if (strlen(cmdline) == strlen(handle_package))
+        {
+            if (!strncmp(cmdline, handle_package, strlen(cmdline)))
+            {
+                return true;
+            }
+        }
+    }
+    else
+    {
+        LOGD("package = %s", package);
+
+        if (strlen(package) == strlen(handle_package))
+        {
+            if (!strncmp(package, handle_package, strlen(package)))
+            {
+                free(package);
+                return true;
+            }
+        }
+    }
+    free(package);
+    return false;
+}
+
+NotificationManager::NotificationManager()
+{
+}
+
+NotificationManager::~NotificationManager()
+{
+}
+
+int NotificationManager::post(StatusNotification *notification)
+{
+    int id = -1;
+
+    if (!notification) {
+        LOGE("Notification handle is NULL.");
+        throw UnknownException("Notification Handle is NULL.");
+    }
+
+    LOGI("notification id = %d", notification->getID());
+    notification_h handle = (notification_h)notification->getNotificationHandle();
+
+    if (!handle) {
+        LOGD("It doesn't have notification handle.");
+        throw UnknownException("It is Empty Notification.");
+    }
+
+    //set Service
+    int ret = 0;
+
+    bundle *service_data = NULL;
+    app_control_h service = notification->getService();
+
+    LOGI("Service : %p, Flag : %d", service, notification->getLaunchFlag());
+
+    if (service && notification->getLaunchFlag())
+    {
+        ret = app_control_to_bundle(service, &service_data);
+        if (ret != APP_CONTROL_ERROR_NONE)
+        {
+            LOGE("Can't create bundle: %d", ret);
+            throw UnknownException("Can't create bundle");
+        }
+
+        LOGI("Notification Launch Flag True");
+        ret = notification_set_property(handle, 0);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("set_property failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+
+        }
+        ret = notification_set_execute_option(handle,
+            NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, service_data);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("can't set notification option: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        }
+    }
+    else
+    {
+        LOGI("Notification Launch Flag False");
+        ret = notification_set_property(handle,
+            NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("set_property failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        }
+    }
+
+    //check layout.
+    int type = (int)notification->getNotiType();
+    notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
+
+    switch (type)
+    {
+        case NOTI_TYPE_SIMPLE:
+        {
+            if (notification->getNumber()>0)
+                noti_layout = NOTIFICATION_LY_NOTI_EVENT_MULTIPLE;
+            else
+                noti_layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
+            break;
+        }
+        case NOTI_TYPE_THUMBNAIL:
+        {
+            noti_layout = NOTIFICATION_LY_NOTI_THUMBNAIL;
+            break;
+        }
+        case NOTI_TYPE_ONGOING:
+        {
+            noti_layout = NOTIFICATION_LY_ONGOING_EVENT;
+            break;
+        }
+         case NOTI_TYPE_PROGRESS:
+        {
+            noti_layout = NOTIFICATION_LY_ONGOING_PROGRESS;
+            break;
+        }
+    }
+
+    LOGD("Layout type = %d", noti_layout);
+    ret = notification_set_layout(handle, noti_layout);
+    LOGD("set Layout result = %d", ret);
+
+    int privID = -1;
+
+    //if noti already exist, it is update.
+    ret = notification_insert(handle, &privID);
+
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("insert failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "Notification object post fail");
+    }
+
+    id = privID;
+    LOGD("private ID : %d", privID);
+    notification->setUpdatedFlag(false);
+
+    if (type == NOTI_TYPE_PROGRESS)
+    {
+
+        double value = 0.0;
+
+        ret = notification_get_size(handle, &value);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("get_size failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "get notification size error");
+        }
+        LOGI("get Size : %d", value);
+        ret = notification_update_size(handle, NOTIFICATION_PRIV_ID_NONE, value);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("update_size failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "update notification size error");
+        }
+
+        ret = notification_get_progress(handle, &value);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("get_progress failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "get notification percentage error");
+        }
+        LOGI("get Percentage : %lf", value);
+
+        ret = notification_update_progress(handle, NOTIFICATION_PRIV_ID_NONE,
+            value);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("update_progress failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        }
+    }
+
+    return id;
+}
+void NotificationManager::update(StatusNotification *notification)
+{
+    if (!notification) {
+        LOGD("INotification is NULL");
+        throw UnknownException("Notificaton is NULL");
+    }
+
+    LOGD("notification id = %d", notification->getID());
+    notification_h handle = (notification_h)notification->getNotificationHandle();
+
+    if (!handle) {
+        LOGD("it doesn't have notification handle.");
+        throw UnknownException("It is Empty Notification.");
+    }
+
+    LOGD("noti type = %d", notification->getNotiType());
+    int ret = 0;
+
+    if (notification->getNotiType() == NOTI_TYPE_PROGRESS)
+    {
+        LOGD("progress type = %d", notification->getProgressType());
+        LOGD("noti id = %d", notification->getID());
+        LOGD("noti progress value = %d", notification->getProgressValue());
+
+        if (NOTI_PROGRESS_TYPE_PERCENTAGE == notification->getProgressType())
+        {
+            LOGD( "Percentage ");
+            ret = notification_update_progress(handle,
+                NOTIFICATION_PRIV_ID_NONE, notification->getProgressValue());
+        }
+        else if (NOTI_PROGRESS_TYPE_SIZE == notification->getProgressType())
+        {
+            LOGD( "size ");
+            ret = notification_update_size(handle, NOTIFICATION_PRIV_ID_NONE,
+                notification->getProgressValue());
+        }
+
+        LOGD("notification_update_progress = %d", ret);
+
+        if (NOTIFICATION_ERROR_NONE != ret)
+        {
+            LOGE("%d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "notification_update_progress failed");
+        }
+
+    }
+
+    LOGD("updated Flag = %d", notification->getUpdatedFlag());
+
+    if (notification->getUpdatedFlag())
+    {
+
+        int type = (int)notification->getNotiType();
+        notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
+
+        switch (type)
+        {
+            case NOTI_TYPE_SIMPLE:
+            {
+                if (notification->getNumber()>0)
+                    noti_layout = NOTIFICATION_LY_NOTI_EVENT_MULTIPLE;
+                else
+                    noti_layout = NOTIFICATION_LY_NOTI_EVENT_SINGLE;
+                break;
+            }
+            case NOTI_TYPE_THUMBNAIL:
+            {
+                noti_layout = NOTIFICATION_LY_NOTI_THUMBNAIL;
+                break;
+            }
+            case NOTI_TYPE_ONGOING:
+            {
+                noti_layout = NOTIFICATION_LY_ONGOING_EVENT;
+                break;
+            }
+            case NOTI_TYPE_PROGRESS:
+            {
+                noti_layout = NOTIFICATION_LY_ONGOING_PROGRESS;
+                break;
+            }
+        }
+
+        LOGD("Layout type = %d", noti_layout);
+        ret = notification_set_layout(handle, noti_layout);
+        LOGD("set Layout result = %d", ret);
+
+
+        bundle *service_data = NULL;
+        app_control_h service = notification->getService();
+
+        if (service)
+        {
+            ret = app_control_to_bundle(service, &service_data);
+            if (ret != APP_CONTROL_ERROR_NONE)
+            {
+                LOGE("%d", ret);
+                throw UnknownException("Can't create bundle");
+            }
+
+            if (notification->getLaunchFlag())
+            {
+                LOGI("Notification Launch Flag True");
+                ret = notification_set_property(handle, 0);
+                if (ret != NOTIFICATION_ERROR_NONE) {
+                    LOGE("set_property failed: %d, %s", ret,
+                        NotificationUtil::getNotificationErrorMessage(ret).c_str());
+                }
+
+                ret = notification_set_execute_option(handle,
+                    NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL,
+                    service_data);
+                if (ret != NOTIFICATION_ERROR_NONE)
+                {
+                    LOGE("Can't set Service option %d, %s", ret,
+                        NotificationUtil::getNotificationErrorMessage(ret).c_str());
+                }
+            }
+            else
+            {
+                LOGI("Notification Launch Flag False");
+                notification_set_property(handle, NOTIFICATION_PROP_DISABLE_APP_LAUNCH);
+            }
+        }
+
+        notification->setLaunchFlag(false);
+
+        LOGD("get Title = %s", notification->getTitle().c_str());
+        ret = notification_update(handle);
+        LOGD("notification_update = %d", ret);
+
+        // init
+        notification->setUpdatedFlag(false);
+
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("update failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            throw UnknownException("Notification Object update fail");
+        }
+    }
+}
+
+void NotificationManager::remove(std::string id)
+{
+    int privID = -1;
+    int ret = 0;
+    bool existFlag = false;
+
+    LOGD("id : %s", id.c_str());
+    std::istringstream stream(id);
+    if (stream.fail())
+    {
+        LOGE("invalid notification ID");
+        throw InvalidValuesException("Invalid notification ID, it don't match id format");
+    }
+
+    stream >> privID;
+
+    notification_h noti = NULL;
+    notification_list_h noti_list = NULL;
+    notification_list_h noti_list_iter = NULL;
+
+    ret = notification_get_grouping_list( NOTIFICATION_TYPE_NONE , -1,
+        &noti_list);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGD("get notification list failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "Can't get noti list");
+    }
+
+    noti_list_iter = notification_list_get_head(noti_list);
+    while ( noti_list_iter != NULL)
+    {
+        noti = notification_list_get_data(noti_list_iter);
+        if (noti != NULL && notification_package_equal(noti))
+        {
+            int noti_priv = -1;
+            ret = notification_get_id(noti, NULL, &noti_priv);
+            if (ret != NOTIFICATION_ERROR_NONE) {
+                LOGE("get_id failed: %d, %s", ret,
+                    NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            }
+
+            LOGD("notification id = %d", noti_priv);
+            if (noti_priv == privID)
+                existFlag = true;
+        }
+        noti_list_iter = notification_list_get_next(noti_list_iter);
+    }
+
+    if (noti_list)
+        notification_free_list(noti_list);
+
+    LOGD("notification ID : %d", privID);
+    if (!existFlag) {
+        LOGE("existFlag is NULL");
+        throw NotFoundException("not exist id");
+    }
+
+    ret = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_NONE, privID);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("delete_by_priv_id failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "notification delete failed");
+    }
+}
+
+void NotificationManager::removeAll()
+{
+    // remove all noti type
+    int ret = notification_delete_all(NOTIFICATION_TYPE_NOTI);
+    if (ret != NOTIFICATION_ERROR_NONE)
+    {
+        LOGE("notification delete failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "notification delete failed");
+    }
+
+    ret = notification_delete_all(NOTIFICATION_TYPE_ONGOING);
+    if (ret != NOTIFICATION_ERROR_NONE)
+    {
+        LOGE("notification delete failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "notification delete failed");
+    }
+}
+
+StatusNotification* NotificationManager::get(std::string id)
+{
+    int privID = 0;
+
+    std::istringstream stream(id);
+    if (stream.fail())
+    {
+        LOGE("invalid notification id: %s", id.c_str());
+        throw InvalidValuesException("Invalid notification ID, it don't match id format");
+    }
+    stream >> privID;
+
+    LOGI("priv ID : %d", privID);
+
+    notification_h notification = notification_load(NULL, privID);
+
+    if (notification != NULL && notification_package_equal(notification))
+    {
+        StatusNotification* noti = new StatusNotification(notification);
+        return noti;
+    }
+    else
+    {
+        LOGE("It's not notification id or removed notifiation");
+        throw NotFoundException("It is not notification ID or removed notification");
+    }
+    return NULL;
+}
+
+std::vector<StatusNotification*> NotificationManager::getAll()
+{
+    LOGD("OK");
+    std::vector<StatusNotification*> data;
+
+    notification_h noti = NULL;
+    notification_list_h noti_list = NULL;
+    notification_list_h noti_list_iter = NULL;
+    int ret = 0;
+
+    ret = notification_get_grouping_list(NOTIFICATION_TYPE_NONE, -1,
+        &noti_list);
+    if (ret != NOTIFICATION_ERROR_NONE)
+    {
+        LOGE("get notification list failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification list failed");
+    }
+
+    noti_list_iter = notification_list_get_head(noti_list);
+    while ( noti_list_iter != NULL)
+    {
+        noti = notification_list_get_data(noti_list_iter);
+        if (noti != NULL && notification_package_equal(noti))
+        {
+            int noti_priv = -1;
+            ret = notification_get_id(noti, NULL, &noti_priv);
+            if (ret != NOTIFICATION_ERROR_NONE) {
+                LOGE("get_id failed: %d, %s", ret,
+                    NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            }
+            LOGD("notification id = %d", noti_priv);
+
+            StatusNotification* notification = new StatusNotification(noti_priv);
+
+            ret = notification_get_id((notification_h)notification->
+                getNotificationHandle(), NULL, &noti_priv);
+            if (ret != NOTIFICATION_ERROR_NONE) {
+                LOGE("get_id failed: %d, %s", ret,
+                     NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            }
+
+            LOGD("loaded notification id = %d", noti_priv);
+            data.push_back(notification);
+        }
+
+        noti_list_iter = notification_list_get_next(noti_list_iter);
+    }
+
+    if (noti_list)
+        notification_free_list(noti_list);
+
+    return data;
+}
+
+} // Notification
+} // DeviceAPI
diff --git a/src/Notification/NotificationManager.h b/src/Notification/NotificationManager.h
new file mode 100755 (executable)
index 0000000..d0447b4
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NOTIFICATION_MANAGER_H__
+#define __TIZEN_NOTIFICATION_MANAGER_H__
+
+#include <MultiCallbackUserData.h>
+#include <app.h>
+#include "NotificationTypes.h"
+#include "StatusNotification.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Notification {
+
+class NotificationManager
+{
+public:
+    NotificationManager();
+    virtual ~NotificationManager();
+
+    int post(StatusNotification *notification);    //return notification id
+
+    void update(StatusNotification *notification);
+
+    void remove(std::string id);
+
+    void removeAll();
+
+    StatusNotification* get(std::string id);
+
+    std::vector<StatusNotification*> getAll();
+
+private:
+};
+
+} // Notification
+} // DeviceAPI
+
+#endif // __TIZEN_NOTIFICATION_MANAGER_H__
\ No newline at end of file
diff --git a/src/Notification/NotificationTypes.h b/src/Notification/NotificationTypes.h
new file mode 100755 (executable)
index 0000000..737b0a2
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _NOTIFICATION_TYPES_H_
+#define _NOTIFICATION_TYPES_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace DeviceAPI {
+namespace Notification {
+
+// enum NotificationType
+#define TIZEN_NOTIFICATION_TYPE_STATUS "STATUS"
+
+// enum StatusNotificationType
+#define TIZEN_STATUS_NOTIFICATION_TYPE_SIMPLE "SIMPLE"
+#define TIZEN_STATUS_NOTIFICATION_TYPE_THUMBNAIL "THUMBNAIL"
+#define TIZEN_STATUS_NOTIFICATION_TYPE_ONGOING "ONGOING"
+#define TIZEN_STATUS_NOTIFICATION_TYPE_PROGRESS "PROGRESS"
+
+// enum NotificationProgressType
+#define TIZEN_NOTIFICATION_PROGRESS_TYPE_PERCENTAGE "PERCENTAGE"
+#define TIZEN_NOTIFICATION_PROGRESS_TYPE_BYTE "BYTE"
+
+// enum NotificationType
+typedef enum
+{
+    NOTI_TYPE_NONE = 0,
+    NOTI_TYPE_SIMPLE,
+    NOTI_TYPE_ONGOING,
+    NOTI_TYPE_PROGRESS,
+    NOTI_TYPE_MUTIPLE,
+    NOTI_TYPE_THUMBNAIL,
+    NOTI_TYPE_MAX
+}NotificationType;
+
+//enum NotificationProgressType
+typedef enum
+{
+    NOTI_PROGRESS_TYPE_NONE = 0,
+    NOTI_PROGRESS_TYPE_PERCENTAGE,
+    NOTI_PROGRESS_TYPE_SIZE,
+    NOTI_PROGRESS_TYPE_MAX
+} NotificationProgressType;
+
+// typedef NotificationId
+typedef std::string NotificationId;
+
+} // Notification
+} // DeviceAPI
+
+#endif // _NOTIFICATION_TYPES_H_
diff --git a/src/Notification/NotificationUtil.cpp b/src/Notification/NotificationUtil.cpp
new file mode 100644 (file)
index 0000000..f2ecb3f
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "NotificationUtil.h"
+
+#include <sstream>
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Notification {
+
+void NotificationUtil::throwNotificationException(const int error_code,
+    const std::string &hint)
+{
+    std::stringstream ss;
+    ss << hint << " : " << getNotificationErrorMessage(error_code);
+    LOGE("%s", ss.str().c_str());
+
+    switch (error_code) {
+        case NOTIFICATION_ERROR_NOT_EXIST_ID:
+            throw NotFoundException(ss.str().c_str());
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+std::string NotificationUtil::getNotificationErrorMessage(const int error_code)
+{
+    switch (error_code) {
+        case NOTIFICATION_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case NOTIFICATION_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case NOTIFICATION_ERROR_IO_ERROR:
+            return "I/O error";
+        case NOTIFICATION_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case NOTIFICATION_ERROR_FROM_DB:
+            return "Error from DB query";
+        case NOTIFICATION_ERROR_ALREADY_EXIST_ID:
+            return "Already exist private ID";
+        case NOTIFICATION_ERROR_FROM_DBUS:
+            return "Error from DBus";
+        case NOTIFICATION_ERROR_NOT_EXIST_ID:
+            return "Not exist private ID";
+        case NOTIFICATION_ERROR_SERVICE_NOT_READY:
+            return "No reponse from notification service";
+        default:
+            return "Unknown Error";
+    }
+}
+
+}
+}
diff --git a/src/Notification/NotificationUtil.h b/src/Notification/NotificationUtil.h
new file mode 100644 (file)
index 0000000..fd6339c
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_NOTIFICATION_UTIL_H_
+#define __TIZEN_NOTIFICATION_UTIL_H_
+
+#include <string>
+#include <notification.h>
+
+namespace DeviceAPI {
+namespace Notification {
+
+class NotificationUtil {
+public:
+    static void throwNotificationException(const int errorCode,
+        const std::string &hint);
+    static std::string getNotificationErrorMessage(const int errorCode);
+};
+
+} // Notification
+} // DeviceAPI
+
+#endif // __TIZEN_NOTIFICATION_UTIL_H_
diff --git a/src/Notification/StatusNotification.cpp b/src/Notification/StatusNotification.cpp
new file mode 100755 (executable)
index 0000000..0b09d07
--- /dev/null
@@ -0,0 +1,2004 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <sstream>
+#include <appsvc/appsvc.h>
+#include <sstream>
+#include <app_control.h>
+#include <app_control_internal.h>
+
+#include <boost/algorithm/string.hpp>
+#include "StatusNotification.h"
+#include "NotificationUtil.h"
+
+namespace DeviceAPI {
+namespace Notification {
+
+#define DEFAULT_ICON_PATH "/opt/share/icons/default/"
+#define MAX_NOTIFICATION_DETAIL_INFO_LENGTH 2
+#define MAX_THUMBNAIL_LENGTH 4
+
+//callback functions.
+static bool service_extra_data_cb(app_control_h service, const char *key,
+    void *user_data)
+{
+    LOGI("OK");
+    char **value = NULL;
+    int length = 0;
+    int ret = 0;
+
+    if (user_data != NULL && key != NULL)
+    {
+        LOGI("user data & key is existed");
+
+        DeviceAPI::Application::ApplicationControlPtr* appControl =
+            (DeviceAPI::Application::ApplicationControlPtr*)(user_data);
+
+        DeviceAPI::Application::ApplicationControlDataPtr data(
+            new DeviceAPI::Application::ApplicationControlData());
+        LOGI("key = %s", key);
+        std::string keyStr = key;
+        std::vector<std::string> keyValue;
+        int index = 0;
+
+        ret = app_control_get_extra_data_array((*appControl)->getService_h(),
+            key, &value, &length);
+        if (ret == APP_CONTROL_ERROR_NONE)
+        {
+            LOGI("extra_data_array length = %d", length);
+
+            if (value != NULL && length != 0)
+            {
+                LOGI("extra_data_length = %d", length);
+                data->setKey(key);
+                for (index = 0; index < length; index++)
+                {
+                    LOGI("Value = %s", value[index]);
+                    keyValue.push_back(value[index]);
+                }
+
+                data->setValue(keyValue);
+                (*appControl)->addAppControlData(data);
+            }
+
+            if (value)
+                free(value);
+        }
+    }
+    return true;
+}
+
+StatusNotification::StatusNotification(NotificationType statusType) :
+    m_notiType(NOTI_TYPE_NONE),
+    m_service(NULL),
+    m_notiHandle(NULL),
+    m_progressType(NOTI_PROGRESS_TYPE_PERCENTAGE),
+    m_notiUpdated(false),
+    m_launchFlag(false)
+{
+    LOGI("statusType = %d", statusType);
+
+    notification_type_e type = NOTIFICATION_TYPE_NONE;
+    int ret = 0;
+    setNotiType(statusType);
+
+    if (statusType == NOTI_TYPE_SIMPLE || statusType == NOTI_TYPE_MUTIPLE ||
+        statusType == NOTI_TYPE_THUMBNAIL)
+    {
+        type = NOTIFICATION_TYPE_NOTI;
+    }
+    else if (statusType == NOTI_TYPE_ONGOING || statusType == NOTI_TYPE_PROGRESS)
+    {
+        type = NOTIFICATION_TYPE_ONGOING;
+    }
+    else
+    {
+        LOGI("invalide noti type : %d", statusType);
+        throw TypeMismatchException("value is not notification type");
+    }
+
+    LOGI("Notification Type : %d", type);
+
+    notification_h noti = notification_create(type);    //create notificatin.
+    if (noti)
+    {
+        setNotificationHandle((void*)noti);
+
+        if (NOTIFICATION_TYPE_ONGOING == type)
+        {
+            //ongoing no ticker.
+            LOGI("ongoing type");
+
+            ret = notification_set_display_applist(noti,
+                NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY|
+                NOTIFICATION_DISPLAY_APP_INDICATOR);
+            if (ret != NOTIFICATION_ERROR_NONE)
+            {
+                LOGE("set_display_applist failed: %d, %s", ret,
+                    NotificationUtil::getNotificationErrorMessage(ret).c_str());
+                NotificationUtil::throwNotificationException(ret,
+                    "can't set notification display applist");
+            }
+        }
+
+    }
+    else
+    {
+        LOGE("notification_create failed");
+        throw UnknownException("can't make new notification object");
+    }
+}
+
+StatusNotification::StatusNotification(void* noti) :
+    m_notiType(NOTI_TYPE_NONE),
+    m_service(NULL),
+    m_notiHandle(NULL),
+    m_progressType(NOTI_PROGRESS_TYPE_PERCENTAGE),
+    m_notiUpdated(false),
+    m_launchFlag(false)
+{
+    notification_h notification = (notification_h)noti;
+    int ret = 0;
+
+    if (!notification) {
+        LOGE("notification is NULL");
+        throw InvalidValuesException("It is not notification object.");
+    }
+
+    NotificationType type = NOTI_TYPE_NONE;
+    notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
+    notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
+
+    notification_get_type(notification, &noti_type);
+    notification_get_layout(notification, &noti_layout);
+
+    //get type.
+    if (noti_type == NOTIFICATION_TYPE_NOTI)
+    {
+        if (noti_layout == NOTIFICATION_LY_NOTI_EVENT_SINGLE ||
+                noti_layout == NOTIFICATION_LY_NOTI_EVENT_MULTIPLE)
+        {
+            type = NOTI_TYPE_SIMPLE;
+        }
+        else if (noti_layout == NOTIFICATION_LY_NOTI_THUMBNAIL)
+        {
+            type = NOTI_TYPE_THUMBNAIL;
+        }
+    }
+    else if (noti_type == NOTIFICATION_TYPE_ONGOING)
+    {
+        if (noti_layout == NOTIFICATION_LY_ONGOING_EVENT)
+        {
+            type = NOTI_TYPE_ONGOING;
+        }
+        else if (noti_layout == NOTIFICATION_LY_ONGOING_PROGRESS)
+        {
+            type = NOTI_TYPE_PROGRESS;
+        }
+    }
+
+    LOGI("notification type = %d", type);
+    setNotiType(type);
+
+    char *strProgressType = NULL;
+    ret = notification_get_image(notification, NOTIFICATION_IMAGE_TYPE_LIST_5,
+        &strProgressType);
+    if (ret == NOTIFICATION_ERROR_NONE)
+    {
+        if (strProgressType)
+        {
+            std::string notiProgressType(strProgressType);
+            if (notiProgressType.compare(TIZEN_NOTIFICATION_PROGRESS_TYPE_BYTE) == 0)
+                m_progressType = NOTI_PROGRESS_TYPE_SIZE;
+        }
+    }
+
+    setNotificationHandle((void*)notification);
+    loadThumbnails();
+    loadDetailInfos();
+
+    //service
+    bundle *bSvc = NULL;
+
+    ret = notification_get_execute_option(notification,
+        NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, &bSvc);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        notification_free(notification);
+
+        LOGE("get_execute_option failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "can't get service data");
+    }
+
+    LOGI("bundle = %p", bSvc);
+    if (bSvc)
+    {
+        int ret = app_control_create(&m_service);
+        if (ret != APP_CONTROL_ERROR_NONE)
+        {
+            LOGI("Fail to create app_control");
+            throw UnknownException("can't create service object");
+        }
+
+        LOGI("bundle is valid");
+        ret = app_control_import_from_bundle(m_service, bSvc);
+        if (ret != APP_CONTROL_ERROR_NONE)
+        {
+            LOGI("Service Create Event Error");
+            throw UnknownException("can't make service object");
+        }
+    }
+}
+
+StatusNotification::StatusNotification(int privID) :
+    m_notiType(NOTI_TYPE_NONE),
+    m_service(NULL),
+    m_notiHandle(NULL),
+    m_progressType(NOTI_PROGRESS_TYPE_PERCENTAGE),
+    m_notiUpdated(false),
+    m_launchFlag(false)
+{
+    LOGI("priv ID : %d", privID);
+
+    notification_h notification = notification_load(NULL, privID);
+    int ret = 0;
+    if (!notification) {
+        LOGE("notifiation is NULL");
+        throw NotFoundException("It is not notification ID or removed notification");
+    }
+
+    NotificationType type = NOTI_TYPE_NONE;
+    notification_type_e noti_type = NOTIFICATION_TYPE_NONE;
+    notification_ly_type_e noti_layout = NOTIFICATION_LY_NONE;
+
+    notification_get_type(notification, &noti_type);
+    notification_get_layout(notification, &noti_layout);
+
+    if (noti_type == NOTIFICATION_TYPE_NOTI)
+    {
+        if (noti_layout == NOTIFICATION_LY_NOTI_EVENT_SINGLE ||
+                noti_layout == NOTIFICATION_LY_NOTI_EVENT_MULTIPLE)
+        {
+            type = NOTI_TYPE_SIMPLE;
+        }
+        else if (noti_layout == NOTIFICATION_LY_NOTI_THUMBNAIL)
+        {
+            type = NOTI_TYPE_THUMBNAIL;
+        }
+    }
+    else if (noti_type == NOTIFICATION_TYPE_ONGOING)
+    {
+        if (noti_layout == NOTIFICATION_LY_ONGOING_EVENT)
+        {
+            type = NOTI_TYPE_ONGOING;
+        }
+        else if (noti_layout == NOTIFICATION_LY_ONGOING_PROGRESS)
+        {
+            type = NOTI_TYPE_PROGRESS;
+        }
+    }
+
+    LOGI("notification type = %d", type);
+    setNotiType(type);
+
+    char *strProgressType = NULL;
+    ret = notification_get_image(notification, NOTIFICATION_IMAGE_TYPE_LIST_5,
+        &strProgressType);
+    if (ret == NOTIFICATION_ERROR_NONE)
+    {
+        if (strProgressType)
+        {
+            std::string notiProgressType(strProgressType);
+            if (notiProgressType.compare(TIZEN_NOTIFICATION_PROGRESS_TYPE_BYTE) == 0)
+                m_progressType = NOTI_PROGRESS_TYPE_SIZE;
+        }
+    }
+
+    setNotificationHandle((void*)notification);
+    loadThumbnails();
+    loadDetailInfos();
+
+    //service
+    bundle *bSvc = NULL;
+    ret = notification_get_execute_option(notification,
+        NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, &bSvc);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_execute_option failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "can't get service data");
+    }
+
+    LOGI("bundle = %p", bSvc);
+    if (bSvc)
+    {
+        LOGI("bundle is valid");
+        int ret = app_control_create(&m_service);
+        if (ret != APP_CONTROL_ERROR_NONE)
+        {
+            LOGI("Fail to create app_control");
+            throw UnknownException("can't create service object");
+        }
+
+        ret = app_control_import_from_bundle(m_service, bSvc);
+        if (ret != APP_CONTROL_ERROR_NONE)
+        {
+            LOGI("Service Create Event Error");
+            throw UnknownException("can't make service object");
+        }
+    }
+}
+
+StatusNotification::~StatusNotification()
+{
+    if (m_notiHandle)
+    {
+        if (m_service != NULL)
+        {
+            app_control_destroy(m_service);
+            m_service = NULL;
+        }
+
+        int ret = notification_free(m_notiHandle);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("notification_free failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "notification free failed");
+        }
+        m_notiHandle = NULL;
+    }
+}
+
+int StatusNotification::getID()
+{
+    // notification not inserted yet.
+    int id = -1;
+    int ret = 0;
+    if (m_notiHandle)
+    {
+        ret = notification_get_id(m_notiHandle, NULL, &id);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("get_id failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        }
+    }
+    return id;
+}
+
+std::string StatusNotification::getStatusType()
+{
+    std::string type;
+
+    if (NOTI_TYPE_SIMPLE ==  getNotiType())
+    {
+        type = "SIMPLE";
+    }
+    else if (NOTI_TYPE_ONGOING ==  getNotiType())
+    {
+        type = "ONGOING";
+    }
+    else if (NOTI_TYPE_PROGRESS ==  getNotiType())
+    {
+        type = "PROGRESS";
+    }
+    else if (NOTI_TYPE_THUMBNAIL ==  getNotiType())
+    {
+        type = "THUMBNAIL";
+    }
+
+    return type;
+}
+
+void StatusNotification::setStatusType(std::string type)
+{
+    LOGI("type = %s", type.c_str());
+
+    NotificationType notiType = NOTI_TYPE_NONE;
+
+    if (type.compare(TIZEN_STATUS_NOTIFICATION_TYPE_SIMPLE) == 0)
+        notiType = NOTI_TYPE_SIMPLE;
+    else if (type.compare(TIZEN_STATUS_NOTIFICATION_TYPE_THUMBNAIL) == 0)
+        notiType = NOTI_TYPE_THUMBNAIL;
+    else if (type.compare(TIZEN_STATUS_NOTIFICATION_TYPE_ONGOING) == 0)
+        notiType = NOTI_TYPE_ONGOING;
+    else if (type.compare(TIZEN_STATUS_NOTIFICATION_TYPE_PROGRESS) == 0)
+        notiType = NOTI_TYPE_PROGRESS;
+    else
+        throw InvalidValuesException("Invalid Status Type.");
+
+    LOGI("Notification type = %d", notiType);
+    setNotiType(notiType);
+}
+
+time_t StatusNotification::getPostedTime()
+{
+    time_t postedTime = 0;
+    int ret = 0;
+
+    if (m_notiHandle) {
+        ret = notification_get_insert_time(m_notiHandle, &postedTime);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("get_insert_time failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "get notification posted time error");
+        }
+    }
+
+    LOGI("posted Time = %s", ctime(&postedTime));
+    return postedTime;
+}
+
+std::string StatusNotification::getTitle()
+{
+    int ret = 0;
+    char *title = NULL;
+
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    ret = notification_get_text(m_notiHandle,NOTIFICATION_TEXT_TYPE_TITLE,
+        &title);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_text failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification title error");
+    }
+
+    std::string notiTitle;
+    if (title) {
+        notiTitle = title;
+        LOGI("get title : %s", title);
+    }
+
+    return notiTitle;
+}
+
+void StatusNotification::setTitle(std::string title)
+{
+    LOGI("Title : %s", title.c_str());
+
+    int ret = 0;
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    LOGI("get Title : %s", getTitle().c_str());
+
+    if (!getTitle().compare(title)) {
+        LOGD("Title is already set %s", title.c_str());
+        return;
+    }
+
+    ret = notification_set_text(m_notiHandle, NOTIFICATION_TEXT_TYPE_TITLE,
+        title.c_str(), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+    if (ret != NOTIFICATION_ERROR_NONE)
+    {
+        LOGE("set_text failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "set notification title error");
+    }
+    setUpdatedFlag(true);
+}
+
+char* StatusNotification::getContent()
+{
+    int ret = 0;
+    char *content = NULL;
+
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    ret = notification_get_text(m_notiHandle, NOTIFICATION_TEXT_TYPE_CONTENT,
+        &content);
+    if (ret != NOTIFICATION_ERROR_NONE)
+    {
+        LOGE("get_text failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification content error");
+    }
+    return content;
+}
+
+void StatusNotification::setContent(const char* content)
+{
+    int ret = 0;
+
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    char *origContent = getContent();
+
+    // different value
+    if (!origContent || !content || strcmp(origContent, content)) {
+        if (!origContent && !content) {
+            return;
+        }
+
+        ret = notification_set_text(m_notiHandle, NOTIFICATION_TEXT_TYPE_CONTENT,
+            content, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("set_text failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification content error");
+        }
+        setUpdatedFlag(true);
+    }
+}
+
+char* StatusNotification::getIconPath()
+{
+    int ret = 0;
+    char *iconPath = NULL;
+
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    ret = notification_get_image(m_notiHandle, NOTIFICATION_IMAGE_TYPE_ICON,
+        &iconPath);
+    if (ret != NOTIFICATION_ERROR_NONE)
+    {
+        LOGE("get_image failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification icon path error");
+    }
+    return iconPath;
+}
+
+void StatusNotification::setIconPath(const char* iconPath)
+{
+    int ret = 0;
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    char *origIconPath = getIconPath();
+
+    if (iconPath)
+        LOGI("icon path = %s", iconPath);
+    if (origIconPath)
+        LOGI("origin icon path = %s", origIconPath);
+
+    if (!origIconPath || !iconPath || strcmp(origIconPath, iconPath)) {
+        if (!origIconPath && !iconPath)
+            return;
+        ret = notification_set_image(m_notiHandle,NOTIFICATION_IMAGE_TYPE_ICON,
+            iconPath);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("set_image failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification icon path error");
+        }
+        setUpdatedFlag(true);
+    }
+}
+
+const char* StatusNotification::getSoundPath()
+{
+    int ret = 0;
+    const char *soundPath = NULL;
+
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    notification_sound_type_e type = NOTIFICATION_SOUND_TYPE_NONE;
+
+    ret = notification_get_sound(m_notiHandle, &type,  &soundPath);
+
+    if (ret != NOTIFICATION_ERROR_NONE)
+    {
+        LOGE("get_sound failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification sound error");
+    }
+
+    LOGI("sound type = %d", type);
+    if (soundPath)
+        LOGI("soundPath = %s", soundPath);
+    if (soundPath && (type == NOTIFICATION_SOUND_TYPE_USER_DATA))
+        return soundPath;
+    else
+        return NULL;
+}
+
+void StatusNotification::setSoundPath(const char* sound)
+{
+    int ret = 0;
+
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    const char *origSoundPath = getSoundPath();
+    if (sound)
+        LOGI("sound path = %s", sound);
+    if (origSoundPath)
+        LOGI("origin sound path = %s", origSoundPath);
+
+    if (!origSoundPath || !sound || strcmp(origSoundPath, sound))
+    {
+        if (!origSoundPath && !sound)
+            return;
+
+        ret = notification_set_sound(m_notiHandle,
+            NOTIFICATION_SOUND_TYPE_USER_DATA, sound);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("set_sound failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification sound error");
+        }
+        setUpdatedFlag(true);
+    }
+}
+
+bool StatusNotification::getDefaultVibration()
+{
+    int ret = 0;
+    notification_vibration_type_e vib_type;
+
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    ret = notification_get_vibration(m_notiHandle, &vib_type,  NULL);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_vibration failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification vibration error");
+    }
+
+    if (NOTIFICATION_VIBRATION_TYPE_DEFAULT == vib_type ||
+        NOTIFICATION_VIBRATION_TYPE_USER_DATA == vib_type) {
+        return true;
+    } else  {
+        return false;
+    }
+}
+
+void StatusNotification::setDefaultVibration(const bool& vibration)
+{
+    int ret = 0;
+    if (!m_notiHandle) {
+        LOGE("handle is null");
+        throw UnknownException("notification handle is null");
+    }
+
+    notification_vibration_type_e vib_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+    LOGI("old vibration = %d", getDefaultVibration());
+    if (getDefaultVibration() != vibration) {
+        if (vibration) {
+            vib_type = NOTIFICATION_VIBRATION_TYPE_DEFAULT;
+        } else {
+            vib_type = NOTIFICATION_VIBRATION_TYPE_NONE;
+        }
+        LOGI("type vibration type = %d", vib_type);
+
+        ret = notification_set_vibration(m_notiHandle, vib_type, NULL);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("set_vibration failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification vibration error");
+        }
+        setUpdatedFlag(true);
+    }
+}
+
+DeviceAPI::Application::ApplicationControlPtr
+StatusNotification::getApplicationControl()
+{
+
+    app_control_h service = NULL;
+    char *tempStr = NULL;
+    int ret = 0;
+
+    DeviceAPI::Application::ApplicationControlPtr
+        appControl(new DeviceAPI::Application::ApplicationControl());
+
+    try {
+        if (m_service) {
+            appControl->setService_h(m_service);
+
+            // mandatory
+            ret = app_control_get_operation(m_service, &tempStr);
+            if (ret == APP_CONTROL_ERROR_NONE) {
+                LOGD("Operation Str = %s", tempStr);
+                if (tempStr) {
+                    appControl->setOperation(tempStr);
+                    free(tempStr);
+                    tempStr = NULL;
+                }
+            } else {
+                LOGE("app_control_get_operation failed: %d", ret);
+            }
+
+            // optional
+            ret = app_control_get_mime(m_service, &tempStr);
+            if (ret == APP_CONTROL_ERROR_NONE) {
+                LOGD("Mime Str = %s", tempStr);
+                if (tempStr) {
+                    appControl->setMime(tempStr);
+                    free(tempStr);
+                    tempStr = NULL;
+                }
+            } else {
+                LOGE("app_control_get_mime failed: %d", ret);
+            }
+
+            // optional
+            ret = app_control_get_uri(m_service, &tempStr);
+            if (ret == APP_CONTROL_ERROR_NONE) {
+                LOGD("Uri Str = %s", tempStr);
+                if (tempStr) {
+                    appControl->setUri(tempStr);
+                    free(tempStr);
+                    tempStr = NULL;
+                }
+            } else {
+                LOGE("app_control_get_uri failed: %d", ret);
+            }
+
+            ret = app_control_get_category(m_service, &tempStr);
+            if (ret == APP_CONTROL_ERROR_NONE) {
+                LOGD("Category Str = %s", tempStr);
+                if (tempStr) {
+                    appControl->setCategory(tempStr);
+                    free(tempStr);
+                    tempStr = NULL;
+                }
+            } else {
+                LOGE("app_control_get_category failed: %d", ret);
+            }
+
+            // optional
+            ret = app_control_foreach_extra_data(m_service,
+                service_extra_data_cb, (void*)&appControl);
+            if (ret != APP_CONTROL_ERROR_NONE) {
+                LOGE("app_control_foreach_extra_data failed: %d", ret);
+                ThrowMsg(WrtDeviceApis::Commons::UnknownException,
+                    "get notification service uri error");
+            }
+
+            return appControl;
+        }
+
+    } Catch (WrtDeviceApis::Commons::Exception) {
+        if (tempStr)
+        {
+            free(tempStr);
+            tempStr = NULL;
+        }
+
+        if (service)
+        {
+            free(service);
+            service = NULL;
+        }
+
+        LOGW("%s", _rethrown_exception.GetMessage().c_str());
+    }
+
+    return appControl;
+}
+
+void StatusNotification::setApplicationControl(
+    DeviceAPI::Application::ApplicationControlPtr control)
+{
+    int ret = 0;
+    // delete old service.
+    if (m_service) {
+        app_control_destroy(m_service);
+        m_service = NULL;
+    }
+
+    ret = app_control_create(&m_service);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("app_control_create failed: %d", ret);
+        throw UnknownException("service creation error");
+    }
+
+    LOGI("getOperation : %s", control->getOperation().c_str());
+    m_launchFlag = false;
+    if (control->getOperation().size() != 0) {
+        // default attribute
+        m_launchFlag = true;
+        ret = app_control_set_operation(m_service,
+            control->getOperation().c_str());
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_set_operation failed: %d", ret);
+            throw UnknownException("service set operation error");
+        }
+    }
+
+    // optional
+    LOGI("getUri : %s", control->getUri().c_str());
+    if (control->getUri().size() != 0) {
+        ret = app_control_set_uri(m_service, control->getUri().c_str());
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_set_uri failed: %d", ret);
+            throw UnknownException("service set uri error");
+        }
+    }
+
+    // optional
+    LOGI("getMime : %s", control->getMime().c_str());
+    if (control->getMime().size() != 0) {
+        ret = app_control_set_mime(m_service, control->getMime().c_str());
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_set_mime failed: %d", ret);
+            throw UnknownException("service set mime error");
+        }
+    }
+
+    LOGI("Category : %s", control->getCategory().c_str());
+    if (control->getCategory().size() != 0) {
+        ret = app_control_set_category(m_service,
+            control->getCategory().c_str());
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_set_category failed: %d", ret);
+            throw UnknownException("service set mime error");
+        }
+    }
+
+    std::vector<DeviceAPI::Application::ApplicationControlDataPtr>
+        appControlDataArray = control->getAppControlDataArray();
+    size_t index = 0;
+
+    LOGI("App Control Datas Count : %d", appControlDataArray.size());
+
+    DeviceAPI::Application::ApplicationControlDataArray::iterator iter;
+    for (iter = appControlDataArray.begin(); iter != appControlDataArray.end();
+        iter++) {
+
+        DeviceAPI::Application::ApplicationControlDataPtr appControlData = *iter;
+        std::string key = appControlData->getKey();
+        LOGI("key : %s", key.c_str());
+
+        if (key.empty()) continue;
+
+        std::vector<std::string> value = appControlDataArray[index]->getValue();
+        const char **arrayValue =
+            (const char**)calloc(sizeof(char*), value.size());
+
+        for (size_t indexArray = 0; indexArray < value.size(); indexArray++)
+        {
+            arrayValue[indexArray] = (char*)value[indexArray].c_str();
+            LOGI("value : %s", arrayValue[indexArray]);
+        }
+
+        const char* strKey = key.c_str();
+        LOGI("value size: %d", value.size());
+        ret = app_control_add_extra_data_array(m_service, strKey, arrayValue,
+            value.size());
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("app_control_add_extra_data_array failed: %d", ret);
+            throw UnknownException("service set extra data error");
+        }
+
+        if (arrayValue) free(arrayValue);
+    }
+}
+
+void StatusNotification::setApplicationId(const char* appId)
+{
+    if (!appId) {
+        LOGE("appId is NULL");
+        return;
+    }
+
+    int ret = 0;
+    if (!m_service) {
+        ret = app_control_create(&m_service);
+        if (ret != APP_CONTROL_ERROR_NONE)
+        {
+            LOGE("app_control_create failed: %d", ret);
+            throw UnknownException("service creation error");
+        }
+    }
+
+    ret = app_control_set_app_id(m_service, appId);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("app_control_set_app_id failed: %d", ret);
+        throw UnknownException("service set appId error");
+    }
+    m_launchFlag = true;
+}
+
+std::string StatusNotification::getApplicationId()
+{
+    std::string retString;
+    char* appIdStr = NULL;
+    int ret = 0;
+
+    if (!m_service) {
+        LOGE("m_service is NULL");
+        return retString;
+    }
+
+    ret = app_control_get_app_id(m_service, &appIdStr);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("app_control_get_app_id failed: %d", ret);
+        throw UnknownException ("Get applicaiton ID failed...");
+    }
+
+    if (appIdStr != NULL) {
+        retString = appIdStr;
+        free(appIdStr);
+    }
+
+    return retString;
+}
+
+bool StatusNotification::isNullApplicationID()
+{
+    char* appIdStr = NULL;
+    int ret = 0;
+    if (!m_service) {
+        LOGE("m_service is NULL");
+        return true;
+    }
+
+    ret = app_control_get_app_id(m_service, &appIdStr);
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("app_control_get_app_id failed: %d", ret);
+        throw UnknownException ("Get applicaiton ID failed...");
+    }
+
+    if (appIdStr == NULL) {
+        return true;
+    } else {
+        free(appIdStr);
+        appIdStr = NULL;
+        return false;
+    }
+    return true;
+}
+
+double StatusNotification::getProgressValue()
+{
+    double value = 0.0;
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        return value;
+    }
+
+    NotificationProgressType progressType = getProgressType();
+    int ret = 0;
+
+    if (progressType == NOTI_PROGRESS_TYPE_SIZE) {
+        ret = notification_get_size(m_notiHandle, &value);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("get_size failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "get notification size error");
+        }
+        LOGI("Size Val = %lf", value);
+    } else if (progressType == NOTI_PROGRESS_TYPE_PERCENTAGE) {
+        ret = notification_get_progress(m_notiHandle, &value);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("get_progress failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "get notification percentage error");
+        }
+        LOGI("Percentage Val = %lf", value);
+    } else {
+        throw UnknownException("get notification progress type error");
+    }
+
+    return value;
+}
+
+void StatusNotification::setProgressValue(const double &progressValue)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+
+    NotificationProgressType progressType = getProgressType();
+    LOGI("Progress Type : %d", progressType);
+
+    double val = getProgressValue();
+    int ret = 0;
+    LOGI("Progress value = %lf, origin Progress Value = %lf", progressValue,
+        val);
+
+    if (progressType == NOTI_PROGRESS_TYPE_SIZE) {
+        ret = notification_set_size(m_notiHandle, progressValue);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("set_size failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification progress size error");
+        }
+    } else if (progressType == NOTI_PROGRESS_TYPE_PERCENTAGE) {
+        ret = notification_set_progress(m_notiHandle, progressValue);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("set_progress failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification percentage error");
+        }
+    } else {
+        throw UnknownException("get notification progress type error");
+    }
+}
+
+NotificationProgressType StatusNotification::getProgressType()
+{
+    return m_progressType;
+}
+
+void StatusNotification::setProgressType(NotificationProgressType type)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+
+    LOGI("NotificationProgressType = %d", type);
+
+    std::string progressType;
+    int ret = 0;
+    if (type == NOTI_PROGRESS_TYPE_PERCENTAGE) {
+        progressType = TIZEN_NOTIFICATION_PROGRESS_TYPE_PERCENTAGE;
+    } else if (type == NOTI_PROGRESS_TYPE_SIZE) {
+        progressType = TIZEN_NOTIFICATION_PROGRESS_TYPE_BYTE;
+    } else {
+        throw TypeMismatchException("Invalid Progress Type.");
+    }
+
+    ret = notification_set_image(m_notiHandle, NOTIFICATION_IMAGE_TYPE_LIST_5,
+        progressType.c_str());
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("set_image failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "set notification image error");
+    }
+    m_progressType = type;
+}
+
+char* StatusNotification::getSubIconPath()
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+
+    char *subIconPath = NULL;
+    int ret = 0;
+
+    ret = notification_get_image(m_notiHandle, NOTIFICATION_IMAGE_TYPE_ICON_SUB,
+        &subIconPath);
+    if (ret != NOTIFICATION_ERROR_NONE)
+    {
+        LOGE("get_image failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification sub icon error");
+    }
+    return subIconPath;
+}
+
+void StatusNotification::setSubIconPath(const char *subIconPath)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+
+    char *origSubIcon = getSubIconPath();
+    int ret = 0;
+    if (subIconPath && origSubIcon)
+        LOGI("subIconPath = %s, origin SubIconPath = %s", subIconPath,
+            origSubIcon);
+    if (!origSubIcon || !subIconPath || strcmp(origSubIcon, subIconPath)) {
+        if (!origSubIcon && !subIconPath)
+            return;
+
+        ret = notification_set_image(m_notiHandle,
+            NOTIFICATION_IMAGE_TYPE_ICON_SUB, subIconPath);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("set_image failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification sub icon error");
+        }
+        setUpdatedFlag(true);
+    }
+}
+
+void StatusNotification::loadThumbnails()
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+
+    if (!m_thumbs.empty())
+        m_thumbs.clear();
+
+    char *thumb = NULL;
+    int ret = 0;
+    ret = notification_get_image(m_notiHandle, NOTIFICATION_IMAGE_TYPE_LIST_1,
+        &thumb);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_image failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification thumbnail error");
+    }
+    if (thumb) m_thumbs.push_back(thumb);
+    thumb = NULL;
+
+    ret = notification_get_image(m_notiHandle, NOTIFICATION_IMAGE_TYPE_LIST_2,
+        &thumb);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_image failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification sub information error");
+    }
+    if (thumb) m_thumbs.push_back(thumb);
+    thumb = NULL;
+
+    ret = notification_get_image(m_notiHandle, NOTIFICATION_IMAGE_TYPE_LIST_3,
+        &thumb);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_image failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification sub information error");
+    }
+
+    if (thumb) m_thumbs.push_back(thumb);
+    thumb = NULL;
+
+    ret = notification_get_image(m_notiHandle, NOTIFICATION_IMAGE_TYPE_LIST_4,
+        &thumb);
+
+    if (ret != NOTIFICATION_ERROR_NONE)
+    {
+        LOGE("get_image failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification sub information error");
+    }
+
+    if (thumb) m_thumbs.push_back(thumb);
+    thumb = NULL;
+}
+
+std::vector<std::string> StatusNotification::getThumbnails()
+{
+    LOGI("thumbnail Size : %d", m_thumbs.size());
+    return m_thumbs;
+}
+
+std::string StatusNotification::getThumbnail(int index)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+
+    LOGI("index : %d", index);
+
+    notification_image_type_e type = NOTIFICATION_IMAGE_TYPE_NONE;
+    int ret = 0;
+    switch (index) {
+        case 0:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_1;
+            break;
+        case 1:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_2;
+            break;
+        case 2:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_3;
+            break;
+        case 3:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_4;
+            break;
+        case 4:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_5;
+            break;
+        default :
+            type = NOTIFICATION_IMAGE_TYPE_NONE;
+    }
+
+    if (type != NOTIFICATION_IMAGE_TYPE_NONE) {
+        char *thumb = NULL;
+
+        ret = notification_get_image(m_notiHandle, type, &thumb);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("get_image failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "get notification image error");
+        }
+
+        std::string thumbnail;
+        if (thumb) thumbnail = thumb;
+        return thumbnail;
+    } else {
+        LOGE("image type is invalid: %d", type);
+        throw UnknownException("Image type is invalid");
+    }
+}
+
+void StatusNotification::setThumbnails(std::vector<std::string> thumbs)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+
+    std::vector<std::string>::iterator it;
+
+    int idx = 0;
+    for (it = thumbs.begin(); it < thumbs.end(); ++it) {
+        std::string str = *it;
+        if (idx < MAX_THUMBNAIL_LENGTH) {
+            // set notification's thumbnail value.
+            setThumbnail(str, idx);
+        }
+        idx ++;
+    }
+
+    m_thumbs = thumbs;
+}
+
+void StatusNotification::setThumbnail( const std::string& thumb, int index)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        return;
+    }
+
+    LOGI("index : %d", index);
+    LOGI("thumb : %s", thumb.c_str());
+    notification_image_type_e type = NOTIFICATION_IMAGE_TYPE_NONE;
+    int ret = 0;
+
+    switch (index) {
+        case 0:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_1;
+            break;
+        case 1:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_2;
+            break;
+        case 2:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_3;
+            break;
+        case 3:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_4;
+            break;
+        case 4:
+            type = NOTIFICATION_IMAGE_TYPE_LIST_5;
+            break;
+        default :
+            type = NOTIFICATION_IMAGE_TYPE_NONE;
+    }
+
+    if (type != NOTIFICATION_IMAGE_TYPE_NONE) {
+        if (getThumbnail(index).compare(thumb)) {
+            ret = notification_set_image(m_notiHandle, type, thumb.c_str());
+            if (ret != NOTIFICATION_ERROR_NONE) {
+                LOGE("set_image failed: %d, %s", ret,
+                    NotificationUtil::getNotificationErrorMessage(ret).c_str());
+                NotificationUtil::throwNotificationException(ret,
+                    "set notification thumbnail error");
+            }
+            setUpdatedFlag(true);
+        }
+    }
+}
+
+char* StatusNotification::getBackground()
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+    char *background = NULL;
+    int ret = 0;
+
+    ret = notification_get_image(m_notiHandle,
+        NOTIFICATION_IMAGE_TYPE_BACKGROUND, &background);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_image failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification background error");
+    }
+    return background;
+}
+
+void StatusNotification::setBackground(const char *imagePath)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+
+    char *origBackground = getBackground();
+    int ret = 0;
+    if (!origBackground || !imagePath || strcmp(origBackground, imagePath)) {
+        if (!origBackground && !imagePath)
+            return;
+
+        ret = notification_set_image(m_notiHandle,
+            NOTIFICATION_IMAGE_TYPE_BACKGROUND, imagePath);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("set_image failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification background error");
+        }
+        setUpdatedFlag(true);
+    }
+}
+
+long StatusNotification::getNumber()
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        return 0;
+    }
+
+    long number = 0;
+    char *strNumber = NULL;
+    int ret = 0;
+
+    ret = notification_get_text(m_notiHandle,
+        NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &strNumber);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_text failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification event count error");
+    }
+
+    if (strNumber)
+        std::istringstream(strNumber) >> number;
+    else
+        LOGI("Number Is NULL");
+
+    LOGI("number = %d", number);
+    return number;
+}
+
+const char* StatusNotification::getStrNumber()
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        return NULL;
+    }
+
+    char *strNumber = NULL;
+    int ret = 0;
+
+    ret = notification_get_text(m_notiHandle,
+        NOTIFICATION_TEXT_TYPE_EVENT_COUNT, &strNumber);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_text failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification event count error");
+    }
+
+    if (!strNumber) {
+        return NULL;
+    }
+
+    return strNumber;
+}
+
+void StatusNotification::setNumber(const long number)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is NULL");
+    }
+
+    if (number!=getNumber()) {
+        std::stringstream stream;
+        stream << number;
+
+        if (stream.fail()) {
+            throw UnknownException("Couldn't convert notification number");
+        }
+
+        std::string strNumber = stream.str();
+        int ret = 0;
+
+        ret = notification_set_text(m_notiHandle,
+            NOTIFICATION_TEXT_TYPE_EVENT_COUNT, strNumber.c_str(), NULL,
+            NOTIFICATION_VARIABLE_TYPE_NONE);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("set_text failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification event count error");
+        }
+        setUpdatedFlag(true);
+    }
+}
+
+void* StatusNotification::getNotificationHandle()
+{
+    return m_notiHandle;
+}
+
+void StatusNotification::setNotificationHandle(void *handle)
+{
+    if (!handle) {
+        throw UnknownException( "notification handle null error");
+    }
+
+    if (m_notiHandle != NULL) {
+
+        // delete old noti.
+        int ret = 0;
+
+        ret = notification_delete(m_notiHandle);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("delete failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "delete notification handle error");
+        }
+        m_notiHandle = NULL;
+    }
+
+    m_notiHandle = (notification_h)handle;
+}
+
+app_control_h StatusNotification::getService()
+{
+    return m_service;
+}
+
+std::string StatusNotification::getLight()
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    unsigned int ledColor = 0;
+    int ret = 0;
+    notification_led_op_e type = NOTIFICATION_LED_OP_ON;
+
+    ret = notification_get_led(m_notiHandle, &type, (int*)&ledColor);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_led failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification led error");
+    }
+
+    std::string light;
+    std::stringstream stream;
+    if (NOTIFICATION_LED_OP_OFF != type) {
+        ledColor = 0x00FFFFFF & ledColor;
+        stream <<  std::hex  << ledColor;
+        light = "#" + stream.str();
+        while(light.length() < 7) {
+            light.insert(1, "0");
+        }
+
+    }
+    LOGD("color: %s", light.c_str());
+    return boost::to_lower_copy(light);
+}
+
+bool StatusNotification::isColorFormatNumberic(std::string& color)
+{
+    // first check length
+    std::string hexCode = "0123456789abcdef";
+    if (color.length() == 7 && !color.compare(0, 1, "#"))
+    {
+        for ( size_t i = 1 ; i < color.length() ; i++)
+        {
+            if (std::string::npos == hexCode.find(color[i]))
+                return false;
+        }
+        return true;
+    }
+    return false;
+}
+
+void StatusNotification::setLight(std::string color)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    // convert lowercase.
+    color = boost::to_lower_copy(color);
+    if (isColorFormatNumberic(color)) {
+        std::stringstream stream;
+        unsigned int ledColor = 0;
+        int ret = 0;
+        notification_led_op_e type = NOTIFICATION_LED_OP_ON;
+        std::string colorCode = color.substr(1, color.length()).insert(0,"ff");
+
+        stream << std::hex << colorCode;
+        LOGI("LedColor = %s", stream.str().c_str());
+        stream >> ledColor;
+        LOGI("LedColor = %d", ledColor);
+
+        if (ledColor != 0)
+            type = NOTIFICATION_LED_OP_ON_CUSTOM_COLOR;
+        else
+            type = NOTIFICATION_LED_OP_OFF;
+
+        ret = notification_set_led(m_notiHandle, type, (int)ledColor);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("set_led failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification led error");
+        }
+
+    } else  {
+        LOGI("color.length() = %d", color.length());
+        throw InvalidValuesException("color code error!");
+    }
+}
+
+unsigned long StatusNotification::getLightOnTime()
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    int onTime = 0;
+    int offTime = 0;
+    int ret = 0;
+
+    ret = notification_get_led_time_period(m_notiHandle, &onTime, &offTime);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_led_time_period failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification led time period error");
+    }
+    LOGI("onTime %d", onTime);
+
+    return (unsigned long) onTime;
+}
+
+void StatusNotification::setLightOnTime(unsigned long time)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    int offTime = getLightOffTime();
+    int ret = 0;
+
+    ret = notification_set_led_time_period(m_notiHandle, time, offTime);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("set_led_time_period failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "set notification led time period error");
+    }
+}
+
+unsigned long StatusNotification::getLightOffTime()
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    int onTime = 0;
+    int offTime = 0;
+    int ret =0;
+
+    ret = notification_get_led_time_period(m_notiHandle, &onTime, &offTime);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_led_time_period failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification led time period error");
+    }
+    LOGI("offTime %d", offTime);
+    return offTime;
+}
+
+void StatusNotification::setLightOffTime(unsigned long time)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    int onTime = getLightOnTime();
+    int ret = 0;
+
+    ret = notification_set_led_time_period(m_notiHandle, onTime, time);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("set_led_time_period failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "set notification led time period error");
+    }
+}
+
+//Detail Info
+void StatusNotification::loadDetailInfos()
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    for ( int idx = 0; idx < MAX_NOTIFICATION_DETAIL_INFO_LENGTH; idx++) {
+        if (!isNullInformation(idx)) {
+            bool isNull = false;
+            std::string main = getInformation(idx);
+            std::string sub = getSubInformation(idx, isNull);
+
+            LOGI("Main:[%s], Sub:[%s], isNull:[%d]", main.c_str(), sub.c_str(),
+                isNull);
+
+            NotificationDetailInfo *info = NULL;
+            if (isNull)
+                info = new NotificationDetailInfo(m_notiHandle, idx, main);
+            else
+                info = new NotificationDetailInfo(m_notiHandle, idx, main, sub);
+            m_detailInfos.push_back(info);
+        }
+    }
+}
+
+std::vector<NotificationDetailInfo*> StatusNotification::getDetailInfos() const
+{
+    return m_detailInfos;
+}
+
+void StatusNotification::setDetailInfos(
+    const std::vector<NotificationDetailInfo*> value)
+{
+    LOGI("DetailInfos = %d", value.size());
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    int idx = 0;
+    for (auto it = value.begin(); it < value.end(); ++it) {
+        NotificationDetailInfo* info = *it;
+        if (idx < MAX_NOTIFICATION_DETAIL_INFO_LENGTH) {
+
+            LOGI("main: %s, sub: %s",
+                info->getMainText().c_str(), info->getSubText().c_str());
+            setInformation(info->getMainText(), idx);
+            setSubInformation(info->getSubText(), idx);
+        }
+        idx ++;
+    }
+
+    m_detailInfos = value;
+}
+
+int StatusNotification::getDetailInfosNum() const
+{
+    return m_detailInfos.size();
+}
+
+void StatusNotification::clearDetailInfos()
+{
+    if (!m_detailInfos.empty())
+    {
+        std::vector<NotificationDetailInfo*>::const_iterator it;
+
+        int idx = 0;
+        for (it = m_detailInfos.begin(); it < m_detailInfos.end(); ++it)
+        {
+            NotificationDetailInfo* info = *it;
+            LOGI("Delete Detail Info : %p", info);
+            if (info)
+                delete info;
+            idx ++;
+        }
+        m_detailInfos.clear();
+    }
+}
+
+std::string StatusNotification::getInformation(int index)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    notification_text_type_e type = NOTIFICATION_TEXT_TYPE_NONE;
+    int ret = 0;
+    switch (index)
+    {
+        case 0:
+            type = NOTIFICATION_TEXT_TYPE_INFO_1;
+            break;
+        case 1:
+            type = NOTIFICATION_TEXT_TYPE_INFO_2;
+            break;
+        case 2:
+            type = NOTIFICATION_TEXT_TYPE_INFO_3;
+            break;
+        default :
+            type = NOTIFICATION_TEXT_TYPE_NONE;
+    }
+
+    if (NOTIFICATION_TEXT_TYPE_NONE == type) {
+        LOGE("Detail info index value is invalid");
+        throw UnknownException("Detail info index value is invalid");
+    }
+
+    char *info = NULL;
+    ret = notification_get_text(m_notiHandle, type, &info);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_text failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification main text error");
+    }
+
+    std::string strInfo;
+    if (info)
+        strInfo = info;
+    LOGI("info: %s", strInfo.c_str());
+    return strInfo;
+}
+
+bool StatusNotification::isNullInformation(int index)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    notification_text_type_e type = NOTIFICATION_TEXT_TYPE_NONE;
+    int ret = 0;
+    switch (index)
+    {
+        case 0:
+            type = NOTIFICATION_TEXT_TYPE_INFO_1;
+            break;
+        case 1:
+            type = NOTIFICATION_TEXT_TYPE_INFO_2;
+            break;
+        case 2:
+            type = NOTIFICATION_TEXT_TYPE_INFO_3;
+            break;
+        default :
+            type = NOTIFICATION_TEXT_TYPE_NONE;
+    }
+    if (NOTIFICATION_TEXT_TYPE_NONE == type) {
+        LOGE("Detail info index value is invalid");
+        throw UnknownException("Detail info index value is invalid");
+    }
+
+    char *info = NULL;
+    ret = notification_get_text(m_notiHandle, type, &info);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_text failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification main text error");
+    }
+
+    if (info) {
+        LOGI("is not null");
+        return false;
+    } else {
+        LOGI("is null");
+        return true;
+    }
+}
+
+std::string StatusNotification::getSubInformation(int index, bool& isNull)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    notification_text_type_e type = NOTIFICATION_TEXT_TYPE_NONE;
+    int ret = 0;
+    switch (index)
+    {
+        case 0:
+            type = NOTIFICATION_TEXT_TYPE_INFO_SUB_1;
+            break;
+        case 1:
+            type = NOTIFICATION_TEXT_TYPE_INFO_SUB_2;
+            break;
+        case 2:
+            type = NOTIFICATION_TEXT_TYPE_INFO_SUB_3;
+            break;
+        default :
+            type = NOTIFICATION_TEXT_TYPE_NONE;
+    }
+
+    if (NOTIFICATION_TEXT_TYPE_NONE == type) {
+        LOGE("Detail info index value is invalid");
+        throw UnknownException("Detail info index value is invalid");
+    }
+
+    char *subInfo = NULL;
+    ret = notification_get_text(m_notiHandle, type, &subInfo);
+    if (ret != NOTIFICATION_ERROR_NONE) {
+        LOGE("get_text failed: %d, %s", ret,
+            NotificationUtil::getNotificationErrorMessage(ret).c_str());
+        NotificationUtil::throwNotificationException(ret,
+            "get notification sub text error");
+    }
+
+    std::string strSubInfo;
+    if (subInfo) {
+        strSubInfo = subInfo;
+        isNull = false;
+    } else {
+        isNull = true;
+    }
+    LOGI("subInfo: %s", strSubInfo.c_str());
+    LOGI("isNull: %d", isNull);
+    return strSubInfo;
+}
+
+void StatusNotification::setInformation( const std::string& info, int index)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    int idx = index;
+    int ret = 0;
+    LOGD("index : %d", idx);
+    LOGD("log : %s", info.c_str());
+
+    notification_text_type_e type = NOTIFICATION_TEXT_TYPE_NONE;
+    switch (idx)
+    {
+        case 0:
+            type = NOTIFICATION_TEXT_TYPE_INFO_1;
+            break;
+        case 1:
+            type = NOTIFICATION_TEXT_TYPE_INFO_2;
+            break;
+        case 2:
+            type = NOTIFICATION_TEXT_TYPE_INFO_3;
+            break;
+        default :
+            type = NOTIFICATION_TEXT_TYPE_NONE;
+    }
+
+    if (NOTIFICATION_TEXT_TYPE_NONE == type) {
+        LOGE("Detail info index value is invalid");
+        throw UnknownException("Detail info index value is invalid");
+    }
+
+    if (getInformation(idx).compare(info) || isNullInformation(idx))
+    {
+        ret = notification_set_text(m_notiHandle, type, info.c_str(), NULL,
+            NOTIFICATION_VARIABLE_TYPE_NONE);
+        if (ret != NOTIFICATION_ERROR_NONE)
+        {
+            LOGE("set_text failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification main text error");
+        }
+        setUpdatedFlag(true);
+    }
+}
+
+void StatusNotification::setSubInformation( const std::string& subInfo, int index)
+{
+    if (!m_notiHandle) {
+        LOGE("noti handle is NULL");
+        throw UnknownException("notification handle is null");
+    }
+
+    int idx = index;
+    LOGD("index : %d", idx);
+    LOGD("log : %s", subInfo.c_str());
+    notification_text_type_e type = NOTIFICATION_TEXT_TYPE_NONE;
+    int ret = 0;
+
+    switch (idx)
+    {
+        case 0:
+            type = NOTIFICATION_TEXT_TYPE_INFO_SUB_1;
+            break;
+        case 1:
+            type = NOTIFICATION_TEXT_TYPE_INFO_SUB_2;
+            break;
+        case 2:
+            type = NOTIFICATION_TEXT_TYPE_INFO_SUB_3;
+            break;
+        default :
+            type = NOTIFICATION_TEXT_TYPE_NONE;
+    }
+
+    if (NOTIFICATION_TEXT_TYPE_NONE == type) {
+        LOGE("Detail info index value is invalid");
+        throw UnknownException("Detail info index value is invalid");
+    }
+
+    bool isNull = false;
+    if (getSubInformation(idx, isNull).compare(subInfo)) {
+        ret = notification_set_text(m_notiHandle, type, subInfo.c_str(), NULL,
+            NOTIFICATION_VARIABLE_TYPE_NONE);
+        if (ret != NOTIFICATION_ERROR_NONE) {
+            LOGE("set_text failed: %d, %s", ret,
+                NotificationUtil::getNotificationErrorMessage(ret).c_str());
+            NotificationUtil::throwNotificationException(ret,
+                "set notification sub text error");
+        }
+        setUpdatedFlag(true);
+    }
+}
+
+} // Notification
+} // DeviceAPI
diff --git a/src/Notification/StatusNotification.h b/src/Notification/StatusNotification.h
new file mode 100755 (executable)
index 0000000..92b406b
--- /dev/null
@@ -0,0 +1,187 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_STATUS_NOTIFICATION_H__
+#define __TIZEN_STATUS_NOTIFICATION_H__
+
+#include <MultiCallbackUserData.h>
+
+#include <app.h>
+#include <notification.h>
+#include <notification_internal.h>
+
+#include <JSApplicationControl.h>
+#include "NotificationTypes.h"
+#include "NotificationDetailInfo.h"
+
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Notification {
+
+class StatusNotification
+{
+
+public:
+    // type
+    explicit StatusNotification(NotificationType type);
+    // notification
+    explicit StatusNotification(void* noti);
+    // private ID of Notification
+    explicit StatusNotification(int privID);
+
+    ~StatusNotification();
+
+    std::string getEnumProgressType();
+
+        void setUpdatedFlag(bool value)
+        {
+             if (value)
+                 LOGD("set True");
+             m_notiUpdated = value;
+        }
+
+        bool getUpdatedFlag()
+        {
+             return m_notiUpdated;
+        }
+
+    bool getLaunchFlag()
+    {
+        return m_launchFlag;
+    }
+
+    void setLaunchFlag(bool value)
+    {
+        m_launchFlag = value;
+    }
+
+    NotificationType getNotiType()
+    {
+        return m_notiType;
+    }
+
+    void setNotiType(NotificationType type)
+    {
+        m_notiType = type;
+    }
+
+    int getID();
+    std::string getStatusType();
+    void setStatusType(std::string type);
+
+    time_t getPostedTime();
+    std::string getTitle();
+    void setTitle(std::string title);
+
+    char* getContent();
+    void setContent(const char* content);
+
+    char* getIconPath() ;
+    void setIconPath(const char* iconPath) ;
+
+    const char* getSoundPath() ;
+    void setSoundPath(const char* sound) ;
+
+    bool getDefaultVibration() ;
+    void setDefaultVibration(const bool& vibration) ;
+
+    NotificationProgressType getProgressType();
+    void setProgressType(NotificationProgressType type);
+
+        double getProgressValue() ;
+        void setProgressValue(const double & progressValue);
+
+    char* getSubIconPath() ;
+    void setSubIconPath(const char *subIconPath);
+
+    std::vector<std::string> getThumbnails();
+    void setThumbnails(std::vector<std::string> thumbs);
+
+    char* getBackground() ;
+    void setBackground(const char* imagePath) ;
+
+    long getNumber() ;
+    const char* getStrNumber() ;
+    void setNumber(const long number) ;
+
+    DeviceAPI::Application::ApplicationControlPtr getApplicationControl();
+    void setApplicationControl(
+        DeviceAPI::Application::ApplicationControlPtr control);
+    void setApplicationId(const char* appId);
+    std::string getApplicationId();
+    bool isNullApplicationID();
+
+    std::string getLight();
+    void setLight(std::string color);
+
+    unsigned long getLightOnTime();
+    void setLightOnTime(unsigned long onTime);
+
+    unsigned long getLightOffTime();
+    void setLightOffTime(unsigned long offTime);
+
+    void* getNotificationHandle();
+    void setNotificationHandle(void *handle);
+
+    app_control_h getService();
+
+    // Detail Info
+    std::vector<NotificationDetailInfo*> getDetailInfos() const;
+    void setDetailInfos(const std::vector<NotificationDetailInfo*> value);
+    int getDetailInfosNum() const;
+    void addDetailInfo(NotificationDetailInfo* value);
+    void clearDetailInfos();
+
+private:
+
+    void loadThumbnails();
+    void setThumbnail( const std::string& info, int index);
+    std::string getThumbnail(int index);
+
+    std::string getInformation(int index);
+    bool isNullInformation(int index);
+    void setInformation( const std::string& info, int index) ;
+
+    std::string getSubInformation(int index, bool& isNull);
+    void setSubInformation( const std::string& info, int index) ;
+
+    void loadDetailInfos();
+
+    bool isColorFormatNumberic(std::string& color);
+
+protected:
+
+    NotificationType m_notiType;
+    app_control_h m_service;
+    notification_h m_notiHandle;
+    NotificationProgressType m_progressType;
+    bool m_notiUpdated;
+    bool m_launchFlag;
+
+    // thumbnail images path
+    std::vector<std::string> m_thumbs;
+    // detail Info
+    std::vector<NotificationDetailInfo*> m_detailInfos;
+};
+
+} // Notification
+} // DeviceAPI
+
+#endif // __TIZEN_STATUS_NOTIFICATION_H__
diff --git a/src/Notification/config.xml b/src/Notification/config.xml
new file mode 100644 (file)
index 0000000..f059ad2
--- /dev/null
@@ -0,0 +1,21 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-notification.so</library-name>
+    <feature-install-uri>notification.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/notification</name>
+        <device-capability>notification</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/notification.read</name>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/notification.write</name>
+        <device-capability>notification</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/Notification/plugin_config.cpp b/src/Notification/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..a540403
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Notification {
+
+#define NOTIFICATION_DEVICE_CAP "notification"
+#define NOTIFICATION_FEATURE_API "http://tizen.org/privilege/notification"
+#define NOTIFICATION_FEATURE_API_WRITE "http://tizen.org/privilege/notification.write"
+
+static FunctionMapping createNotificationFunctions();
+static FunctionMapping NotificationFunctions = createNotificationFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(Notification, NotificationFunctions);
+
+#pragma GCC visibility pop
+
+static FunctionMapping createNotificationFunctions()
+{
+    FunctionMapping pushMapping;
+
+    /**
+    * Device capabilities
+    */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_NOTIFICATION, NOTIFICATION_DEVICE_CAP);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_NOTIFICATION);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_NOTIFICATION, DEVICE_CAP_NOTIFICATION);
+
+    /**
+    * Api Features
+    */
+    ACE_CREATE_FEATURE(NOTIFICATION_FEATURE_WRITE, NOTIFICATION_FEATURE_API_WRITE);
+    ACE_CREATE_FEATURE_LIST(NOTIFICATION_FEATURES_WRITE);
+    ACE_ADD_API_FEATURE(NOTIFICATION_FEATURES_WRITE, NOTIFICATION_FEATURE_WRITE);
+
+    ACE_CREATE_FEATURE(NOTIFICATION_FEATURE, NOTIFICATION_FEATURE_API);
+    ACE_CREATE_FEATURE_LIST(NOTIFICATION_FEATURES);
+    ACE_ADD_API_FEATURE(NOTIFICATION_FEATURES, NOTIFICATION_FEATURE_WRITE);
+    ACE_ADD_API_FEATURE(NOTIFICATION_FEATURES, NOTIFICATION_FEATURE);
+
+
+    AceFunction NotificationWrite = ACE_CREATE_FUNCTION(FUNCTION_NOTIFICATION_WRITE, NOTIFICATION_FUNC,
+       NOTIFICATION_FEATURES, DEVICE_LIST_NOTIFICATION);
+
+    pushMapping.insert(std::make_pair(NOTIFICATION_FUNC, NotificationWrite));
+
+    return pushMapping;
+}
+
+} // Notification
+} // DeviceAPI
diff --git a/src/Notification/plugin_config.h b/src/Notification/plugin_config.h
new file mode 100755 (executable)
index 0000000..c3584ac
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _NOTIFICATION_PLUGIN_CONFIG_H_
+#define _NOTIFICATION_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Notification {
+
+// attributes
+#define NOTIFICATION_ID "id"
+#define NOTIFICATION_TYPE "type"
+#define NOTIFICATION_POSTED_TIME "postedTime"
+#define NOTIFICATION_TITLE "title"
+#define NOTIFICATION_CONTENT "content"
+#define STATUS_NOTIFICATION_STATUS_TYPE "statusType"
+#define STATUS_NOTIFICATION_ICON_PATH "iconPath"
+#define STATUS_NOTIFICATION_SUB_ICON_PATH "subIconPath"
+#define STATUS_NOTIFICATION_NUMBER "number"
+#define STATUS_NOTIFICATION_DETAIL_INFO "detailInfo"
+#define STATUS_NOTIFICATION_BACKGROUND_IMAGE_PATH "backgroundImagePath"
+#define STATUS_NOTIFICATION_THUMBNAILS "thumbnails"
+#define STATUS_NOTIFICATION_SOUND_PATH "soundPath"
+#define STATUS_NOTIFICATION_VIBRATION "vibration"
+#define STATUS_NOTIFICATION_APP_CONTROL "appControl"
+#define STATUS_NOTIFICATION_APP_ID "appId"
+#define STATUS_NOTIFICATION_LIGHT "ledColor"
+#define STATUS_NOTIFICATION_LIGHT_ONTIME "ledOnPeriod"
+#define STATUS_NOTIFICATION_LIGHT_OFFTIME "ledOffPeriod"
+#define STATUS_NOTIFICATION_PROGRESS_TYPE "progressType"
+#define STATUS_NOTIFICATION_PROGRESS_VALUE "progressValue"
+#define NOTIFICATION_DETAIL_INFO_MAIN_TEXT "mainText"
+#define NOTIFICATION_DETAIL_INFO_SUB_TEXT "subText"
+
+// functions
+#define NOTIFICATION_MANAGER_API_POST "post"
+#define NOTIFICATION_MANAGER_API_UPDATE "update"
+#define NOTIFICATION_MANAGER_API_REMOVE "remove"
+#define NOTIFICATION_MANAGER_API_REMOVE_ALL "removeAll"
+#define NOTIFICATION_MANAGER_API_GET "get"
+#define NOTIFICATION_MANAGER_API_GET_ALL "getAll"
+
+#define NOTIFICATION_FUNC "Notification"
+
+DECLARE_FUNCTION_GETTER(Notification);
+
+#define NOTIFICATION_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getNotificationFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _NOTIFICATION_PLUGIN_CONFIG_H_
diff --git a/src/Notification/plugin_initializer.cpp b/src/Notification/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..8304acf
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+
+#include "JSNotificationManager.h"
+#include "JSStatusNotification.h"
+#include "JSNotificationDetailInfo.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Notification {
+
+class_definition_options_t ConstructorClassOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Notification] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Notification] on_widget_stop_callback (%d)", widgetId);
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"Notification");
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Notification] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Notification] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "notification",
+        (js_class_template_getter)JSNotificationManager::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "StatusNotification",
+        (js_class_template_getter)JSStatusNotification::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSStatusNotification::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "NotificationDetailInfo",
+        (js_class_template_getter)JSNotificationDetailInfo::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSNotificationDetailInfo::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_END
+
+} // Notification
+} // DeviceAPI
diff --git a/src/Package/CMakeLists.txt b/src/Package/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..04e76da
--- /dev/null
@@ -0,0 +1,56 @@
+SET(TARGET_NAME ${package_target})
+SET(DESTINATION_NAME ${package_dest})
+SET(TARGET_IMPL_NAME ${package_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_package REQUIRED
+    capi-appfw-app-manager
+    capi-appfw-package-manager
+    pkgmgr
+    pkgmgr-info
+)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${TOP}/Package
+    ${platform_pkgs_package_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSPackageInformation.cpp
+    JSPackageManager.cpp
+    PackageInformation.cpp
+    PackageManager.cpp
+    PackageUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${platform_pkgs_package_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/package
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Package/JSPackageInformation.cpp b/src/Package/JSPackageInformation.cpp
new file mode 100755 (executable)
index 0000000..d8942cb
--- /dev/null
@@ -0,0 +1,165 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include "JSPackageInformation.h"
+#include "PackageInformation.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Package {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+JSClassRef JSPackageInformation::m_classRef = NULL;
+
+JSClassDefinition JSPackageInformation::m_classInfo = {
+    0,                                        // current (and only) version is 0
+    kJSClassAttributeNone,                    // attributes
+    TIZEN_INTERFACE_PACKAGE_INFORMATION,    // class name
+    NULL,                                    // parent class
+    m_property,                                // static values
+    NULL,                                    // static functions
+    initialize,                                // initialize
+    finalize,                                // finalize
+    NULL,                                    // hasProperty
+    NULL,                                    // getProperty
+    NULL,                                    // setProperty
+    NULL,                                    // deleteProperty
+    NULL,                                    // getPropertyNames
+    NULL,                                    // callAsConstructor
+    NULL,                                    // callAsConstructor
+    NULL,                                    // hasInstance
+    NULL                                    // convertToType
+};
+
+JSStaticValue JSPackageInformation::m_property[] = {
+    { TIZEN_PACKAGE_INFORMATION_ID, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PACKAGE_INFORMATION_NAME, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PACKAGE_INFORMATION_ICONPATH, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PACKAGE_INFORMATION_VERSION, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PACKAGE_INFORMATION_TOTAL_SIZE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PACKAGE_INFORMATION_DATA_SIZE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PACKAGE_INFORMATION_LAST_MODIFIED, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PACKAGE_INFORMATION_AUTHOR, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PACKAGE_INFORMATION_DESCRIPTION, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PACKAGE_INFORMATION_APP_IDS, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSPackageInformation::getClassRef() {
+    if (!m_classRef) {
+        m_classRef = JSClassCreate(&m_classInfo);
+    }
+    return m_classRef;
+}
+
+
+JSValueRef JSPackageInformation::createJSObject(JSContextRef context, PackageInformation *pkgInfo)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(pkgInfo));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    return jsValueRef;
+}
+
+
+void JSPackageInformation::initialize(JSContextRef context, JSObjectRef object)
+{
+}
+
+void JSPackageInformation::finalize(JSObjectRef object)
+{
+}
+
+bool JSPackageInformation::isObjectOfClass(JSContextRef context, JSValueRef value)
+{
+    return JSValueIsObjectOfClass(context, value, getClassRef());
+}
+
+PackageInformation* JSPackageInformation::getPrivData(JSObjectRef object)
+{
+    PackageInformation *priv = static_cast<PackageInformation*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Private object is null");
+        throw TypeMismatchException("Private object is null");
+    }
+
+    return priv;
+}
+
+JSValueRef JSPackageInformation::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        PackageInformation* privateData = getPrivData(object);
+        if (!privateData) {
+            LOGE("Private object is NULL");
+            throw TypeMismatchException("Private object is NULL");
+        }
+
+        if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_ID)) {
+            return JSUtil::toJSValueRef(context, privateData->m_id);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_NAME)) {
+            return JSUtil::toJSValueRef(context, privateData->m_name);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_ICONPATH)) {
+            return JSUtil::toJSValueRef(context, privateData->m_iconPath);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_VERSION)) {
+            return JSUtil::toJSValueRef(context, privateData->m_version);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_LAST_MODIFIED)) {
+            return JSUtil::makeDateObject(context, privateData->m_lastModified);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_AUTHOR)) {
+            return JSUtil::toJSValueRef(context, privateData->m_author);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_DESCRIPTION)) {
+            return JSUtil::toJSValueRef(context, privateData->m_description);
+        } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_APP_IDS)) {
+            return JSUtil::toJSValueRef(context, privateData->m_appIds);
+        } else {
+            // Operation to get size need long time (IPC Delay).
+            if (!privateData->m_isInitialized) {
+                privateData->initializePackageInfo();
+            }
+
+            if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_TOTAL_SIZE)) {
+                return JSUtil::toJSValueRef(context, privateData->m_totalSize);
+            } else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PACKAGE_INFORMATION_DATA_SIZE)) {
+                return JSUtil::toJSValueRef(context, privateData->m_dataSize);
+            }
+        }
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::TypeMismatchException err("TypeMismatchException occured");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+}
+}
diff --git a/src/Package/JSPackageInformation.h b/src/Package/JSPackageInformation.h
new file mode 100755 (executable)
index 0000000..1448566
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_JS_PACKAGE_INFORMATION_H_
+#define _TIZEN_JS_PACKAGE_INFORMATION_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "PackageInformation.h"
+
+namespace DeviceAPI {
+namespace Package {
+
+#define TIZEN_INTERFACE_PACKAGE_INFORMATION             "PackageInformation"
+
+// Fields
+#define TIZEN_PACKAGE_INFORMATION_ID                     "id"
+#define TIZEN_PACKAGE_INFORMATION_NAME                 "name"
+#define TIZEN_PACKAGE_INFORMATION_ICONPATH             "iconPath"
+#define TIZEN_PACKAGE_INFORMATION_VERSION                 "version"
+#define TIZEN_PACKAGE_INFORMATION_TOTAL_SIZE             "totalSize"
+#define TIZEN_PACKAGE_INFORMATION_DATA_SIZE             "dataSize"
+#define TIZEN_PACKAGE_INFORMATION_LAST_MODIFIED         "lastModified"
+#define TIZEN_PACKAGE_INFORMATION_AUTHOR                 "author"
+#define TIZEN_PACKAGE_INFORMATION_TYPE                     "type"
+#define TIZEN_PACKAGE_INFORMATION_DESCRIPTION            "description"
+#define TIZEN_PACKAGE_INFORMATION_APP_IDS                "appIds"
+
+class JSPackageInformation {
+public:
+    /*
+     * This initializes this JS class in the JS Engine.
+     */
+    static JSClassRef getClassRef();
+
+    static JSValueRef createJSObject(JSContextRef context, PackageInformation *pkgInfo);
+
+    static bool isObjectOfClass(JSContextRef context, JSValueRef value);
+
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_classRef;
+
+    static PackageInformation* getPrivData(JSObjectRef object);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+};
+
+}
+}
+#endif
diff --git a/src/Package/JSPackageManager.cpp b/src/Package/JSPackageManager.cpp
new file mode 100755 (executable)
index 0000000..6f92d7f
--- /dev/null
@@ -0,0 +1,365 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <PlatformException.h>
+#include <CommonsJavaScript/Converter.h>
+#include <JSUtil.h>
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+
+#include "JSPackageManager.h"
+#include "JSPackageInformation.h"
+#include "PackageManager.h"
+#include "PackageInformation.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Package {
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+
+JSClassRef JSPackageManager::m_jsClassRef = NULL;
+
+JSClassDefinition JSPackageManager::m_classInfo = {
+    0,                                    // current (and only) version is 0
+    kJSClassAttributeNone,                    // attributes
+    TIZEN_INTERFACE_PACKAGE_MANAGER,        // class name
+    NULL,                                // parent class
+    NULL,                                // static values
+    m_function,                            // static functions
+    initialize,                                // initialize
+    finalize,                                // finalize
+    NULL,                                // hasProperty
+    NULL,                                // getProperty
+    NULL,                                // setProperty
+    NULL,                                // deleteProperty
+    NULL,                                // getPropertyNames
+    NULL,                                // callAsConstructor
+    NULL,                                // callAsConstructor
+    NULL,                                // hasInstance
+    NULL                                    // convertToType
+};
+
+JSStaticFunction JSPackageManager::m_function[] = {
+    { PACKAGE_FUNCTION_API_INSTALL, JSPackageManager::install, kJSPropertyAttributeNone },
+    { PACKAGE_FUNCTION_API_UNINSTALL, JSPackageManager::uninstall, kJSPropertyAttributeNone },
+    { PACKAGE_FUNCTION_API_GET_PACKAGE_INFO, JSPackageManager::getPackageInfo, kJSPropertyAttributeNone },
+    { PACKAGE_FUNCTION_API_GET_PACKAGES_INFO, JSPackageManager::getPackagesInfo, kJSPropertyAttributeNone },
+    { PACKAGE_FUNCTION_API_SET_PACKAGE_INFO_EVENT_LISTENER, JSPackageManager::setPackageInfoEventListener, kJSPropertyAttributeNone },
+    { PACKAGE_FUNCTION_API_UNSET_PACKAGE_INFO_EVENT_LISTENER, JSPackageManager::unsetPackageInfoEventListener, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSPackageManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSPackageManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSPackageManager::initialize(JSContextRef context, JSObjectRef object)
+{
+}
+
+void JSPackageManager::finalize(JSObjectRef object)
+{
+    CallbackUserData *callback = static_cast<CallbackUserData*>(JSObjectGetPrivate(object));
+    if( callback != NULL ){
+        JSObjectSetPrivate(object, NULL);
+        delete callback;
+    }
+}
+
+JSValueRef JSPackageManager::install(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    TIME_TRACER_ITEM_BEGIN("install(ACE)", 0);
+    AceSecurityStatus status = PACKAGE_CHECK_ACCESS(PACKAGE_FUNCTION_API_INSTALL);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    TIME_TRACER_ITEM_END("install(ACE)", 0);
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        string path = validator.toString(0);
+
+        JSObjectRef eventCBObj = validator.toCallbackObject(1, false, "onprogress", "oncomplete", NULL);
+        JSObjectRef errCB = validator.toFunction(2, true);
+
+        CallbackUserData *onprogressCb = NULL;
+        CallbackUserData *oncompleteCb = NULL;
+        CallbackUserData *onerrorCb = NULL;
+
+        JSValueRef onprogress = JSUtil::getProperty(context, eventCBObj, "onprogress", exception);
+        if (!JSValueIsUndefined(context, onprogress)) {
+            onprogressCb = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            onprogressCb->setSuccessCallback(onprogress);
+        }
+
+        JSValueRef oncomplete = JSUtil::getProperty(context, eventCBObj, "oncomplete", exception);
+        if (!JSValueIsUndefined(context, oncomplete)) {
+            oncompleteCb = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            oncompleteCb->setSuccessCallback(oncomplete);
+        }
+
+        if (errCB) {
+            onerrorCb = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            onerrorCb->setSuccessCallback(errCB);
+        }
+
+        PackageInstallEventCallback *pkgInstallEventCB = new PackageInstallEventCallback(GlobalContextManager::getInstance()->getGlobalContext(context), onprogressCb, oncompleteCb, onerrorCb);
+
+        PackageManager::getInstance()->install(path, pkgInstallEventCB);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSPackageManager::uninstall(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    TIME_TRACER_ITEM_BEGIN("uninstall(ACE)", 0);
+    AceSecurityStatus status = PACKAGE_CHECK_ACCESS(PACKAGE_FUNCTION_API_INSTALL);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    TIME_TRACER_ITEM_END("uninstall(ACE)", 0);
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        string id = validator.toString(0);
+        //JSObjectRef eventCBObj = validator.toObject(1, true);
+        JSObjectRef eventCBObj = validator.toCallbackObject(1, false, "onprogress", "oncomplete", NULL);
+        JSObjectRef errCB = validator.toFunction(2, true);
+
+        CallbackUserData *onprogressCb = NULL;
+        CallbackUserData *oncompleteCb = NULL;
+        CallbackUserData *onerrorCb = NULL;
+
+        JSValueRef onprogress = JSUtil::getProperty(context, eventCBObj, "onprogress", exception);
+        if (!JSValueIsUndefined(context, onprogress)) {
+            onprogressCb = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            onprogressCb->setSuccessCallback(onprogress);
+        }
+
+        JSValueRef oncomplete = JSUtil::getProperty(context, eventCBObj, "oncomplete", exception);
+        if (!JSValueIsUndefined(context, oncomplete)) {
+            oncompleteCb = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            oncompleteCb->setSuccessCallback(oncomplete);
+        }
+
+        if (errCB) {
+            onerrorCb = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            onerrorCb->setSuccessCallback(errCB);
+        }
+
+        PackageInstallEventCallback *pkgInstallEventCB = new PackageInstallEventCallback(GlobalContextManager::getInstance()->getGlobalContext(context), onprogressCb, oncompleteCb, onerrorCb);
+
+        PackageManager::getInstance()->uninstall(id, pkgInstallEventCB);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSPackageManager::getPackagesInfo(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    TIME_TRACER_ITEM_BEGIN("getPackagesInfo(ACE)", 0);
+    AceSecurityStatus status = PACKAGE_CHECK_ACCESS(PACKAGE_FUNCTION_API_GET_PACKAGES_INFO);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    TIME_TRACER_ITEM_END("getPackagesInfo(ACE)", 0);
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCBObj = validator.toFunction(0);
+        JSObjectRef errCB = validator.toFunction(1, true);
+
+        PackageInfoCallbackData *callback = new PackageInfoCallbackData(GlobalContextManager::getInstance()->getGlobalContext(context));
+        callback->setSuccessCallback(successCBObj);
+        if (argumentCount > 1) {
+            callback->setErrorCallback(errCB);
+        }
+
+        PackageManager::getInstance()->getPackagesInfo(callback);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSPackageManager::getPackageInfo(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    TIME_TRACER_ITEM_BEGIN("(getPackageInfo) ACE", 0);
+    AceSecurityStatus status = PACKAGE_CHECK_ACCESS(PACKAGE_FUNCTION_API_GET_PACKAGE_INFO);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    TIME_TRACER_ITEM_END("(getPackageInfo) ACE", 0);
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        string id = validator.toString(0, true);
+
+        PackageInformation* pkgInfo = PackageManager::getInstance()->getPackageInfo(id);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSPackageInformation::createJSObject(context, pkgInfo);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSPackageManager::setPackageInfoEventListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    TIME_TRACER_ITEM_BEGIN("(setPackageInfoEventListener) ACE", 0);
+    AceSecurityStatus status = PACKAGE_CHECK_ACCESS(PACKAGE_FUNCTION_API_SET_PACKAGE_INFO_EVENT_LISTENER);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    TIME_TRACER_ITEM_END("(setPackageInfoEventListener) ACE", 0);
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef eventCBObj = validator.toCallbackObject(0, false, "oninstalled", "onupdated", "onuninstalled", NULL);
+
+        CallbackUserData *oninstalledCb = NULL;
+        CallbackUserData *onupdatedCb = NULL;
+        CallbackUserData *onuninstalledCb = NULL;
+
+        JSValueRef oninstalled = JSUtil::getProperty(context, eventCBObj, "oninstalled", exception);
+        if (!JSValueIsUndefined(context, oninstalled)) {
+            oninstalledCb = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            oninstalledCb->setSuccessCallback(oninstalled);
+        }
+
+        JSValueRef onupdated = JSUtil::getProperty(context, eventCBObj, "onupdated", exception);
+        if (!JSValueIsUndefined(context, onupdated)) {
+            onupdatedCb = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            onupdatedCb->setSuccessCallback(onupdated);
+        }
+
+        JSValueRef onuninstalled = JSUtil::getProperty(context, eventCBObj, "onuninstalled", exception);
+        if (!JSValueIsUndefined(context, onuninstalled)) {
+            onuninstalledCb = new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+            onuninstalledCb->setSuccessCallback(onuninstalled);
+        }
+
+        PackageInfoEventCallback *pkginfoEventCB = new PackageInfoEventCallback(oninstalledCb, onupdatedCb, onuninstalledCb);
+
+        PackageManager::getInstance()->setPackageInfoEventListener(pkginfoEventCB);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in ApplicationManager.getAppSharedURI().");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSPackageManager::unsetPackageInfoEventListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    TIME_TRACER_ITEM_BEGIN("(unsetPackageInfoEventListener) ACE", 0);
+    AceSecurityStatus status = PACKAGE_CHECK_ACCESS(PACKAGE_FUNCTION_API_UNSET_PACKAGE_INFO_EVENT_LISTENER);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    TIME_TRACER_ITEM_END("(unsetPackageInfoEventListener) ACE", 0);
+
+    try {
+        PackageManager::getInstance()->unsetPackageInfoEventListener();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSValueMakeUndefined(context);
+
+    } catch(const BasePlatformException& err) {
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+}
+}
diff --git a/src/Package/JSPackageManager.h b/src/Package/JSPackageManager.h
new file mode 100755 (executable)
index 0000000..214d6e0
--- /dev/null
@@ -0,0 +1,98 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_JS_PACKAGE_MANAGER_H_
+#define _TIZEN_JS_PACKAGE_MANAGER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+
+namespace DeviceAPI {
+namespace Package {
+
+#define TIZEN_INTERFACE_PACKAGE_MANAGER "PackageManager"
+
+class JSPackageManager {
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Install an package
+     */
+    static JSValueRef install(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Uninstall an package
+     */
+    static JSValueRef uninstall(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+
+    /**
+     * Gets the list of installed packages.
+     */
+    static JSValueRef getPackagesInfo(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Gets the package information of based on the package ID.
+     */
+    static JSValueRef getPackageInfo(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+
+    /**
+     * Watch for package installation & uninstallation.
+     */
+    static JSValueRef setPackageInfoEventListener(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * Unset watch for installation & uninstallation
+     */
+    static JSValueRef unsetPackageInfoEventListener(JSContextRef context, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount,
+            const JSValueRef arguments[], JSValueRef* exception);
+
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+}
+}
+#endif
diff --git a/src/Package/PackageInformation.cpp b/src/Package/PackageInformation.cpp
new file mode 100755 (executable)
index 0000000..0495e0e
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <package-manager.h>
+#include <pkgmgr-info.h>
+#include <Logger.h>
+
+#include "PackageInformation.h"
+#include "PackageUtil.h"
+
+namespace DeviceAPI {
+namespace Package {
+
+PackageInformation::PackageInformation() :
+    m_isInitialized(false)
+{
+}
+
+PackageInformation::~PackageInformation()
+{
+}
+
+void PackageInformation::initializePackageInfo()
+{
+    LOGD("Enter : %s", m_id.c_str());
+
+    pkgmgr_client *pc = pkgmgr_client_new(PC_REQUEST);
+    if (pc == NULL) {
+        LOGE("Fail to create pkgmgr client");
+    } else {
+        int ret = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, PM_GET_TOTAL_SIZE, pc, NULL, m_id.c_str(), NULL, NULL, NULL);
+        if (ret < 0) {
+            LOGE("Fail to get total size");
+        } else {
+            m_totalSize = ret;
+        }
+
+        ret = pkgmgr_client_request_service(PM_REQUEST_GET_SIZE, PM_GET_DATA_SIZE, pc, NULL, m_id.c_str(), NULL, NULL, NULL);
+        if (ret < 0) {
+            LOGE("Fail to get data size");
+        } else {
+            m_dataSize = ret;
+        }
+
+        ret = pkgmgr_client_free(pc);
+        if(ret != PMINFO_R_OK){
+            LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+        }
+        pc = NULL;
+    }
+
+    LOGD("enter");
+    m_isInitialized = true;
+}
+
+}
+}
diff --git a/src/Package/PackageInformation.h b/src/Package/PackageInformation.h
new file mode 100644 (file)
index 0000000..009c0f7
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_PACKAGE_INFORMATION_H_
+#define _TIZEN_PACKAGE_INFORMATION_H_
+
+#include <string>
+#include <vector>
+
+namespace DeviceAPI {
+namespace Package {
+
+using namespace std;
+
+class PackageInformation
+{
+public:
+    PackageInformation();
+    ~PackageInformation();
+    void initializePackageInfo();
+
+public:
+    string m_id;
+    string m_name;
+    string m_iconPath;
+    string m_version;
+    time_t m_lastModified;
+    long m_totalSize;
+    long m_dataSize;;
+    string m_author;
+    string m_type;
+    string m_description;
+    vector<string> m_appIds;
+    bool m_isInitialized;
+};
+
+}
+}
+#endif
diff --git a/src/Package/PackageManager.cpp b/src/Package/PackageManager.cpp
new file mode 100755 (executable)
index 0000000..7144770
--- /dev/null
@@ -0,0 +1,853 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <glib.h>
+#include <JSWebAPIErrorFactory.h>
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+// to get package name by appid
+#include <app_manager.h>
+
+// To get cert information from package
+#include <package_manager.h>
+#include <package_info.h>
+
+// To get app size and installed time
+#include <pkgmgr-info.h>
+
+// To use ecore_thread
+#include <Ecore.h>
+
+#include <TimeTracer.h>
+#include <Logger.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "PackageManager.h"
+#include "PackageInformation.h"
+#include "JSPackageInformation.h"
+#include "PackageUtil.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+using namespace std;
+
+#ifdef __cplusplus
+extern "C" {
+int package_manager_client_destroy(package_manager_request_h request);
+}
+#endif
+
+namespace DeviceAPI {
+namespace Package {
+
+PackageInfoCallbackData::PackageInfoCallbackData(JSContextRef globalCtx):
+    CallbackUserData(globalCtx)
+{
+    m_exceptionCode = WrtDeviceApis::Commons::ExceptionCodes::None;
+}
+
+PackageInfoCallbackData::~PackageInfoCallbackData()
+{
+
+}
+
+vector<PackageInformation> PackageInfoCallbackData::getPackageInfoList()
+{
+    return m_pkgInfos;
+}
+
+
+void PackageInfoCallbackData::addPackageInfo(PackageInformation pkgInfo)
+{
+    m_pkgInfos.push_back(pkgInfo);
+}
+
+
+void PackageInfoCallbackData::setExceptionCode(ExceptionCodes::Enumeration exceptionCode)
+{
+    m_exceptionCode = exceptionCode;
+}
+
+ExceptionCodes::Enumeration PackageInfoCallbackData::getExceptionCode() const
+{
+    return m_exceptionCode;
+}
+
+PackageInfoEventCallback::PackageInfoEventCallback(CallbackUserData* oninstalled, CallbackUserData* onupdated, CallbackUserData* onuninstalled)
+{
+    m_oninstalled = oninstalled;
+    m_onupdated = onupdated;
+    m_onuninstalled = onuninstalled;
+    m_handle_p = NULL;
+}
+
+PackageInfoEventCallback::~PackageInfoEventCallback()
+{
+    if (m_oninstalled)
+        delete m_oninstalled;
+
+    if (m_onupdated)
+        delete m_onupdated;
+
+    if (m_onuninstalled)
+        delete m_onuninstalled;
+}
+
+CallbackUserData* PackageInfoEventCallback::getOnInstalled()
+{
+    return m_oninstalled;
+}
+
+CallbackUserData* PackageInfoEventCallback::getOnUpdated()
+{
+    return m_onupdated;
+}
+
+CallbackUserData* PackageInfoEventCallback::getOnUninstalled()
+{
+    return m_onuninstalled;
+}
+
+pkgmgr_client** PackageInfoEventCallback::getEventHandler()
+{
+    return m_handle_p;
+}
+
+void PackageInfoEventCallback::setEventHandler(pkgmgr_client **handler)
+{
+    m_handle_p = handler;
+}
+
+PackageInstallEventCallback::PackageInstallEventCallback(JSContextRef globalCtx, CallbackUserData* onprogress, CallbackUserData* oncomplete, CallbackUserData* onerror)
+{
+    m_context = globalCtx;
+    m_onprogress = onprogress;
+    m_oncomplete = oncomplete;
+    m_onerror = onerror;
+
+    m_request_handle = NULL;
+}
+
+PackageInstallEventCallback::~PackageInstallEventCallback()
+{
+    if (m_request_handle != NULL) {
+        //package_manager_request_destroy(m_request_handle);
+        package_manager_client_destroy(m_request_handle);
+    }
+
+    if (m_onprogress)
+        delete m_onprogress;
+
+    if (m_oncomplete)
+        delete m_oncomplete;
+
+    if (m_onerror)
+        delete m_onerror;
+}
+
+CallbackUserData* PackageInstallEventCallback::getOnProgress()
+{
+    return m_onprogress;
+}
+
+CallbackUserData* PackageInstallEventCallback::getOnComplete()
+{
+    return m_oncomplete;
+}
+
+CallbackUserData* PackageInstallEventCallback::getOnError()
+{
+    return m_onerror;
+}
+
+JSContextRef PackageInstallEventCallback::getContext()
+{
+    return m_context;
+}
+
+void PackageInstallEventCallback::setHandle(package_manager_request_h handle)
+{
+    m_request_handle = handle;
+}
+
+package_manager_request_h PackageInstallEventCallback::getHandle()
+{
+    return m_request_handle;
+}
+
+static int get_current_pkg_id(char** pkg_id)
+{
+    app_info_h handle;
+
+    char *app_id = NULL;
+    int pid = getpid();
+    int ret = app_manager_get_app_id(pid, &app_id);
+    if (ret != APP_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getAppManagerErrorMessage(ret).c_str());
+        return ret;
+    }
+
+    ret = app_info_create(app_id, &handle);
+    free(app_id);
+    if (ret != APP_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getAppManagerErrorMessage(ret).c_str());
+        return ret;
+    }
+
+    ret = app_info_get_package(handle, pkg_id);
+    if ((ret != APP_MANAGER_ERROR_NONE) || (*pkg_id == NULL)) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getAppManagerErrorMessage(ret).c_str());
+        app_info_destroy(handle);
+        return ret;
+    }
+
+    ret = app_info_destroy(handle);
+    if (ret != APP_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getAppManagerErrorMessage(ret).c_str());
+        return ret;
+    }
+
+    return ret;
+}
+
+static bool app_callback(package_info_app_component_type_e comp_type, const char *app_id, void *user_data)
+{
+    PackageInformation* pkgInfo = (PackageInformation*)user_data;
+    pkgInfo->m_appIds.push_back(app_id);
+    return true;
+}
+
+static PackageInformation* create_pkg_info(pkgmgrinfo_pkginfo_h handle)
+{
+    PackageInformation *pkgInfo = new PackageInformation();
+
+    char* id = NULL;
+    char* name = NULL;
+    char* iconPath = NULL;
+    char* version = NULL;
+    int lastModified = 0;
+    char* type = NULL;
+    char* author = NULL;
+    char* description = NULL;
+    vector<string> appIds;
+    int ret = 0;
+
+    ret = pkgmgrinfo_pkginfo_get_pkgid(handle, &id);
+    if ((ret != PMINFO_R_OK) || (id == NULL)) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+        delete pkgInfo;
+        return NULL;
+    } else {
+        pkgInfo->m_id = id;
+    }
+
+    ret = pkgmgrinfo_pkginfo_get_label(handle, &name);
+    if ((ret != PMINFO_R_OK) || (name == NULL)) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+    } else {
+        pkgInfo->m_name = name;
+    }
+
+    ret = pkgmgrinfo_pkginfo_get_icon(handle, &iconPath);
+    if ((ret != PMINFO_R_OK) || (iconPath == NULL)) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+    } else {
+        pkgInfo->m_iconPath = iconPath;
+    }
+
+    ret = pkgmgrinfo_pkginfo_get_version(handle, &version);
+    if ((ret != PMINFO_R_OK) || (version == NULL)) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+    } else {
+        pkgInfo->m_version = version;
+    }
+
+    ret = pkgmgrinfo_pkginfo_get_installed_time(handle, &lastModified);
+    if (ret != PMINFO_R_OK) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+    } else {
+        pkgInfo->m_lastModified = lastModified;
+    }
+
+    ret = pkgmgrinfo_pkginfo_get_type(handle, &type);
+    if ((ret != PMINFO_R_OK) || (type == NULL)) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+    } else {
+        pkgInfo->m_type = type;
+    }
+
+    ret = pkgmgrinfo_pkginfo_get_author_name(handle, &author);
+    if ((ret != PMINFO_R_OK) || (author == NULL)) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+    } else {
+        pkgInfo->m_author = author;
+    }
+
+    ret = pkgmgrinfo_pkginfo_get_description(handle, &description);
+    if ((ret != PMINFO_R_OK) || (description == NULL)) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+    } else {
+        pkgInfo->m_description = description;
+    }
+
+    package_info_h package_info;
+
+    ret = package_info_create(id, &package_info);
+    if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPackageManagerErrorMessage(ret).c_str());
+        delete pkgInfo;
+        return NULL;
+    }
+
+    ret = package_info_foreach_app_from_package(package_info, PACKAGE_INFO_ALLAPP, app_callback, (void*)pkgInfo);
+    if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPackageManagerErrorMessage(ret).c_str());
+    }
+
+    ret = package_info_destroy(package_info);
+    if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPackageManagerErrorMessage(ret).c_str());
+    }
+
+    // REMARK: data size and total size is set at first access time
+    // REMARK: do not destroy handle. because handle is comes from outside!!
+    return pkgInfo;
+}
+
+static gboolean getCompleteCB(void *data)
+{
+    PackageInfoCallbackData *callback = (PackageInfoCallbackData *)data;
+    JSContextRef context = callback->getContext();
+
+    if( !GlobalContextManager::getInstance()->isAliveGlobalContext(context)){
+        LOGE("context was closed");
+        return false;
+    }
+
+    if (callback->getExceptionCode() == WrtDeviceApis::Commons::ExceptionCodes::None) {
+        vector<PackageInformation> pkgInfoList = callback->getPackageInfoList();
+
+        JSObjectRef jsResult = JSCreateArrayObject(context, 0, NULL);
+        if (jsResult == NULL) {
+            JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+            callback->callErrorCallback(error);
+            return false;
+        }
+
+        for (size_t i = 0; i < pkgInfoList.size(); ++i) {
+            JSValueRef tmpVal = JSPackageInformation::createJSObject(context, &pkgInfoList[i]);
+            if (!JSSetArrayElement(context, jsResult, i, tmpVal)) {
+                JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+                callback->callErrorCallback(error);
+                return false;
+            }
+        }
+
+        callback->callSuccessCallback(jsResult);
+    } else {
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform exception");
+        callback->callErrorCallback(error);
+    }
+
+    delete callback;
+
+    return false;
+}
+
+static int get_package_list_cb(pkgmgrinfo_pkginfo_h handle, void *user_data)
+{
+    PackageInfoCallbackData *callback = (PackageInfoCallbackData *)user_data;
+    PackageInformation* pkgInfo = create_pkg_info(handle);
+    if (pkgInfo != NULL) {
+        callback->addPackageInfo(*pkgInfo);
+        delete pkgInfo;
+    } else {
+        LOGE("Fail to get pkgInfo");
+    }
+    return 0;
+}
+
+static void getThreadCB(void *data, Ecore_Thread *thread)
+{
+    PackageInfoCallbackData *callback = (PackageInfoCallbackData *)data;
+
+    int ret = pkgmgrinfo_pkginfo_get_list(get_package_list_cb, data);
+    if (ret != PMINFO_R_OK) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+        callback->setExceptionCode(WrtDeviceApis::Commons::ExceptionCodes::PlatformException);
+    }
+
+    // the operation of ecore_thread_run() is not normal. (the finish callback is not called from main thread.)
+    // so, add complete callback to gmainloop explicitly.
+    g_idle_add(getCompleteCB, data);
+}
+
+
+static void package_event_cb(app_info_event_e event_type, const char *package, void *user_data)
+{
+    PackageInfoEventCallback *eventCB = (PackageInfoEventCallback *)user_data;
+
+    switch(event_type) {
+        case APP_INFO_EVENT_INSTALLED: 
+            {
+                pkgmgrinfo_pkginfo_h handle;
+                int ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
+                if (ret != PMINFO_R_OK) {
+                    LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+                    // Do not throw exception. No one can handle exception because this code is called from async callback.
+                    //throw NotFoundException("Can't find given package");
+                    break;
+                }
+
+                PackageInformation* pkgInfo = create_pkg_info(handle);
+                ret = pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+                if (ret != PMINFO_R_OK) {
+                    LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+                }
+
+                if (pkgInfo == NULL) {
+                    LOGE("Fail to get pkg info. skip callback call");
+                } else {
+                    CallbackUserData *callback = eventCB->getOnInstalled();
+                    if (callback) {
+                        CHECK_CURRENT_CONTEXT_ALIVE(callback->getContext());
+                        callback->callSuccessCallback(JSPackageInformation::createJSObject(callback->getContext(), pkgInfo));
+                    }
+                }
+                break;
+            }
+        case APP_INFO_EVENT_UNINSTALLED: 
+            {
+                CallbackUserData *callback = eventCB->getOnUninstalled();
+                if (callback) {
+                    CHECK_CURRENT_CONTEXT_ALIVE(callback->getContext());
+                    Converter converter(callback->getContext());
+                    callback->callSuccessCallback(converter.toJSValueRef(package));
+                }
+                break;
+            }
+        case APP_INFO_EVENT_UPDATED: 
+            {
+                pkgmgrinfo_pkginfo_h handle;
+                int ret = pkgmgrinfo_pkginfo_get_pkginfo(package, &handle);
+                if (ret != PMINFO_R_OK) {
+                    LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+                    // Do not throw exception. No one can handle exception because this code is called from async callback.
+                    //throw NotFoundException("Can't find given package");
+                    break;
+                }
+
+                PackageInformation* pkgInfo = create_pkg_info(handle);
+                pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+                if (ret != PMINFO_R_OK) {
+                    LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+                }
+
+                if (pkgInfo == NULL) {
+                    LOGE("Fail to get pkg info. skip callback call");
+                } else {
+                    CallbackUserData *callback = eventCB->getOnUpdated();
+                    if (callback) {
+                        CHECK_CURRENT_CONTEXT_ALIVE(callback->getContext());
+                        callback->callSuccessCallback(JSPackageInformation::createJSObject(callback->getContext(), pkgInfo));
+                    }
+                }
+                break;
+            }
+        default:
+            LOGE("Fail!! Unknown event type is entered : %d", event_type);
+            break;
+    }
+
+
+}
+
+static int app_list_changed_cb_broker(int id, const char *type, const char *package, const char *key, const char *val, const void *msg, void *data)
+{
+    static app_info_event_e event_type;
+
+    if (!strcasecmp(key, "start"))
+    {
+        LOGD("start ");
+        if (!strcasecmp(val, "install"))
+        {
+            event_type = APP_INFO_EVENT_INSTALLED;
+        }
+        else if (!strcasecmp(val, "uninstall"))
+        {
+            event_type = APP_INFO_EVENT_UNINSTALLED;
+        }
+        else if (!strcasecmp(val, "update"))
+        {
+            event_type = APP_INFO_EVENT_UPDATED;
+        }
+    }
+    else if (!strcasecmp(key, "end") && !strcasecmp(val, "ok"))
+    {
+        LOGD("end ");
+        if (event_type >= 0)
+        {
+            package_event_cb(event_type, package, data);
+
+            // Check whether handler is freed in the callback function or not.
+            // if freed, return error code to avoid iteration of callback function. (core platform side)
+            PackageInfoEventCallback * callback = (PackageInfoEventCallback *)data;
+            pkgmgr_client ** handler_p = callback->getEventHandler();
+            if (*handler_p == NULL) {
+                LOGE("handler is NULL");
+                return -1;
+            }
+            LOGD("handler is not NULL");
+        }
+    }
+
+    return 0;
+}
+
+
+void install_request_cb(int id, const char *type, const char *package,
+        package_manager_event_type_e event_type,
+        package_manager_event_state_e event_state,
+        int progress,
+        package_manager_error_e error,
+        void *user_data)
+{
+    PackageInstallEventCallback *callback = (PackageInstallEventCallback *)user_data;
+    JSContextRef context = callback->getContext();;
+
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+
+    switch (event_state) {
+        case PACKAGE_MANAGER_EVENT_STATE_COMPLETED: 
+            {
+                if (callback->getOnComplete()) {
+                    Converter converter(context);
+                    callback->getOnComplete()->callSuccessCallback(converter.toJSValueRef(package));
+                }
+
+                LOGD("destroy client handle");
+                // this api is not supported from platform.
+                //package_manager_request_destroy(callback->getHandle());
+                package_manager_client_destroy(callback->getHandle());
+                callback->setHandle(NULL);
+
+                //clean-up callback object
+                delete callback;
+
+                break;
+            }
+        case PACKAGE_MANAGER_EVENT_STATE_FAILED: 
+            {
+                JSValueRef jsError = NULL;
+                if (error == PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE) {
+                    jsError = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::NOT_FOUND_ERROR,"given package is not found");
+                } else {
+                    jsError = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::UNKNOWN_ERROR,"platform exception");
+                }
+
+                if (callback->getOnError()) {
+                    callback->getOnError()->callSuccessCallback(jsError);
+                }
+
+                LOGD("destroy client handle");
+                // this api is not supported from platform.
+                //package_manager_request_destroy(callback->getHandle());
+                package_manager_client_destroy(callback->getHandle());
+                callback->setHandle(NULL);
+
+                //clean-up callback object
+                delete callback;
+
+                break;
+            }
+        case PACKAGE_MANAGER_EVENT_STATE_STARTED:
+        case PACKAGE_MANAGER_EVENT_STATE_PROCESSING: 
+            {
+                if (callback->getOnProgress() && package && package[0]!='\0') {
+                    Converter converter(context);
+                    JSValueRef args[2] = {converter.toJSValueRef(package), converter.toJSValueRef(progress)};
+                    callback->getOnProgress()->callSuccessCallback(2, args);
+                }
+                break;
+            }
+        default:
+            JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(context, JSWebAPIErrorFactory::UNKNOWN_ERROR,"platform exception");
+            if (callback->getOnError()) {
+                callback->getOnError()->callSuccessCallback(error);
+            }
+            LOGD("destroy client handle");
+            // this api is not supported from platform.
+            //package_manager_request_destroy(callback->getHandle());
+            package_manager_client_destroy(callback->getHandle());
+            callback->setHandle(NULL);
+
+            //clean-up callback object
+            delete callback;
+
+            break;
+    }
+
+}
+
+static string ltrim(const string s)
+{
+    string str = s;
+    string::iterator i;
+    for (i = str.begin(); i != str.end(); i++) {
+        if (!isspace(*i)) {
+            break;
+        }
+    }
+    if (i == str.end()) {
+        str.clear();
+    } else {
+        str.erase(str.begin(), i);
+    }
+    return str;
+}
+
+
+static string convertUriToPath(const string str)
+{
+    string result;
+    string schema ("file://");
+    string _str = ltrim(str);
+
+    string _schema = _str.substr(0,schema.size());
+    if(_schema == schema) {
+        result = _str.substr(schema.size());
+    } else {
+        result = _str;
+    }
+    return result;
+}
+
+
+void PackageManager::install(string pkgPath, PackageInstallEventCallback* callback)
+{
+    int ret = 0;
+    int id = 0;
+    package_manager_request_h request_h;
+    JSContextRef globalCtx = callback->getContext();
+    CallbackUserData* errCallback = callback->getOnError();
+
+    ret = package_manager_request_create(&request_h);
+    if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPackageManagerErrorMessage(ret).c_str());
+        if (errCallback) {
+            JSValueRef error =
+                JSWebAPIErrorFactory::makeErrorObject(globalCtx, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Platform Error");
+            errCallback->callSuccessCallback(error);
+        }
+        delete callback;
+        return;
+    }
+
+    ret = package_manager_request_install(request_h, convertUriToPath(pkgPath).c_str(), &id);
+    if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPackageManagerErrorMessage(ret).c_str());
+        if (errCallback) {
+            JSValueRef error =
+                JSWebAPIErrorFactory::makeErrorObject(globalCtx, JSWebAPIErrorFactory::NOT_FOUND_ERROR, "Not proper file");
+            errCallback->callSuccessCallback(error);
+        }
+        delete callback;
+        return;
+    }
+
+    callback->setHandle(request_h);
+
+    ret = package_manager_request_set_event_cb(request_h, install_request_cb, callback);
+    if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPackageManagerErrorMessage(ret).c_str());
+        if (errCallback) {
+            JSValueRef error =
+                JSWebAPIErrorFactory::makeErrorObject(globalCtx, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Platform Error");
+            errCallback->callSuccessCallback(error);
+        }
+        delete callback;
+        return;
+    }
+}
+
+void PackageManager::uninstall(string pkgPath, PackageInstallEventCallback* callback)
+{
+    int ret = 0;
+    int id = 0;
+    package_manager_request_h request_h;
+    JSContextRef globalCtx = callback->getContext();
+    CallbackUserData* errCallback = callback->getOnError();
+
+    ret = package_manager_request_create(&request_h);
+    if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPackageManagerErrorMessage(ret).c_str());
+        if (errCallback) {
+            JSValueRef error =
+                JSWebAPIErrorFactory::makeErrorObject(globalCtx, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Platform Error");
+            errCallback->callSuccessCallback(error);
+        }
+        //clean-up callback object
+        delete callback;
+        return;
+    }
+
+    ret = package_manager_request_uninstall(request_h, pkgPath.c_str(), &id);
+    if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPackageManagerErrorMessage(ret).c_str());
+        if (errCallback) {
+            JSValueRef error =
+                JSWebAPIErrorFactory::makeErrorObject(globalCtx, JSWebAPIErrorFactory::NOT_FOUND_ERROR, "Not proper file");
+            errCallback->callSuccessCallback(error);
+        }
+        //clean-up callback object
+        delete callback;
+        return;
+    }
+
+    callback->setHandle(request_h);
+
+    ret = package_manager_request_set_event_cb(request_h, install_request_cb, callback);
+    if (ret != PACKAGE_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPackageManagerErrorMessage(ret).c_str());
+        if (errCallback) {
+            JSValueRef error =
+                JSWebAPIErrorFactory::makeErrorObject(globalCtx, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Platform Error");
+            errCallback->callSuccessCallback(error);
+        }
+        //clean-up callback object
+        delete callback;
+        return;
+    }
+}
+
+
+PackageInformation* PackageManager::getPackageInfo(string pkgId)
+{
+    if (pkgId.empty() || !pkgId.compare("null")) {
+        char *pkg_id = NULL;
+
+        TIME_TRACER_ITEM_BEGIN("(getPackageInfo) get_current_pkg_id", 0);
+        int ret = get_current_pkg_id(&pkg_id);
+        TIME_TRACER_ITEM_END("(getPackageInfo) get_current_pkg_id", 0);
+        if((ret != APP_MANAGER_ERROR_NONE) || (pkg_id == NULL))    {
+            LOGE("ret : %d , %s", ret, PackageUtil::getAppManagerErrorMessage(ret).c_str());
+            PackageUtil::throwAppManagerException(ret, "getPackageInfo");
+        }
+        pkgId = pkg_id;
+        free(pkg_id);
+    }
+
+    pkgmgrinfo_pkginfo_h handle;
+    TIME_TRACER_ITEM_BEGIN("(getPackageInfo) pkgmgrinfo_pkginfo_get_pkginfo", 0);
+    int ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgId.c_str(), &handle);
+    TIME_TRACER_ITEM_END("(getPackageInfo) pkgmgrinfo_pkginfo_get_pkginfo", 0);
+    if (ret != PMINFO_R_OK) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+        throw NotFoundException("Can't find given package");
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(getPackageInfo) create_pkg_info", 0);
+    PackageInformation* pkgInfo = create_pkg_info(handle);
+    TIME_TRACER_ITEM_END("(getPackageInfo) create_pkg_info", 0);
+    pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+    if (ret != PMINFO_R_OK) {
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+    }
+
+    if (pkgInfo == NULL) {
+        LOGE("Can't get pkg info from given package");
+        throw UnknownException("Can't get pkg info from given package");
+    }
+
+    return pkgInfo;
+}
+
+
+void PackageManager::getPackagesInfo(PackageInfoCallbackData *user_data)
+{
+    // getting info of all package from other thread. the result callback will be called on main thread
+    ecore_thread_run(getThreadCB, NULL, NULL, user_data);
+}
+
+
+void PackageManager::setPackageInfoEventListener(PackageInfoEventCallback * eventCB)
+{
+    if (m_manager_handle == NULL) {
+        TIME_TRACER_ITEM_BEGIN("(setPackageInfoEventListener) pkgmgr_client_new", 0);
+        m_manager_handle = pkgmgr_client_new(PC_LISTENING);
+        TIME_TRACER_ITEM_END("(setPackageInfoEventListener) pkgmgr_client_new", 0);
+        if (m_manager_handle == NULL) {
+            LOGE("Fail to create package manager handle");
+            throw UnknownException("Fail to create package manager handle");
+        }
+    }
+
+    eventCB->setEventHandler(&m_manager_handle);
+
+    TIME_TRACER_ITEM_BEGIN("(setPackageInfoEventListener) pkgmgr_client_listen_status", 0);
+    int ret = pkgmgr_client_listen_status(m_manager_handle, app_list_changed_cb_broker, eventCB);
+    TIME_TRACER_ITEM_END("(setPackageInfoEventListener) pkgmgr_client_listen_status", 0);
+    if(ret < 0) {
+        LOGE("Fail to register listener : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+        throw UnknownException("Fail to register listener");
+    }
+}
+
+void PackageManager::unsetPackageInfoEventListener()
+{
+    if (m_manager_handle == NULL) {
+        LOGE("no package manager handle registered");
+        return;
+    }
+
+    TIME_TRACER_ITEM_BEGIN("(unsetPackageInfoEventListener) pkgmgr_client_free", 0);
+    int ret = pkgmgr_client_free(m_manager_handle);
+    if(ret != PMINFO_R_OK){
+        LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+    }
+    TIME_TRACER_ITEM_END("(unsetPackageInfoEventListener) pkgmgr_client_free", 0);
+    m_manager_handle = NULL;
+}
+
+PackageManager* PackageManager::getInstance()
+{
+    static PackageManager instance;
+    return &instance;
+}
+
+PackageManager::PackageManager()
+{
+}
+
+PackageManager::~PackageManager()
+{
+    if (m_manager_handle != NULL) {
+        int ret = pkgmgr_client_free(m_manager_handle);
+        if(ret != PMINFO_R_OK){
+            LOGE("ret : %d , %s", ret, PackageUtil::getPkginfoErrorMessage(ret).c_str());
+        }
+
+        m_manager_handle = NULL;
+    }
+
+}
+
+}
+}
diff --git a/src/Package/PackageManager.h b/src/Package/PackageManager.h
new file mode 100644 (file)
index 0000000..e4f33bb
--- /dev/null
@@ -0,0 +1,132 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _TIZEN_PACKAGE_MANAGER_H_
+#define _TIZEN_PACKAGE_MANAGER_H_
+
+#include <string>
+#include <list>
+#include <CallbackUserData.h>
+#include <CommonsJavaScript/Converter.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <Commons/Exception.h>
+
+#include <package_manager.h>
+#include <package-manager.h>
+
+#include "PackageInformation.h"
+
+namespace DeviceAPI {
+namespace Package {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+using namespace std;
+
+class PackageInfoCallbackData : public CallbackUserData
+{
+public:
+    PackageInfoCallbackData(JSContextRef globalCtx);
+    ~PackageInfoCallbackData();
+
+    vector<PackageInformation> getPackageInfoList();
+    void addPackageInfo(PackageInformation pkgInfo);
+
+    void setExceptionCode(ExceptionCodes::Enumeration exceptionCode);
+    ExceptionCodes::Enumeration getExceptionCode() const;
+
+public:
+    pkgmgr_client *pc;
+
+private:
+    vector<PackageInformation> m_pkgInfos;
+    ExceptionCodes::Enumeration m_exceptionCode;
+};
+
+
+class PackageInfoEventCallback
+{
+public:
+    PackageInfoEventCallback(CallbackUserData* oninstalled, CallbackUserData* onupdated, CallbackUserData* onuninstalled);
+    ~PackageInfoEventCallback();
+    CallbackUserData* getOnInstalled();
+    CallbackUserData* getOnUpdated();
+    CallbackUserData* getOnUninstalled();
+    pkgmgr_client ** getEventHandler();
+    void setEventHandler(pkgmgr_client **handle_p);
+
+private:
+    CallbackUserData* m_oninstalled;
+    CallbackUserData* m_onupdated;
+    CallbackUserData* m_onuninstalled;
+    pkgmgr_client **m_handle_p;
+};
+
+class PackageInstallEventCallback
+{
+public:
+    PackageInstallEventCallback(JSContextRef globalCtx, CallbackUserData* onprogress, CallbackUserData* oncomplete, CallbackUserData* onerror);
+    ~PackageInstallEventCallback();
+    CallbackUserData* getOnProgress();
+    CallbackUserData* getOnComplete();
+    CallbackUserData* getOnError();
+    JSContextRef getContext();
+    void setHandle(package_manager_request_h handle);
+    package_manager_request_h getHandle();
+
+private:
+    CallbackUserData* m_onprogress;
+    CallbackUserData* m_oncomplete;
+    CallbackUserData* m_onerror;
+    package_manager_request_h m_request_handle;
+    JSContextRef m_context;
+};
+
+
+class PackageManager
+{
+public:
+    enum InstalledStorageType
+    {
+        INTERNAL,
+        EXTERNAL
+    };
+
+    void install(string pkgPath, PackageInstallEventCallback* callback);
+    void uninstall(string pkgPath, PackageInstallEventCallback* callback);
+    void move(string pkgPath, string type, PackageInstallEventCallback* callback);
+
+    bool isInstalled(string pkgId);
+    PackageInformation* getPackageInfo(string pkgId);
+    void getPackagesInfo(PackageInfoCallbackData *user_data);
+    string getPackageIdFromAppId(string appId);
+    void setPackageInfoEventListener(PackageInfoEventCallback * eventCB);
+    void unsetPackageInfoEventListener();
+
+    static PackageManager* getInstance();
+
+private:
+    PackageManager();
+    ~PackageManager();
+    pkgmgr_client *m_manager_handle;
+    string m_curr_app_id;
+
+};
+
+}    // Package
+}   // DeviceAPI
+#endif
diff --git a/src/Package/PackageUtil.cpp b/src/Package/PackageUtil.cpp
new file mode 100755 (executable)
index 0000000..d2b47fe
--- /dev/null
@@ -0,0 +1,124 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <sstream>
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "PackageUtil.h"
+
+namespace DeviceAPI {
+namespace Package {
+
+using namespace DeviceAPI::Common;
+
+void PackageUtil::throwPackageManagerException(const int errorCode,
+                                        const std::string &hint)
+{
+    std::stringstream ss;
+    ss << hint << " : " << getPackageManagerErrorMessage(errorCode);
+    LOGE("%s", ss.str().c_str());
+
+    switch(errorCode) {
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+void PackageUtil::throwAppManagerException(const int errorCode,
+                                        const std::string &hint)
+{
+    std::stringstream ss;
+    ss << hint << " : " << getAppManagerErrorMessage(errorCode);
+    LOGE("%s", ss.str().c_str());
+
+    switch(errorCode) {
+        case APP_MANAGER_ERROR_NO_SUCH_APP:
+            throw NotFoundException(ss.str().c_str());
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+std::string PackageUtil::getPackageManagerErrorMessage(const int errorCode)
+{
+    LOGE("Error : %d", errorCode);
+
+    switch(errorCode) {
+        case PACKAGE_MANAGER_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case PACKAGE_MANAGER_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case PACKAGE_MANAGER_ERROR_IO_ERROR:
+            return "IO error";
+        case PACKAGE_MANAGER_ERROR_NO_SUCH_PACKAGE:
+            return "Not found package";
+        case PACKAGE_MANAGER_ERROR_SYSTEM_ERROR:
+            return "System error";
+        case PACKAGE_MANAGER_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        default:
+            return "Unknown Error";
+    }
+}
+
+std::string PackageUtil::getAppManagerErrorMessage(const int errorCode)
+{
+    LOGE("Error : %d", errorCode);
+
+    switch(errorCode) {
+        case APP_MANAGER_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case APP_MANAGER_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case APP_MANAGER_ERROR_IO_ERROR:
+            return "IO error";
+        case APP_MANAGER_ERROR_NO_SUCH_APP:
+            return "Not found application";
+        case APP_MANAGER_ERROR_DB_FAILED:
+            return "Database failed";
+        case APP_MANAGER_ERROR_INVALID_PACKAGE:
+            return "Invalid package";
+        case APP_MANAGER_ERROR_APP_NO_RUNNING:
+            return "App no running";
+        case APP_MANAGER_ERROR_REQUEST_FAILED:
+            return "Request failed";
+        case APP_MANAGER_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        default:
+            return "Unknown Error";
+    }
+}
+
+std::string PackageUtil::getPkginfoErrorMessage(const int errorCode)
+{
+    LOGE("Error : %d", errorCode);
+
+    switch(errorCode) {
+        case PMINFO_R_ERROR:
+            return "pkginfo error";
+        case PMINFO_R_EINVAL:
+            return "Invalid argument";
+        default:
+            return "Unknown Error";
+    }
+}
+
+
+
+} // Package
+} // DeviceAPI
diff --git a/src/Package/PackageUtil.h b/src/Package/PackageUtil.h
new file mode 100755 (executable)
index 0000000..b5f2cbb
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_PACKAGE_UTIL_H_
+#define __TIZEN_PACKAGE_UTIL_H_
+
+#include <string>
+#include <app_manager.h>
+#include <package_manager.h>
+#include <pkgmgr-info.h>
+
+namespace DeviceAPI {
+namespace Package {
+
+class PackageUtil {
+public:
+    static void throwPackageManagerException(const int errorCode, const std::string &hint);
+    static void throwAppManagerException(const int errorCode, const std::string &hint);
+    static std::string getPackageManagerErrorMessage(const int errorCode);
+    static std::string getAppManagerErrorMessage(const int errorCode);
+    static std::string getPkginfoErrorMessage(const int errorCode);
+};
+
+} // Package
+} // DeviceAPI
+
+#endif // __TIZEN_SENSOR_UTIL_H_
diff --git a/src/Package/config.xml b/src/Package/config.xml
new file mode 100755 (executable)
index 0000000..3b0a98e
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-package.so</library-name>
+    <feature-install-uri>package.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/packagemanager.install</name>
+        <device-capability>packagemanager.install</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/package.info</name>
+        <device-capability>package.info</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/Package/plugin_config.cpp b/src/Package/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..d1dab3f
--- /dev/null
@@ -0,0 +1,149 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <iostream>
+#include <Commons/Exception.h>
+#include <dpl/exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define PACKAGE_FEATURE_API_INSTALL        "http://tizen.org/privilege/packagemanager.install"
+#define PACKAGE_FEATURE_API_INFO        "http://tizen.org/privilege/package.info"
+
+#define PACKAGE_DEVICE_CAP_INSTALL        "packagemanager.install"
+#define PACKAGE_DEVICE_CAP_INFO            "package.info"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Package {
+
+static FunctionMapping createPackageFunctions();
+
+static FunctionMapping PackageFunctions =
+    createPackageFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(Package, PackageFunctions);
+
+#pragma GCC visibility pop
+
+static FunctionMapping createPackageFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_PACKAGE_INSTALL, PACKAGE_DEVICE_CAP_INSTALL);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_PACKAGE_INFO, PACKAGE_DEVICE_CAP_INFO);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_PACKAGE_INSTALL);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_PACKAGE_INFO);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_PACKAGE_INSTALL, DEVICE_CAP_PACKAGE_INSTALL);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_PACKAGE_INFO, DEVICE_CAP_PACKAGE_INFO);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_PACKAGE_INSTALL, PACKAGE_FEATURE_API_INSTALL);
+    ACE_CREATE_FEATURE(FEATURE_PACKAGE_INFO, PACKAGE_FEATURE_API_INFO);
+
+    ACE_CREATE_FEATURE_LIST(PACKAGE_FEATURES_PACKAGE_INSTALL);
+    ACE_ADD_API_FEATURE(PACKAGE_FEATURES_PACKAGE_INSTALL, FEATURE_PACKAGE_INSTALL);
+
+    ACE_CREATE_FEATURE_LIST(PACKAGE_FEATURES_PACKAGE_INFO);
+    ACE_ADD_API_FEATURE(PACKAGE_FEATURES_PACKAGE_INFO, FEATURE_PACKAGE_INFO);
+
+    /**
+     * Functions
+     */
+    FunctionMapping packageMapping;
+
+    // install
+    AceFunction installFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_INSTALL,
+            PACKAGE_FUNCTION_API_INSTALL,
+            PACKAGE_FEATURES_PACKAGE_INSTALL,
+            DEVICE_LIST_PACKAGE_INSTALL);
+
+    packageMapping.insert(std::make_pair(
+                PACKAGE_FUNCTION_API_INSTALL,
+                installFunc));
+
+    // uninstall
+    AceFunction uninstallFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UNINSTALL,
+            PACKAGE_FUNCTION_API_UNINSTALL,
+            PACKAGE_FEATURES_PACKAGE_INSTALL,
+            DEVICE_LIST_PACKAGE_INSTALL);
+
+    packageMapping.insert(std::make_pair(
+                PACKAGE_FUNCTION_API_UNINSTALL,
+                uninstallFunc));
+
+    // getPackageInfo
+    AceFunction getPackageInfoFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_PACKAGE_INFO,
+            PACKAGE_FUNCTION_API_GET_PACKAGE_INFO,
+            PACKAGE_FEATURES_PACKAGE_INFO,
+            DEVICE_LIST_PACKAGE_INFO);
+
+    packageMapping.insert(std::make_pair(
+                PACKAGE_FUNCTION_API_GET_PACKAGE_INFO,
+                getPackageInfoFunc));
+
+    // getPackagesInfo
+    AceFunction getPackagesInfoFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_PACKAGES_INFO,
+            PACKAGE_FUNCTION_API_GET_PACKAGES_INFO,
+            PACKAGE_FEATURES_PACKAGE_INFO,
+            DEVICE_LIST_PACKAGE_INFO);
+
+    packageMapping.insert(std::make_pair(
+                PACKAGE_FUNCTION_API_GET_PACKAGES_INFO,
+                getPackagesInfoFunc));
+
+    // setPackageInfoEventListener
+    AceFunction setPackageInfoEventListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_PACKAGE_INFO_EVENT_LISTENER,
+            PACKAGE_FUNCTION_API_SET_PACKAGE_INFO_EVENT_LISTENER,
+            PACKAGE_FEATURES_PACKAGE_INFO,
+            DEVICE_LIST_PACKAGE_INFO);
+
+    packageMapping.insert(std::make_pair(
+                PACKAGE_FUNCTION_API_SET_PACKAGE_INFO_EVENT_LISTENER,
+                setPackageInfoEventListenerFunc));
+
+    // unsetPackageInfoEventListener
+    AceFunction unsetPackageInfoEventListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UNSET_PACKAGE_INFO_EVENT_LISTENER,
+            PACKAGE_FUNCTION_API_UNSET_PACKAGE_INFO_EVENT_LISTENER,
+            PACKAGE_FEATURES_PACKAGE_INFO,
+            DEVICE_LIST_PACKAGE_INFO);
+
+    packageMapping.insert(std::make_pair(
+                PACKAGE_FUNCTION_API_UNSET_PACKAGE_INFO_EVENT_LISTENER,
+                unsetPackageInfoEventListenerFunc));
+
+    return packageMapping;
+}
+
+}
+}
diff --git a/src/Package/plugin_config.h b/src/Package/plugin_config.h
new file mode 100755 (executable)
index 0000000..91d25a3
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _PACKAGE_PLUGIN_CONFIG_H_
+#define _PACKAGE_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+// feature : install
+#define PACKAGE_FUNCTION_API_INSTALL                    "install"
+#define PACKAGE_FUNCTION_API_UNINSTALL                    "uninstall"
+
+// feature : read
+#define PACKAGE_FUNCTION_API_GET_PACKAGES_INFO                    "getPackagesInfo"
+#define PACKAGE_FUNCTION_API_GET_PACKAGE_INFO                        "getPackageInfo"
+#define PACKAGE_FUNCTION_API_SET_PACKAGE_INFO_EVENT_LISTENER        "setPackageInfoEventListener"
+#define PACKAGE_FUNCTION_API_UNSET_PACKAGE_INFO_EVENT_LISTENER    "unsetPackageInfoEventListener"
+
+namespace DeviceAPI {
+namespace Package {
+
+DECLARE_FUNCTION_GETTER(Package);
+
+#define PACKAGE_CHECK_ACCESS(functionName)                \
+aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(        \
+        getPackageFunctionData,                                    \
+        functionName)
+
+}
+}
+#endif
+
diff --git a/src/Package/plugin_initializer.cpp b/src/Package/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..a913e77
--- /dev/null
@@ -0,0 +1,85 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <dpl/string.h>
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+#include "JSPackageManager.h"
+#include "PackageManager.h"
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Package {
+
+void on_widget_start_callback(int widgetId) {
+    LOGD("[Tizen2_1\\Package] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    Try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } Catch(WrtDeviceApis::Commons::Exception) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId) {
+    LOGD("[Tizen2_1\\Package] on_widget_stop_callback (%d)", widgetId);
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"Package");
+    TIME_TRACER_RELEASE();
+    Try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } Catch(WrtDeviceApis::Commons::Exception) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Package] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Package] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+    PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+    PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+    PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+    PLUGIN_CLASS_MAP_BEGIN
+    PLUGIN_CLASS_MAP_ADD_CLASS(
+            WRT_JS_EXTENSION_OBJECT_TIZEN,
+            "package",
+            (js_class_template_getter)DeviceAPI::Package::JSPackageManager::getClassRef,
+            NULL)
+
+    PLUGIN_CLASS_MAP_END
+
+} //Package
+} //DeviceAPI
+
diff --git a/src/Power/CMakeLists.txt b/src/Power/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..74a8bb1
--- /dev/null
@@ -0,0 +1,50 @@
+SET(TARGET_NAME ${power_target})
+SET(DESTINATION_NAME ${power_dest})
+SET(TARGET_IMPL_NAME ${power_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_power REQUIRED capi-system-device deviced)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_power_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSPowerManager.cpp
+    PowerManager.cpp
+    PowerPlatformProxy.cpp
+    PowerUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${platform_pkgs_power_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/power
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
+
diff --git a/src/Power/JSPowerManager.cpp b/src/Power/JSPowerManager.cpp
new file mode 100755 (executable)
index 0000000..1d953e7
--- /dev/null
@@ -0,0 +1,344 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <TimeTracer.h>
+
+#include "JSPowerManager.h"
+#include "plugin_config_impl.h"
+#include "PowerManager.h"
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+using namespace std;
+
+namespace DeviceAPI {
+namespace Power {
+
+JSClassDefinition JSPowerManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "PowerManager",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function,
+    initialize,
+    finalize,
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSPowerManager::m_function[] = {
+    { POWER_FUNCTION_API_REQUEST, request, kJSPropertyAttributeNone },
+    { POWER_FUNCTION_API_RELEASE, release, kJSPropertyAttributeNone },
+    { POWER_FUNCTION_API_SET_SCREEN_STATE_CHANGE_LISTENER, setScreenStateChangeListener, kJSPropertyAttributeNone },
+    { POWER_FUNCTION_API_UNSET_SCREEN_STATE_CHANGE_LISTENER, unsetScreenStateChangeListener, kJSPropertyAttributeNone },
+    { POWER_FUNCTION_API_GET_SCREEN_BRIGHTNESS, getScreenBrightness, kJSPropertyAttributeNone },
+    { POWER_FUNCTION_API_SET_SCREEN_BRIGHTNESS, setScreenBrightness, kJSPropertyAttributeNone },
+    { POWER_FUNCTION_API_IS_SCREEN_ON, isScreenOn, kJSPropertyAttributeNone },
+    { POWER_FUNCTION_API_RESTORE_SCREEN_BRIGHTNESS, restoreScreenBrightness, kJSPropertyAttributeNone },
+    { POWER_FUNCTION_API_TURN_SCREEN_ON, turnScreenOn, kJSPropertyAttributeNone },
+    { POWER_FUNCTION_API_TURN_SCREEN_OFF, turnScreenOff, kJSPropertyAttributeNone },
+
+    { 0, 0, 0 }
+};
+
+JSClassRef JSPowerManager::m_jsClassRef = JSClassCreate(JSPowerManager::getClassInfo());
+
+void JSPowerManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+    PowerManagerPriv *priv = new PowerManagerPriv(GlobalContextManager::getInstance()->getGlobalContext(context));
+    JSObjectSetPrivate(object, static_cast<void*>(priv));
+}
+
+void JSPowerManager::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+    PowerManagerPriv *priv = static_cast<PowerManagerPriv*>(JSObjectGetPrivate(object));
+    if( priv != NULL ){
+        PowerManager::getInstance()->removeScreenStateChangedCallback(priv);
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+const JSClassRef JSPowerManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSPowerManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSPowerManager::request(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    PowerManagerPriv *thisPriv = static_cast<PowerManagerPriv*>(JSObjectGetPrivate(thisObject));
+    if (!thisPriv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
+    }
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIZEN_CHECK_ACCESS(context, exception, thisPriv, POWER_FUNCTION_API_REQUEST);
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        string resource_str = validator.toString(0);
+        string state_str = validator.toString(1);
+        PowerResource resource(resource_str.c_str());
+        PowerState state(state_str.c_str());
+        PowerManager::getInstance()->request( resource , state );
+    }catch(const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPowerManager::release(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        string resource_str = validator.toString(0);
+        PowerResource resource(resource_str.c_str());
+        PowerManager::getInstance()->release( resource );
+
+    }catch(const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPowerManager::setScreenStateChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef func = validator.toFunction(0);
+        PowerManagerPriv *thisPriv = static_cast<PowerManagerPriv*>(JSObjectGetPrivate(thisObject));
+        thisPriv->setSuccessCallback(func);
+        PowerManager::getInstance()->addScreenStateChangedCallback(thisPriv);
+
+    }catch(const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }catch( const std::bad_alloc& oom){
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::UNKNOWN_ERROR, "Out of memory");
+    }
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPowerManager::unsetScreenStateChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    PowerManagerPriv *thisPriv = static_cast<PowerManagerPriv*>(JSObjectGetPrivate(thisObject));
+    PowerManager::getInstance()->removeScreenStateChangedCallback(thisPriv);
+
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPowerManager::getScreenBrightness(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try{
+        double brightness = PowerManager::getInstance()->getScreenBrightness();
+        LOGD("brightness : %d", brightness);
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSUtil::toJSValueRef(context, brightness);
+    }catch(const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSPowerManager::setScreenBrightness(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    PowerManagerPriv *thisPriv = static_cast<PowerManagerPriv*>(JSObjectGetPrivate(thisObject));
+    if (!thisPriv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
+    }
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIZEN_CHECK_ACCESS(context, exception, thisPriv, POWER_FUNCTION_API_SET_SCREEN_BRIGHTNESS);
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        double value = validator.toDouble(0);
+        LOGD(" value = %f", value);
+        PowerManager::getInstance()->setScreenBrightness(value);
+    }catch(const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);
+
+}
+
+JSValueRef JSPowerManager::isScreenOn(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try{
+        bool state = PowerManager::getInstance()->isScreenOn();
+        TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+        return JSUtil::toJSValueRef(context,state);
+    }catch(const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSPowerManager::restoreScreenBrightness(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+
+    try{
+        PowerManager::getInstance()->restoreScreenBrightness();
+    }catch(const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);}
+
+JSValueRef JSPowerManager::turnScreenOn(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    PowerManagerPriv *thisPriv = static_cast<PowerManagerPriv*>(JSObjectGetPrivate(thisObject));
+    if (!thisPriv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
+    }
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIZEN_CHECK_ACCESS(context, exception, thisPriv, POWER_FUNCTION_API_TURN_SCREEN_ON);
+
+    try{
+        PowerManager::getInstance()->setScreenState(true);
+    }catch(const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPowerManager::turnScreenOff(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    PowerManagerPriv *thisPriv = static_cast<PowerManagerPriv*>(JSObjectGetPrivate(thisObject));
+    if (!thisPriv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(context, exception, JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong object");
+    }
+    TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 0);
+    TIZEN_CHECK_ACCESS(context, exception, thisPriv, POWER_FUNCTION_API_TURN_SCREEN_OFF);
+
+    try{
+        PowerManager::getInstance()->setScreenState(false);
+    }catch(const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    TIME_TRACER_ITEM_END(__FUNCTION__, 0);
+    return JSValueMakeUndefined(context);
+}
+
+}
+}
diff --git a/src/Power/JSPowerManager.h b/src/Power/JSPowerManager.h
new file mode 100755 (executable)
index 0000000..64d1292
--- /dev/null
@@ -0,0 +1,181 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _JS_TIZEN_POWER_MANAGER_H_
+#define _JS_TIZEN_POWER_MANAGER_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+#include <Security.h>
+#include <CallbackUserData.h>
+
+namespace DeviceAPI {
+namespace Power {
+
+class PowerManagerPriv : public DeviceAPI::Common::CallbackUserData, public DeviceAPI::Common::SecurityAccessor
+{
+public:
+    PowerManagerPriv(JSContextRef ctx) : DeviceAPI::Common::CallbackUserData(ctx), DeviceAPI::Common::SecurityAccessor() {}
+    virtual ~PowerManagerPriv() {}
+};
+
+class JSPowerManager
+{
+  public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+  private:
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Requests a power resource.
+     */
+    static JSValueRef request(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Releases a previous power request.
+     */
+    static JSValueRef release(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Sets the screen state change listener.
+     */
+    static JSValueRef setScreenStateChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Unsets the screen state change listener.
+     */
+    static JSValueRef unsetScreenStateChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Gets the screen brightness.
+     */
+    static JSValueRef getScreenBrightness(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Sets the screen brightness.
+     */
+    static JSValueRef setScreenBrightness(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Returns true if screen is on.
+     */
+    static JSValueRef isScreenOn(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Restore the screen brightensss to the default setting value.
+     */
+    static JSValueRef restoreScreenBrightness(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Turns the screen on.
+     */
+    static JSValueRef turnScreenOn(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Turns the screen off.
+     */
+    static JSValueRef turnScreenOff(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+}
+}
+
+#endif /* _JS_TIZEN_POWER_MANAGER_H_ */
+
diff --git a/src/Power/PowerManager.cpp b/src/Power/PowerManager.cpp
new file mode 100755 (executable)
index 0000000..55f5f3f
--- /dev/null
@@ -0,0 +1,489 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PowerManager.h"
+#include "PowerPlatformProxy.h"
+#include "PowerUtil.h"
+#include <cstring>
+#include <device/display.h>
+#include <device/power.h>
+#include <device/callback.h>
+#include <device.h>
+#include <algorithm>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <vconf.h>
+#include <Logger.h>
+#include <unistd.h>
+#include <GlobalContextManager.h>
+
+using namespace DeviceAPI::Common;
+using namespace std;
+
+namespace DeviceAPI {
+namespace Power {
+
+PowerResource::PowerResource(const char *resource)
+{
+    if( strcmp(resource,"SCREEN") == 0 )
+        mType = SCREEN;
+    else if( strcmp(resource,"CPU") == 0 )
+        mType = CPU;
+    else
+        throw TypeMismatchException("value is not PowerResource type");
+};
+
+const std::string PowerResource::toString(){
+    static const char *table[] = {"SCREEN", "CPU"};
+    return std::string(table[mType]);
+}
+
+
+PowerState::PowerState(const char *str)
+{
+    static const char *table[] = { "SCREEN_OFF", "SCREEN_DIM", "SCREEN_NORMAL", "SCREEN_BRIGHT", "CPU_AWAKE"};
+    static state state_table[] = { SCREENOFF, SCREENDIM, SCREENNORMAL, SCREENBRIGHT, CPUAWAKE };
+    for(unsigned int i =0; i < sizeof(table)/sizeof(char*) ; i++){
+        if( strcmp(str, table[i]) == 0 ){
+            mState = state_table[i];
+            return;
+        }
+    }
+    throw TypeMismatchException("value is not PowerState type");
+};
+
+PowerState::PowerState(state in):mState(in){
+}
+
+const std::string PowerState::toString(){
+    static const char *table[] = { "SCREEN_OFF", "SCREEN_DIM", "SCREEN_NORMAL", "SCREEN_BRIGHT", "CPU_AWAKE"};
+    return std::string(table[mState]);
+}
+
+
+void PowerManager::onPlatformStateChangedCB(device_callback_e type, void *value, void *user_data){
+    LOGD("enter");
+    PowerManager* object = static_cast<PowerManager*>(user_data);
+    if(object == NULL){
+        LOGE("User data is NULL");
+        return;
+    }
+    if(type != DEVICE_CALLBACK_DISPLAY_STATE){
+        LOGE("type is not DISPLAY_STATE");
+        return;
+    }
+    display_state_e state = static_cast<display_state_e>(reinterpret_cast<int>(value));
+    PowerState current(PowerState::SCREENOFF);
+    switch( state ){
+        case DISPLAY_STATE_NORMAL :
+            {
+                LOGD("state normal");
+                current.mState = object->mBrightStateEnable ? PowerState::SCREENBRIGHT : PowerState::SCREENNORMAL;
+                break;
+            }
+        case DISPLAY_STATE_SCREEN_DIM : 
+            {
+                LOGD("screen dim");
+                current.mState = PowerState::SCREENDIM;
+                break;
+            }
+        case DISPLAY_STATE_SCREEN_OFF :
+            {
+                LOGD("screen off");
+                current.mState = PowerState::SCREENOFF;
+                if (object->mSetCustomBrightness == true) {
+                    object->restoreScreenBrightness();
+                    object->mSetCustomBrightness = false;
+                }
+                break;
+            }
+    }
+    object->broadcastScreenState(current);
+}
+
+
+void PowerManager::request(PowerResource resource, PowerState state){
+    LOGD("enter : request");
+    if( resource == PowerResource::SCREEN && state == PowerState::CPUAWAKE)
+        throw InvalidValuesException("invalid PowerState");
+    if( resource == PowerResource::CPU && state != PowerState::CPUAWAKE)
+        throw InvalidValuesException("invalid PowerState");
+
+    if(mCurrentRequestedState.mState == PowerState::SCREENDIM) {
+        int ret = PowerPlatformProxy::getInstance().deviceUnlockState();
+        if(ret < 0) {
+            LOGE("deviceUnlockState error %d", ret);
+            throw UnknownException("device_power_request_unlock error");
+        }
+    }
+
+    int ret=0;
+    switch( state ){
+        case PowerState::CPUAWAKE :
+            {
+                ret = device_power_request_lock(POWER_LOCK_CPU, 0);
+                if( DEVICE_ERROR_NONE !=ret ){
+                    LOGE("device_power_request_lock error : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+                    PowerUtil::throwPowerException(ret,"request");
+                }
+                break;
+            }
+        case PowerState::SCREENDIM :
+            {
+                ret = PowerPlatformProxy::getInstance().deviceLockState();
+                if(ret < 0) {
+                    LOGE("device_power_request_lock error %d", ret);
+                    throw UnknownException("device_power_request_lock error");
+                }
+
+                break;
+            }
+        case PowerState::SCREENNORMAL :
+            {
+                ret = device_power_request_lock(POWER_LOCK_DISPLAY, 0);
+                if( DEVICE_ERROR_NONE!=ret ){
+                    LOGE("device_power_request_lock error : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+                    PowerUtil::throwPowerException(ret,"request");
+                }
+                break;
+            }
+        case PowerState::SCREENBRIGHT :
+            {
+                int maxBrightness;
+                ret = device_display_get_max_brightness(0, &maxBrightness);
+                if( DEVICE_ERROR_NONE!=ret) {
+                    LOGE("Platform error while getting max brightness: %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+                    PowerUtil::throwPowerException(ret,"request");
+                }
+
+                setPlatformBrightness( maxBrightness );
+
+                LOGI("Succeeded setting the brightness to a max level: %d", maxBrightness);
+                ret = device_display_change_state(DISPLAY_STATE_NORMAL);
+                if( DEVICE_ERROR_NONE!=ret ){
+                    LOGE("device_display_change_state(DISPLAY_STATE_NORMAL) error : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+                    PowerUtil::throwPowerException(ret,"request");
+                }
+                ret = device_power_request_lock(POWER_LOCK_DISPLAY, 0);
+                if( DEVICE_ERROR_NONE!=ret ){
+                    LOGE("device_power_request_lock error : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+                    PowerUtil::throwPowerException(ret,"request");
+                }
+
+                mBrightStateEnable = true;
+                display_state_e platform_state = DISPLAY_STATE_NORMAL;
+                ret = device_display_get_state(&platform_state);
+                if(ret != DEVICE_ERROR_NONE) {
+                    LOGE("device_display_get_state failed : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+                }
+                if( platform_state ==  DISPLAY_STATE_NORMAL)
+                    broadcastScreenState(PowerState::SCREENBRIGHT);
+                break;
+            }
+        case PowerState::SCREENOFF:
+            LOGE("SCREEN_OFF state cannot be requested");
+            throw InvalidValuesException("SCREEN_OFF state cannot be requested");
+
+        default :
+            LOGE("Platform error while locking state");
+            throw UnknownException("Platform error while locking state");
+    }
+    mCurrentRequestedState.mState = state;
+
+}
+
+void PowerManager::release(PowerResource resource){
+    LOGD("enter : release");
+    int ret;
+    if( PowerResource::SCREEN == resource ) {
+        ret = device_power_release_lock(POWER_LOCK_DISPLAY);
+        if( DEVICE_ERROR_NONE!=ret )
+            LOGI("Platform return value from dim unlock: %d", ret);
+
+        if( mBrightStateEnable ){
+            ret = PowerPlatformProxy::getInstance().deviceSetBrightnessFromSettings();
+            if( DEVICE_ERROR_NONE!=ret){
+                LOGE("Platform error while setting restore brightness %d", ret);
+                throw UnknownException("Platform error while setting restore brightness");
+            }
+        }
+
+        mBrightStateEnable = false;
+        display_state_e platform_state = DISPLAY_STATE_NORMAL;
+        if(mCurrentRequestedState.mState == PowerState::SCREENDIM) {
+            ret = PowerPlatformProxy::getInstance().deviceUnlockState();
+        } else {
+            ret = device_display_get_state(&platform_state);
+        }
+        if(ret != DEVICE_ERROR_NONE) {
+            LOGE("device_display_get_state failed : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+        }
+        if( platform_state ==  DISPLAY_STATE_NORMAL)
+            broadcastScreenState(PowerState::SCREENNORMAL);
+
+        mCurrentRequestedState.mState = PowerState::NONE;
+
+    } else if( PowerResource::CPU == resource ) {
+        ret = device_power_release_lock(POWER_LOCK_CPU);
+        if( DEVICE_ERROR_NONE!=ret )
+            LOGE("Platform return value from off unlock : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+    }
+}
+
+double PowerManager::getScreenBrightness(){
+    LOGD("enter : getScreenBrightness");
+    int brightness, maxBrightness, ret;
+    brightness = getPlatformBrightness();
+    LOGI("Brightness value: %d", brightness);
+    ret = device_display_get_max_brightness(0, &maxBrightness);
+    if( ret != 0 ){
+        LOGE("Platform error while getting brightness : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+        PowerUtil::throwPowerException(ret,"getScreenBrightness");
+    }
+    return (double)brightness/(double)maxBrightness;
+}
+
+void PowerManager::setScreenBrightness(double brightness){
+    LOGD("enter : setScreenBrightness %f", brightness);
+    int ret, maxBrightness;
+    if( brightness > 1 || brightness < 0 )
+        throw InvalidValuesException("brightness should be 0 <= brightness <= 1");
+    ret = device_display_get_max_brightness(0, &maxBrightness);
+    if( ret != 0 ){
+        LOGE("Platform error while setting restore brightness : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+        PowerUtil::throwPowerException(ret,"setScreenBrightness");
+    }
+    int nativeBrightness = (int)(brightness*maxBrightness);
+
+    if (nativeBrightness == 0)
+        nativeBrightness = 1;
+
+    setPlatformBrightness(nativeBrightness);
+    LOGD("Set the brightness value: %d", nativeBrightness);
+}
+
+bool PowerManager::isScreenOn(){
+    LOGD("enter : isScreenOn");
+    display_state_e platform_state = DISPLAY_STATE_NORMAL;
+    int ret = device_display_get_state(&platform_state);
+    if(ret != DEVICE_ERROR_NONE) {
+        LOGE("device_display_get_state failed : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+    }
+    if(DISPLAY_STATE_SCREEN_OFF==platform_state)
+        return false;
+    else
+        return true;
+}
+
+void PowerManager::setScreenState(bool onoff){
+    LOGD("enter : setScreenState");
+    int ret = 0;
+    if( onoff )
+        ret = device_display_change_state(DISPLAY_STATE_NORMAL);
+    else
+        ret = device_display_change_state(DISPLAY_STATE_SCREEN_OFF);
+
+    if( ret<0 ){
+        LOGE("Platform error while changing screen state : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+        PowerUtil::throwPowerException(ret,"setScreenState");
+    }
+
+    int timeout=100;
+    while(timeout--){
+        if( isScreenOn() == onoff )
+            break;
+        usleep(100000);
+    }
+
+}
+
+void PowerManager::restoreScreenBrightness(){
+    LOGD("enter : restoreScreenBrightness");
+    int ret;
+    ret = PowerPlatformProxy::getInstance().deviceSetBrightnessFromSettings();
+    if( DEVICE_ERROR_NONE != ret){
+        LOGE("Platform error while restoring brightness %d", ret);
+        throw UnknownException("Platform error while restoring brightness");
+    }
+}
+
+PowerManager* PowerManager::getInstance(){
+    static PowerManager instance;
+    return &instance;
+}
+
+void PowerManager::addScreenStateChangedCallback(Common::CallbackUserData * callback){
+    list<CallbackUserData*>::iterator itr;
+    itr = find(mListener.begin(), mListener.end(), callback);
+    if( itr == mListener.end() ){
+        mListener.push_back(callback);
+        LOGD("add callback");
+    }
+}
+
+void PowerManager::removeScreenStateChangedCallback(Common::CallbackUserData * callback){
+    mListener.remove(callback);
+    LOGD("remove callback");
+}
+
+void PowerManager::setPlatformBrightness(int brightness){
+    LOGD("setPlatformBrightness %d", brightness);
+    if( mCurrentState.mState == PowerState::SCREENDIM ){
+        mCurrentBrightness = brightness;
+        LOGI("Current state is not normal state the value is saved in cache: %d", brightness);
+        mShouldBeReadFromCache = true;
+        return;
+    } else if( mCurrentState.mState == PowerState::SCREENBRIGHT ){
+        mCurrentBrightness = brightness;
+        LOGI("Current state is not normal state the value is saved in cache: %d", brightness);
+        mShouldBeReadFromCache = true;
+        return;
+    }else
+        mShouldBeReadFromCache = false;
+
+    int ret = PowerPlatformProxy::getInstance().deviceSetBrightness(brightness);
+    if( ret != 0){
+        LOGE("Platform error while setting %d brightness: %d", brightness, ret);
+        throw UnknownException("Platform error while setting brightness.");
+    }
+    mSetCustomBrightness = true;
+    mCurrentBrightness = brightness;
+}
+
+int PowerManager::getPlatformBrightness(){
+    LOGD("enter : getPlatformBrightness");
+    int currentPowerState = 1;
+    int brightness = 0;
+    int isCustomMode = 0;
+    int isAutoBrightness = 0;
+    int ret = 0;
+
+    vconf_get_int(VCONFKEY_PM_STATE, &currentPowerState);
+    if( currentPowerState == VCONFKEY_PM_STATE_NORMAL){
+        vconf_get_int(VCONFKEY_PM_CURRENT_BRIGHTNESS, &brightness);
+        LOGD("[PM_STATE_NORMAL] return VCONFKEY_PM_CURRENT_BRIGHTNESS %d", brightness);
+        return brightness;
+    }
+
+    vconf_get_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, &isCustomMode);
+    if( (isCustomMode && mCurrentBrightness != -1) || mShouldBeReadFromCache ){
+        LOGD("return custom brightness %d", mCurrentBrightness);
+        return mCurrentBrightness;
+    }
+
+    vconf_get_int(VCONFKEY_SETAPPL_BRIGHTNESS_AUTOMATIC_INT, &isAutoBrightness);
+    if( isAutoBrightness == 1 ){
+        ret = vconf_get_int(VCONFKEY_SETAPPL_PREFIX"/automatic_brightness_level" /*prevent RSA build error*/, &brightness);
+        if( ret != 0 ) //RSA binary has no AUTOMATIC_BRIGHTNESS
+            vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &brightness);
+    }else{
+        vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &brightness);
+    }
+    LOGD("BRIGHTNESS(%s) %d", isAutoBrightness == 1 ? "auto" : "fix" , brightness);
+
+    return brightness;
+}
+
+
+void PowerManager::restoreSettedBrightness(){
+    LOGD("enter : restoreSettedBrightness");
+    int isCustomMode = 0;
+    vconf_get_int(VCONFKEY_PM_CUSTOM_BRIGHTNESS_STATUS, &isCustomMode);
+    if( isCustomMode || mShouldBeReadFromCache ){
+        if( mCurrentBrightness == -1 ){
+            // brightness was changed in other process
+            restoreScreenBrightness();
+        }else{
+            setPlatformBrightness(mCurrentBrightness);
+        }
+    }
+    mShouldBeReadFromCache = false;
+}
+
+void PowerManager::broadcastScreenState(PowerState current){
+    LOGD("enter : broadcastScreenState");
+    if( mCurrentState == current)
+        return;
+
+    PowerState PreviousState = mCurrentState;
+    mCurrentState = current;
+
+    if( mCurrentState.mState == PowerState::SCREENNORMAL && PreviousState.mState == PowerState::SCREENDIM ){
+        //restore ScreenBrightness
+        try{
+            restoreSettedBrightness();
+        }
+        catch( const BasePlatformException& err){
+            LOGE("Error restore custom brightness %s", err.getMessage().c_str());
+        }
+    }
+    if( mCurrentState.mState == PowerState::SCREENNORMAL && PreviousState.mState == PowerState::SCREENOFF){
+        mShouldBeReadFromCache = false;
+    }
+    list<CallbackUserData*> tmplist(mListener);
+    list<CallbackUserData*>::iterator itr = tmplist.begin();
+
+    while( itr != tmplist.end() ){
+        CallbackUserData *callback = *itr;
+        if( callback != NULL ){
+            JSValueRef previousState = JSUtil::toJSValueRef(callback->getContext(), PreviousState.toString());
+            JSValueRef currentState = JSUtil::toJSValueRef(callback->getContext(), mCurrentState.toString());
+            JSValueRef args[2] = { previousState, currentState };
+            callback->callSuccessCallback(2, args);
+        }
+        ++itr;
+    }
+}
+
+
+PowerManager::PowerManager():mCurrentState(PowerState::SCREENNORMAL),mBrightStateEnable(false),mCurrentBrightness(-1),
+mShouldBeReadFromCache(false),mCurrentRequestedState(PowerState::NONE){
+    LOGD("enter");
+    int ret = 0;
+    display_state_e platform_state = DISPLAY_STATE_NORMAL;
+    ret = device_display_get_state(&platform_state);
+    if(ret != DEVICE_ERROR_NONE) {
+        LOGE("device_display_get_state failed : %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+    }
+    switch( platform_state ){
+        case DISPLAY_STATE_NORMAL :
+            mCurrentState.mState = PowerState::SCREENNORMAL;
+            break;
+        case DISPLAY_STATE_SCREEN_DIM :
+            mCurrentState.mState = PowerState::SCREENDIM;
+            break;
+        case DISPLAY_STATE_SCREEN_OFF :
+            mCurrentState.mState = PowerState::SCREENOFF;
+            break;
+    }
+    ret = device_add_callback(DEVICE_CALLBACK_DISPLAY_STATE, PowerManager::onPlatformStateChangedCB, static_cast<void*>(this));
+    if(ret != DEVICE_ERROR_NONE) {
+        LOGE("device_add_callback failed %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+    }
+}
+PowerManager::~PowerManager(){
+    LOGD("enter");
+    int ret = 0;
+    ret = device_remove_callback(DEVICE_CALLBACK_DISPLAY_STATE, PowerManager::onPlatformStateChangedCB);
+    if(ret != DEVICE_ERROR_NONE) {
+        LOGE("device_remove_callback failed %s", PowerUtil::getPowerErrorMessage(ret).c_str());
+    }
+}
+
+} //Power
+} //DeviceAPI
+
diff --git a/src/Power/PowerManager.h b/src/Power/PowerManager.h
new file mode 100755 (executable)
index 0000000..76e8a7c
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _POWER_MANAGER_H_
+#define _POWER_MANAGER_H_
+
+#include <string>
+#include <list>
+#include <CallbackUserData.h>
+#include <JavaScriptCore/JavaScript.h>
+#include <device/callback.h>
+
+namespace DeviceAPI {
+namespace Power {
+
+class PowerResource{
+public:
+    enum type { SCREEN=0, CPU=1 };
+    PowerResource( const char * str );
+    operator type() const {return mType;}
+    const std::string toString();
+    type mType;
+};
+
+class PowerState{
+public:
+    enum state { SCREENOFF, SCREENDIM, SCREENNORMAL, SCREENBRIGHT, CPUAWAKE, NONE };
+    PowerState( const char * str );
+    PowerState( state in);
+    operator state() const {return mState;}
+    const std::string toString();
+    state mState;
+};
+
+
+
+class PowerManager
+{
+public:
+    void request( PowerResource resource, PowerState state );
+    void release( PowerResource resource );
+    double getScreenBrightness();
+    void setScreenBrightness(double brightness);
+    void restoreScreenBrightness();
+    bool isScreenOn();
+    void setScreenState( bool onoff );
+
+    void addScreenStateChangedCallback(Common::CallbackUserData *callback);
+    void removeScreenStateChangedCallback(Common::CallbackUserData *callback);
+
+    static PowerManager* getInstance();
+private:
+    int getPlatformBrightness();
+    void setPlatformBrightness(int i);
+    void restoreSettedBrightness();
+    static void onPlatformStateChangedCB(device_callback_e type, void *value, void *user_data);
+    PowerManager();
+    virtual ~PowerManager();
+    void broadcastScreenState(PowerState current);
+    std::list<Common::CallbackUserData*> mListener;
+    PowerState mCurrentState;
+    bool mBrightStateEnable;
+    int mCurrentBrightness;
+    bool mShouldBeReadFromCache;
+    bool mSetCustomBrightness;
+    PowerState mCurrentRequestedState;
+
+};
+
+}
+}
+
+#endif /* _POWER_MANAGER_H_ */
+
diff --git a/src/Power/PowerPlatformProxy.cpp b/src/Power/PowerPlatformProxy.cpp
new file mode 100755 (executable)
index 0000000..579c56b
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PowerPlatformProxy.h"
+
+#include <algorithm>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Power {
+
+PowerPlatformProxy::PowerPlatformProxy() :
+    m_dbusOp("org.tizen.system.deviced", "/Org/Tizen/System/DeviceD/Display", "org.tizen.system.deviced.display")
+{
+}
+
+PowerPlatformProxy::~PowerPlatformProxy()
+{
+}
+
+int PowerPlatformProxy::deviceLockState()
+{
+    DeviceAPI::Common::DBusOperationArguments args;
+    args.addArgumentString("lcddim");
+    args.addArgumentString("staycurstate");
+    args.addArgumentString("NULL");
+    args.addArgumentInt32(0);
+
+    return m_dbusOp.invokeSyncGetInt("lockstate", &args);
+}
+
+int PowerPlatformProxy::deviceUnlockState()
+{
+    DeviceAPI::Common::DBusOperationArguments args;
+    args.addArgumentString("lcddim");
+    args.addArgumentString("keeptimer");
+
+    return m_dbusOp.invokeSyncGetInt("unlockstate", &args);
+}
+
+int PowerPlatformProxy::deviceSetBrightnessFromSettings()
+{
+    return m_dbusOp.invokeSyncGetInt("ReleaseBrightness", NULL);
+}
+
+int PowerPlatformProxy::deviceSetBrightness(int val)
+{
+    DeviceAPI::Common::DBusOperationArguments args;
+    args.addArgumentInt32(val);
+
+    return m_dbusOp.invokeSyncGetInt("HoldBrightness", &args);
+}
+
+PowerPlatformProxy& PowerPlatformProxy::getInstance()
+{
+    static PowerPlatformProxy instance;
+
+    return instance;
+}
+
+} //Power
+} //DeviceAPI
diff --git a/src/Power/PowerPlatformProxy.h b/src/Power/PowerPlatformProxy.h
new file mode 100755 (executable)
index 0000000..c2545e7
--- /dev/null
@@ -0,0 +1,49 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _DEVICEAPI_POWER_POWERPLATFORMPROXY_H_
+#define _DEVICEAPI_POWER_POWERPLATFORMPROXY_H_
+
+#include <DBusOperation.h>
+
+namespace DeviceAPI {
+namespace Power {
+
+class PowerPlatformProxy
+{
+private:
+    PowerPlatformProxy();
+
+public:
+    virtual ~PowerPlatformProxy();
+
+    int deviceLockState();
+    int deviceUnlockState();
+    int deviceSetBrightnessFromSettings();
+    int deviceSetBrightness(int val);
+
+private:
+    DeviceAPI::Common::DBusOperation m_dbusOp;
+
+public:
+    static PowerPlatformProxy& getInstance();
+};
+
+}
+}
+
+#endif /* _DEVICEAPI_POWER_POWERPLATFORMPROXY_H_ */
diff --git a/src/Power/PowerUtil.cpp b/src/Power/PowerUtil.cpp
new file mode 100755 (executable)
index 0000000..9187204
--- /dev/null
@@ -0,0 +1,68 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PowerUtil.h"
+
+#include <sstream>
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Power {
+
+using namespace DeviceAPI::Common;
+
+void PowerUtil::throwPowerException(const int errorCode, const std::string &hint)
+{
+    std::stringstream ss;
+    ss << hint << " : " << getPowerErrorMessage(errorCode);
+    LOGE("%s", ss.str().c_str());
+
+    switch(errorCode) {
+        case DEVICE_ERROR_INVALID_PARAMETER:
+            throw InvalidValuesException(ss.str().c_str());
+        case DEVICE_ERROR_PERMISSION_DENIED:
+            throw SecurityException(ss.str().c_str());
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+std::string PowerUtil::getPowerErrorMessage(const int errorCode)
+{
+    LOGE("%d", errorCode);
+
+    switch(errorCode) {
+        case DEVICE_ERROR_OPERATION_FAILED:
+            return "Operation failed";
+        case DEVICE_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case DEVICE_ERROR_INVALID_PARAMETER:
+            return "Invalid Parameter";
+        case DEVICE_ERROR_ALREADY_IN_PROGRESS:
+            return "Operation already in progress";
+        case DEVICE_ERROR_NOT_SUPPORTED:
+            return "Not supported";
+        case DEVICE_ERROR_NOT_INITIALIZED:
+            return "Not initialized";
+        default:
+            return "Unknown Error";
+    }
+}
+
+} // Power
+} // DeviceAPI
diff --git a/src/Power/PowerUtil.h b/src/Power/PowerUtil.h
new file mode 100755 (executable)
index 0000000..2cd1ea4
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_POWER_UTIL_H_
+#define __TIZEN_POWER_UTIL_H_
+
+#include <string>
+#include <device.h>
+
+
+namespace DeviceAPI {
+namespace Power {
+
+class PowerUtil {
+public:
+    static void throwPowerException(const int errorCode, const std::string &hint);
+    static std::string getPowerErrorMessage(const int errorCode);
+};
+
+} // Power
+} // DeviceAPI
+
+#endif // __TIZEN_POWER_UTIL_H_
diff --git a/src/Power/config.xml b/src/Power/config.xml
new file mode 100755 (executable)
index 0000000..92b3f63
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-power.so</library-name>
+    <feature-install-uri>power.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/power</name>
+        <device-capability>power</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/Power/plugin_config.cpp b/src/Power/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..086e0c4
--- /dev/null
@@ -0,0 +1,178 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <map>
+
+#include "plugin_config_impl.h"
+#include "plugin_config.h"
+
+#define POWER_FEATURE_API "http://tizen.org/privilege/power"
+
+#define POWER_DEVICE_CAP "power"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Power {
+
+static FunctionMapping createPowerFunctions();
+
+static FunctionMapping PowerFunctions =
+    createPowerFunctions();
+
+DEFINE_FUNCTION_GETTER(Power, PowerFunctions);
+
+static FunctionMapping createPowerFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_POWER, POWER_DEVICE_CAP);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_POWER);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_POWER, DEVICE_CAP_POWER);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_POWER, POWER_FEATURE_API);
+
+    ACE_CREATE_FEATURE_LIST(POWER_FEATURES);
+    ACE_ADD_API_FEATURE(POWER_FEATURES, FEATURE_POWER);
+
+    /**
+     * Functions
+     */
+    FunctionMapping powerMapping;
+
+    // request
+    AceFunction requestFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REQUEST,
+            POWER_FUNCTION_API_REQUEST,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_REQUEST,
+                               requestFunc));
+
+    // release
+    AceFunction releaseFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_RELEASE,
+            POWER_FUNCTION_API_RELEASE,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_RELEASE,
+                               releaseFunc));
+
+    // setScreenStateChangeListener
+    AceFunction setScreenStateChangeListenerFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_SCREEN_STATE_CHANGE_LISTENER,
+            POWER_FUNCTION_API_SET_SCREEN_STATE_CHANGE_LISTENER,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_SET_SCREEN_STATE_CHANGE_LISTENER,
+                               setScreenStateChangeListenerFunc));
+
+    // setScreenStateChangeListenerFunc
+    AceFunction setScreenStateChangeListenerFuncFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UNSET_SCREEN_STATE_CHANGE_LISTENER,
+            POWER_FUNCTION_API_UNSET_SCREEN_STATE_CHANGE_LISTENER,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_UNSET_SCREEN_STATE_CHANGE_LISTENER,
+                               setScreenStateChangeListenerFuncFunc));
+
+    // getScreenBrightness
+    AceFunction getScreenBrightnessFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_SCREEN_BRIGHTNESS,
+            POWER_FUNCTION_API_GET_SCREEN_BRIGHTNESS,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_GET_SCREEN_BRIGHTNESS,
+                               getScreenBrightnessFunc));
+
+    // setScreenBrightness
+    AceFunction setScreenBrightnessFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_SCREEN_BRIGHTNESS,
+            POWER_FUNCTION_API_SET_SCREEN_BRIGHTNESS,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_SET_SCREEN_BRIGHTNESS,
+                               setScreenBrightnessFunc));
+
+    // isScreenOn
+    AceFunction isScreenOnFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_IS_SCREEN_ON,
+            POWER_FUNCTION_API_IS_SCREEN_ON,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_IS_SCREEN_ON,
+                               isScreenOnFunc));
+
+    // restoreScreenBrightness
+    AceFunction restoreScreenBrightnessFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_RESTORE_SCREEN_BRIGHTNESS,
+            POWER_FUNCTION_API_RESTORE_SCREEN_BRIGHTNESS,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_RESTORE_SCREEN_BRIGHTNESS,
+                               restoreScreenBrightnessFunc));
+
+    // turnScreenOn
+    AceFunction turnScreenOnFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_TURN_SCREEN_ON,
+            POWER_FUNCTION_API_TURN_SCREEN_ON,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_TURN_SCREEN_ON,
+                               turnScreenOnFunc));
+
+    // turnScreenOff
+    AceFunction turnScreenOffFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_TURN_SCREEN_OFF,
+            POWER_FUNCTION_API_TURN_SCREEN_OFF,
+            POWER_FEATURES,
+            DEVICE_LIST_POWER);
+
+    powerMapping.insert(std::make_pair(
+                               POWER_FUNCTION_API_TURN_SCREEN_OFF,
+                               turnScreenOffFunc));
+
+    return powerMapping;
+}
+
+}
+}
diff --git a/src/Power/plugin_config.h b/src/Power/plugin_config.h
new file mode 100755 (executable)
index 0000000..f0fb941
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _POWER_PLUGIN_CONFIG_H_
+#define _POWER_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+namespace DeviceAPI {
+namespace Power {
+
+DECLARE_FUNCTION_GETTER(Power);
+
+#define POWER_CHECK_ACCESS(functionName) \
+aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+        getPowerFunctionData, \
+        functionName)
+
+}
+}
+
+#endif // _POWER_PLUGIN_CONFIG_H_
diff --git a/src/Power/plugin_config_impl.h b/src/Power/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..7e8ab4f
--- /dev/null
@@ -0,0 +1,32 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an AS IS BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _POWER_PLUGIN_CONFIG_IMPL_H_
+#define _POWER_PLUGIN_CONFIG_IMPL_H_
+
+#define POWER_FUNCTION_API_REQUEST "request"
+#define POWER_FUNCTION_API_RELEASE "release"
+#define POWER_FUNCTION_API_SET_SCREEN_STATE_CHANGE_LISTENER "setScreenStateChangeListener"
+#define POWER_FUNCTION_API_UNSET_SCREEN_STATE_CHANGE_LISTENER "unsetScreenStateChangeListener"
+#define POWER_FUNCTION_API_GET_SCREEN_BRIGHTNESS "getScreenBrightness"
+#define POWER_FUNCTION_API_SET_SCREEN_BRIGHTNESS "setScreenBrightness"
+#define POWER_FUNCTION_API_IS_SCREEN_ON "isScreenOn"
+#define POWER_FUNCTION_API_RESTORE_SCREEN_BRIGHTNESS "restoreScreenBrightness"
+#define POWER_FUNCTION_API_TURN_SCREEN_ON "turnScreenOn"
+#define POWER_FUNCTION_API_TURN_SCREEN_OFF "turnScreenOff"
+
+#endif
diff --git a/src/Power/plugin_initializer.cpp b/src/Power/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..81270be
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Logger.h>
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+#include "JSPowerManager.h"
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+#include <Security.h>
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace Power {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+AceSecurityStatus powerAceCheckAccessFunction(const char* functionName)
+{
+    return POWER_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerPowerSetter,
+        DeviceAPI::Power::PowerManagerPriv,
+        gSecurityAccessor);
+
+class_definition_options_t ClassOptions =
+{
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerPowerSetter,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LoggerD("[Tizen\\Power] on_widget_start_callback (" << widgetId << ")");
+    TIME_TRACER_INIT();
+
+    Try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } Catch (Exception) {
+        LoggerE("WrtAccess initialization failed");
+    }
+
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, powerAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LoggerD("[Tizen\\Power] on_widget_stop_callback (" << widgetId << ")");
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"Power");
+    TIME_TRACER_RELEASE();
+
+    Try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } Catch (Exception) {
+        LoggerE("WrtAccess deinitialization failed");
+    }
+
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LoggerD("[Tizen\\Power] on_frame_load_callback (" << context << ")");
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LoggerD("[Tizen\\Power] on_frame_unload_callback (" << context << ")");
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+    PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+    PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+    PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+    PLUGIN_CLASS_MAP_BEGIN
+    PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+            "power",
+            (js_class_template_getter)JSPowerManager::getClassRef,
+            &ClassOptions)
+    PLUGIN_CLASS_MAP_END
+
+}
+}
+
diff --git a/src/Push/CMakeLists.txt b/src/Push/CMakeLists.txt
new file mode 100644 (file)
index 0000000..a2e4902
--- /dev/null
@@ -0,0 +1,58 @@
+
+SET(TARGET_NAME ${push_target})
+SET(DESTINATION_NAME ${push_dest})
+SET(TARGET_IMPL_NAME ${push_impl})
+
+IF(ENABLE_OPTIONAL_PUSH)
+PKG_CHECK_MODULES(platform_pkgs_push REQUIRED push capi-appfw-application)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${application_include}
+    ${platform_pkgs_push_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${application_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSPushManager.cpp
+    JSPushMessage.cpp
+    PushManager.cpp
+    PushMessage.cpp
+    PushUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${application_impl}
+    ${platform_pkgs_push_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_PUSH)
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/push
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Push/JSPushManager.cpp b/src/Push/JSPushManager.cpp
new file mode 100644 (file)
index 0000000..3d01daf
--- /dev/null
@@ -0,0 +1,404 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include <JSApplicationControl.h>
+#include <TimeTracer.h>
+#include <Export.h>
+
+#include "JSPushManager.h"
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Push {
+
+JSClassDefinition JSPushManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "PushManager",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSPushManager::m_function[] = {
+    {
+        PUSH_MANAGER_API_REGISTER_SERVICE,
+        registerService,
+        kJSPropertyAttributeNone
+    },
+    {
+        PUSH_MANAGER_API_UNREGISTER_SERVICE,
+        unregisterService,
+        kJSPropertyAttributeNone
+    },
+    {
+        PUSH_MANAGER_API_CONNECT_SERVICE,
+        connectService,
+        kJSPropertyAttributeNone
+    },
+    {
+        PUSH_MANAGER_API_DISCONNECT_SERVICE,
+        disconnectService,
+        kJSPropertyAttributeNone
+    },
+    {
+        PUSH_MANAGER_API_GET_REGISTRATION_ID,
+        getRegistrationId,
+        kJSPropertyAttributeNone
+    },
+    {
+        PUSH_MANAGER_API_GET_UNREAD_NOTIFICATIONS,
+        getUnreadNotifications,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSPushManager::m_jsClassRef =
+    JSClassCreate(JSPushManager::getClassInfo());
+
+const JSClassRef DLL_EXPORT JSPushManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSPushManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSPushManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        PushManager *priv = PushManager::getInstance();
+        JSObjectSetPrivate(object, static_cast<void*>(priv));
+    }
+}
+
+void JSPushManager::finalize(JSObjectRef object)
+{
+}
+
+JSValueRef JSPushManager::registerService(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = PUSH_CHECK_ACCESS(PUSH_MANAGER_API_REGISTER_SERVICE);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        // Private Object
+        PushManager *priv =
+            static_cast<PushManager *>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+        JSContextRef global_ctx =
+            GlobalContextManager::getInstance()->getGlobalContext(context);
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // appControl
+        DeviceAPI::Application::ApplicationControlPtr appControl;
+        JSObjectRef appControlObj = validator.toObject(0, DeviceAPI::Application::JSApplicationControl::getClassRef());
+        if (appControlObj) {
+            appControl = DeviceAPI::Application::JSApplicationControl::getApplicationControl(context, appControlObj);
+        }
+
+        MultiCallbackUserDataPtr callback(new MultiCallbackUserData(global_ctx));
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(1);
+        if (successCallbackObj) {
+            callback->setCallback("onsuccess", successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(2, true);
+        if (errorCallbackObj) {
+            callback->setCallback("onerror", errorCallbackObj);
+        }
+
+        // perform
+        priv->registerService(appControl, callback, global_ctx);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in PushManager.registerService().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSPushManager::unregisterService(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = PUSH_CHECK_ACCESS(PUSH_MANAGER_API_UNREGISTER_SERVICE);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        bool is_callback_obj = false;
+        // Private Object
+        PushManager *priv = static_cast<PushManager *>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+        JSContextRef global_ctx =
+            GlobalContextManager::getInstance()->getGlobalContext(context);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        MultiCallbackUserDataPtr callback(new MultiCallbackUserData(global_ctx));
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(0, true);
+        if (successCallbackObj) {
+            is_callback_obj = true;
+            callback->setCallback("onsuccess", successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(1, true);
+        if (errorCallbackObj) {
+            is_callback_obj = true;
+            callback->setCallback("onerror", errorCallbackObj);
+        }
+
+        // perform
+        priv->unregisterService(callback, global_ctx, is_callback_obj);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in PushManager.unregisterService().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSPushManager::connectService(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = PUSH_CHECK_ACCESS(PUSH_MANAGER_API_CONNECT_SERVICE);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        // Private Object
+        PushManager *priv =
+            static_cast<PushManager *>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // notificationCallback
+        MultiCallbackUserDataPtr callback;
+        JSObjectRef notificationCallbackObj = validator.toFunction(0);
+        if (notificationCallbackObj) {
+            callback.reset(new MultiCallbackUserData(
+                GlobalContextManager::getInstance()->getGlobalContext(context)));
+            callback->setCallback("onsuccess", notificationCallbackObj);
+        }
+
+        // perform
+        priv->connectService(callback, context);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in PushManager.connectService().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSPushManager::disconnectService(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = PUSH_CHECK_ACCESS(PUSH_MANAGER_API_DISCONNECT_SERVICE);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        // Private Object
+        PushManager *priv =
+            static_cast<PushManager *>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Private object is NULL");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+        // perform
+        priv->disconnectService(context);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in PushManager.disconnectService().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSPushManager::getRegistrationId(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = PUSH_CHECK_ACCESS(PUSH_MANAGER_API_GET_REGISTRATION_ID);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        // Private Object
+        PushManager *priv =
+            static_cast<PushManager *>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+        JSContextRef global_ctx =
+            GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        // perform
+        std::string ret = priv->getRegistrationId(global_ctx);
+        if (ret.empty()) {
+            return JSValueMakeNull(context);
+        } else {
+            return JSUtil::toJSValueRef(context, ret);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in PushManager.getRegistrationId().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSPushManager::getUnreadNotifications(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = PUSH_CHECK_ACCESS(PUSH_MANAGER_API_GET_UNREAD_NOTIFICATIONS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        LOGD("Enter");
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // Private Object
+        PushManager *priv =
+            static_cast<PushManager *>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            LOGE("Private object is NULL.");
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        // perform
+        priv->getUnreadNotifications();
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in PushManager.getRegistrationId().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // Push
+} // DeviceAPI
diff --git a/src/Push/JSPushManager.h b/src/Push/JSPushManager.h
new file mode 100644 (file)
index 0000000..1cb67f1
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_PUSH_MANAGER_H__
+#define __TIZEN_JS_PUSH_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "PushManager.h"
+
+namespace DeviceAPI {
+namespace Push {
+
+class JSPushManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef registerService(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unregisterService(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef connectService(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef disconnectService(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getRegistrationId(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getUnreadNotifications(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Push
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Push/JSPushMessage.cpp b/src/Push/JSPushMessage.cpp
new file mode 100644 (file)
index 0000000..e0c5ba7
--- /dev/null
@@ -0,0 +1,139 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+
+#include "JSPushMessage.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Push {
+
+JSClassDefinition JSPushMessage::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "PushMessage",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSClassRef JSPushMessage::m_jsClassRef =
+    JSClassCreate(JSPushMessage::getClassInfo());
+
+const JSClassRef JSPushMessage::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSPushMessage::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSPushMessage::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object)) {
+        PushMessage *priv = new PushMessage();
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            delete priv;
+        }
+    }
+}
+
+void JSPushMessage::finalize(JSObjectRef object)
+{
+    PushMessage *priv = static_cast<PushMessage *>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+PushMessage* JSPushMessage::getPrivateObject(JSContextRef context, JSObjectRef object)
+{
+    PushMessage *priv = static_cast<PushMessage *>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("private object is NULL");
+        throw TypeMismatchException("PushMessage's private object is NULL.");
+    }
+
+    // appData
+    JSValueRef appData = JSUtil::getProperty(context, object, PUSH_MESSAGE_APP_DATA);
+    priv->setAppData(JSUtil::JSValueToString(context, appData));
+
+    // alertMessage
+    JSValueRef alertMessage = JSUtil::getProperty(context, object, PUSH_MESSAGE_ALERT_MESSAGE);
+    priv->setAlertMessage(JSUtil::JSValueToString(context, alertMessage));
+
+    // date
+    JSValueRef date = JSUtil::getProperty(context, object, PUSH_MESSAGE_DATE);
+    priv->setDate(JSUtil::JSValueToTimeT(context, date));
+
+    return priv;
+}
+
+void JSPushMessage::setPrivateObject(JSContextRef context, JSObjectRef object, PushMessage *priv)
+{
+    if (!priv) {
+        LOGE("private object is NULL");
+        throw TypeMismatchException("PushMessage's private object is NULL.");
+    }
+
+    JSObjectSetPrivate(object, static_cast<void*>(priv));
+
+    // appData
+    JSUtil::setProperty(context, object, PUSH_MESSAGE_APP_DATA,
+            JSUtil::toJSValueRef(context, priv->getAppData()), kJSPropertyAttributeNone);
+
+    // alertMessage
+    JSUtil::setProperty(context, object, PUSH_MESSAGE_ALERT_MESSAGE,
+            JSUtil::toJSValueRef(context, priv->getAlertMessage()), kJSPropertyAttributeNone);
+
+    // date
+    JSUtil::setProperty(context, object, PUSH_MESSAGE_DATE,
+            JSUtil::makeDateObject(context, priv->getDate()), kJSPropertyAttributeNone);
+}
+
+
+} // Push
+} // DeviceAPI
diff --git a/src/Push/JSPushMessage.h b/src/Push/JSPushMessage.h
new file mode 100644 (file)
index 0000000..0850a94
--- /dev/null
@@ -0,0 +1,71 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_PUSH_MESSAGE_H__
+#define __TIZEN_JS_PUSH_MESSAGE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "PushMessage.h"
+
+namespace DeviceAPI {
+namespace Push {
+
+class JSPushMessage
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static PushMessage* getPrivateObject(JSContextRef context, JSObjectRef object);
+    static void setPrivateObject(JSContextRef context, JSObjectRef object, PushMessage *priv);
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Push
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Push/PushManager.cpp b/src/Push/PushManager.cpp
new file mode 100755 (executable)
index 0000000..5dd647d
--- /dev/null
@@ -0,0 +1,703 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <sstream>
+
+#include <app_manager.h>
+
+#include "JSPushMessage.h"
+#include "PushMessage.h"
+#include "PushManager.h"
+#include "PushUtil.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <GlobalContextManager.h>
+
+#ifdef ENABLE_TIME_TRACER
+#define _P(T, x) \
+(TIME_TRACER_ITEM_BEGIN("PUSH_" #T "_PLATFORM", 0), x); \
+TIME_TRACER_ITEM_END("PUSH_" #T "_PLATFORM", 0);
+#else
+#define _P(T, x) x
+#endif
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Push {
+
+static void _get_push_message(push_notification_h handle, PushMessage *message);
+static void get_param(const char *msg, const char *name, char **value);
+
+std::string PushManager::m_appId;
+std::string PushManager::m_pkgId;
+std::mutex PushManager::s_registered_mutex;
+std::mutex PushManager::s_notification_mutex;
+
+static void _get_push_message(push_notification_h handle, PushMessage *message)
+{
+    LOGD("Enter");
+
+    int ret = PUSH_ERROR_NONE;
+    char *appData = NULL;
+    char *rawMessage = NULL;
+    char *alertMessage = NULL;
+    long long int date = -1;
+
+    if (!message) {
+        LOGE("message is null");
+        throw UnknownException("message is null");
+    }
+
+    ret = push_get_notification_data(handle, &appData);
+    if (ret != PUSH_ERROR_NONE) {
+        LOGE("Platform error while getting notification data: %d, %s",
+            ret, PushUtil::getPushErrorMessage(ret).c_str());
+        PushUtil::throwPushException(ret,
+            "Platform error while getting notification data");
+    }
+
+    ret = push_get_notification_message(handle, &rawMessage);
+    if (ret != PUSH_ERROR_NONE) {
+        LOGE("Platform error while getting notification message: %d, %s",
+            ret, PushUtil::getPushErrorMessage(ret).c_str());
+        PushUtil::throwPushException(ret,
+            "Platform error while getting notification message");
+    }
+
+    get_param(rawMessage, "alertMessage", &alertMessage);
+    if (!alertMessage) {
+        std::stringstream ss;
+        ss << "Platform error while getting alert message from raw message. ";
+        LOGE("%s", ss.str().c_str());
+        throw UnknownException((ss.str()).c_str());
+    }
+    free(rawMessage);
+    rawMessage = NULL;
+
+    ret = push_get_notification_time(handle, &date);
+    if (ret != PUSH_ERROR_NONE) {
+        std::stringstream ss;
+        ss << "Platform error while getting notification date/time."
+            << PushUtil::getPushErrorMessage(ret);
+        LOGE("%s", ss.str().c_str());
+    }
+
+    if (appData) {
+        message->setAppData(appData);
+    }
+
+    if (alertMessage) {
+        message->setAlertMessage(alertMessage);
+    }
+
+    if (date >= 0) {
+        message->setDate((time_t)date);
+    }
+
+    free(appData);
+    appData = NULL;
+    free(alertMessage);
+    alertMessage = NULL;
+}
+
+static void get_param(const char *msg, const char *name, char **value)
+{
+    int step = 0;
+    int pos = 0;
+    int tokenpos = 0;
+
+    while (step >= 0) {
+        switch (step) {
+            case 0: // key
+                switch (msg[pos]) {
+                    case '=':
+                        if (!strncmp(name, &msg[tokenpos], strlen(name))) {
+                            step = 2;
+                            tokenpos = pos + 1;
+                        } else {
+                            step = 1;
+                        }
+                        break;
+                    case '&':
+                        tokenpos = pos + 1;
+                        step = 0;
+                        break;
+                    case 0:
+                        step = -1;
+                        tokenpos = pos;
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            case 1: // skip
+                switch (msg[pos]) {
+                    case '&':
+                        tokenpos = pos + 1;
+                        step = 0;
+                        break;
+                    case 0:
+                        step = -1;
+                        tokenpos = pos;
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            case 2: // value
+                switch (msg[pos]) {
+                    case '&':
+                    case 0:
+                        step = -1;
+                        break;
+                    default:
+                        break;
+                }
+                break;
+            default:
+                break;
+        }
+        pos++;
+    }
+
+    *value = (char*)calloc(1, pos - tokenpos);
+    if (*value != NULL) {
+        strncpy(*value, &msg[tokenpos], pos - tokenpos - 1);
+    }
+}
+
+static void push_connection_state_cb(push_state_e state, const char *err,
+    void *user_data)
+{
+    LOGD("Push connection state cb with state: %d, err: %s", state, err);
+
+    PushManager *thisPushManager = static_cast<PushManager*>(user_data);
+    if (!thisPushManager) {
+        LOGE("user_data of push_connection_state_cb() is NULL.");
+    } else {
+        std::lock_guard<std::mutex> lock(PushManager::s_registered_mutex);
+        thisPushManager->m_connectionState = state;
+    }
+}
+
+static void push_notify_cb(push_notification_h noti, void *user_data)
+{
+    PushMessage *pushMessage = new PushMessage();
+    PushMessage *dummy = NULL;
+
+    LOGD("Push notification cb");
+
+    try {
+        PushManager *thisPushManager = static_cast<PushManager*>(user_data);
+        if (!thisPushManager) {
+            throw UnknownException("user_data of push_notify_cb() is NULL.");
+        }
+
+        _get_push_message(noti, pushMessage);
+
+        std::lock_guard<std::mutex> lock(PushManager::s_notification_mutex);
+        std::map<JSContextRef, MultiCallbackUserDataPtr>::iterator itr =
+            thisPushManager->m_notificationCallback.begin();
+        while (itr != thisPushManager->m_notificationCallback.end()) {
+            MultiCallbackUserDataPtr callback = itr->second;
+            if (callback) {
+                JSContextRef context = callback->getContext();
+                if(GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+
+                    dummy = new PushMessage(pushMessage->getAppData(),
+                            pushMessage->getAlertMessage(),
+                            pushMessage->getDate());
+
+                    JSObjectRef pushMessageObj =
+                        JSObjectMake(context, JSPushMessage::getClassRef(), NULL);
+                    JSPushMessage::setPrivateObject(context, pushMessageObj, dummy);
+
+                    callback->invokeCallback("onsuccess", pushMessageObj);
+                }
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s", err.getMessage().c_str());
+    }
+
+    delete pushMessage;
+    pushMessage = NULL;
+}
+
+static void push_registration_result_cb(push_result_e result, const char *msg,
+    void *user_data)
+{
+    LOGD("Push registration cb");
+    int ret;
+    char *tmp = NULL;
+    PushMultiCallbackUserDataHolder* holder = NULL;
+
+    try {
+        holder = static_cast<PushMultiCallbackUserDataHolder*>(user_data);
+        if (!holder) {
+            LOGE("callback holder is null");
+            return;
+        }
+
+        MultiCallbackUserDataPtr callback = holder->ptr;
+        if (!callback) {
+            delete holder;
+            holder = NULL;
+            return;
+        }
+
+        JSContextRef context = callback->getContext();
+        if( !GlobalContextManager::getInstance()->isAliveGlobalContext(context)){
+            LOGE("context was closed");
+            delete holder;
+            holder = NULL;
+            return;
+        }
+
+        if (result == PUSH_RESULT_SUCCESS) {
+            ret = push_get_registration_id(PushManager::getInstance()->m_connectionHandle, &tmp);
+            if (PUSH_ERROR_NONE != ret) {
+                delete holder;
+                holder = NULL;
+
+                LOGE("Platform error while getting registration id: %d, %s", ret,
+                    PushUtil::getPushErrorMessage(ret).c_str());
+                PushUtil::throwPushException(ret,
+                    "Platform error while getting registration id");
+            }
+            if (tmp) {
+                std::string registrationId(tmp);
+                callback->invokeCallback("onsuccess",
+                    JSUtil::toJSValueRef(context, registrationId));
+                free(tmp);
+            }
+        } else {
+            UnknownException error(msg == NULL ? "Unknown" : msg);
+            JSObjectRef errorObj =
+                JSWebAPIErrorFactory::makeErrorObject(context, error);
+            callback->invokeCallback("onerror", errorObj);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s", err.getMessage().c_str());
+    }
+
+    delete holder;
+    holder = NULL;
+}
+
+static void push_unregistration_result_cb(push_result_e result, const char *msg,
+    void *user_data)
+{
+    LOGD("Push unregistration cb");
+    PushMultiCallbackUserDataHolder* holder = NULL;
+
+    try {
+        holder = static_cast<PushMultiCallbackUserDataHolder*>(user_data);
+        if (!holder) {
+            LOGE("callback holder is null");
+            return;
+        }
+
+        MultiCallbackUserDataPtr callback = holder->ptr;
+        if (!callback) {
+            delete holder;
+            holder = NULL;
+            return;
+        }
+
+        JSContextRef context = callback->getContext();
+        if( !GlobalContextManager::getInstance()->isAliveGlobalContext(context)){
+            LOGE("context was closed");
+            delete holder;
+            holder = NULL;
+            return;
+        }
+
+        if (result == PUSH_RESULT_SUCCESS) {
+            callback->invokeCallback("onsuccess");
+        } else {
+            LOGD("Enter msg: %s", msg);
+            UnknownException error(msg == NULL ? "Unknown" : msg);
+            JSObjectRef errorObj =
+                JSWebAPIErrorFactory::makeErrorObject(context, error);
+            callback->invokeCallback("onerror", errorObj);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("%s", err.getMessage().c_str());
+    }
+
+    delete holder;
+    holder = NULL;
+}
+
+static gboolean push_unregistration_result_cb1(void *user_data)
+{
+    LOGD("Push unregistration cb1");
+    PushMultiCallbackUserDataHolder* holder = NULL;
+
+    try {
+        holder = static_cast<PushMultiCallbackUserDataHolder*>(user_data);
+        if (!holder) {
+            LOGE("callback holder is null");
+            return false;
+        }
+
+        MultiCallbackUserDataPtr callback = holder->ptr;
+        if (!callback) {
+            delete holder;
+            holder = NULL;
+            return false;
+        }
+
+        callback->invokeCallback("onsuccess");
+    } catch (const BasePlatformException &err) {
+        LOGE("%s", err.getMessage().c_str());
+    }
+
+    delete holder;
+    holder = NULL;
+    return false;
+}
+
+PushManager::PushManager():
+    m_connectionState(PUSH_STATE_UNREGISTERED),
+    m_connectionHandle(NULL)
+{
+    LOGD("Connecting to the push service...");
+    setAppId();
+
+    int ret = push_connect(m_pkgId.c_str(), push_connection_state_cb,
+        push_notify_cb, this, &m_connectionHandle);
+
+    if (PUSH_ERROR_NONE != ret) {
+        LOGE("Error while connecting to the push service: %d, %s", ret,
+            PushUtil::getPushErrorMessage(ret).c_str());
+    }
+}
+
+PushManager::~PushManager()
+{
+    LOGD("Disconnecting to the push service...");
+
+    push_disconnect(m_connectionHandle);
+}
+
+PushManager *PushManager::getInstance() {
+    LOGD("Getting instance of PushManager...");
+    static PushManager instance;
+    return &instance;
+}
+
+void PushManager::setAppId() {
+    app_info_h handle;
+    char *_pkg_id = NULL;
+    char *app_id = NULL;
+    int pid = getpid();
+    int ret = app_manager_get_app_id(pid, &app_id);
+    if (ret != APP_MANAGER_ERROR_NONE) {
+        LOGE("Fail to get appid: %d", ret);
+        return;
+    }
+    m_appId = app_id;
+    free(app_id);
+
+    ret = app_manager_get_app_info(m_appId.c_str(), &handle);
+    if (ret != APP_MANAGER_ERROR_NONE) {
+        LOGE("WrtAccess initialization failed: %d", ret);
+        return;
+    }
+
+    ret = app_info_get_package(handle, &_pkg_id);
+    if ((ret != APP_MANAGER_ERROR_NONE) || (_pkg_id == NULL)) {
+        LOGW("Fail to get pkg id: %d", ret);
+    }
+
+    ret = app_info_destroy(handle);
+    if (ret != APP_MANAGER_ERROR_NONE) {
+        LOGE("WrtAccess initialization failed: %d", ret);
+        return;
+    }
+
+    if (_pkg_id) {
+        m_pkgId = _pkg_id;
+        free(_pkg_id);
+    }
+}
+
+void PushManager::registerService(ApplicationControlPtr appControl,
+        MultiCallbackUserDataPtr callback, JSContextRef context)
+{
+    LOGD("Entered");
+    int ret;
+    app_control_h service;
+
+    ret = _P(registerService, app_control_create(&service));
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Platform error while creating service: %d, %s", ret,
+            PushUtil::getPushErrorMessage(ret).c_str());
+        PushUtil::throwPushException(ret, "Platform error while create service");
+    }
+
+    if (appControl->getOperation().compare("") != 0) {
+        ret = _P(registerService, app_control_set_operation(service,
+            appControl->getOperation().c_str()));
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("Platform error while setting operation to appcontrol: %d, %s",
+                PushUtil::getPushErrorMessage(ret).c_str());
+            PushUtil::throwPushException(ret,
+                "Platform error while setting operation to appcontrol");
+        }
+    } else {
+        throw InvalidValuesException(
+            "the operation of application control is invalid.");
+    }
+
+    if (appControl->getUri().compare("") != 0) {
+        ret = _P(registerService, app_control_set_uri(service,
+            appControl->getUri().c_str()));
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGW("Platform error while setting uri to appControl: %d, %s",
+                ret, PushUtil::getPushErrorMessage(ret).c_str());
+        }
+    }
+
+    if (appControl->getMime().compare("") != 0) {
+        ret = _P(registerService, app_control_set_mime(service,
+            appControl->getMime().c_str()));
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGW("Platform error while setting mime to appControl: %d, %s",
+                ret, PushUtil::getPushErrorMessage(ret).c_str());
+        }
+    }
+
+    ret = _P(registerService, app_control_set_app_id(service, m_appId.c_str()));
+    if (ret != APP_CONTROL_ERROR_NONE) {
+        LOGE("Platform error while setting appId to appControl: %d, %s",
+            ret, PushUtil::getPushErrorMessage(ret).c_str());
+        PushUtil::throwPushException(ret,
+            "Platform error while setting appId to appControl");
+    }
+
+    std::vector<ApplicationControlDataPtr> controlDataArray =
+        appControl->getAppControlDataArray();
+    if (!controlDataArray.empty()) {
+        std::string key;
+        const char **arr = NULL;
+
+        for (size_t i = 0; i < controlDataArray.size(); i++) {
+            key = controlDataArray.at(i)->getKey();
+            if (key.empty()) {
+                LOGW("Invalid key for %d in ApplicationControl's data array.", i);
+                continue;
+            }
+
+            std::vector<std::string> valueArray =
+                controlDataArray.at(i)->getValue();
+            size_t size = valueArray.size();
+
+            arr = (const char**)calloc(sizeof(char*), size);
+            if (arr == NULL) {
+                LOGE("calloc failed");
+                throw UnknownException(
+                    "Out of Memory: Can't allocate value array for ApplicationControl's data");
+            }
+
+            for (size_t j = 0; j < size; j++) {
+                arr[j] = valueArray.at(j).c_str();
+            }
+
+            if (size == 1) {
+                ret = _P(registerService, app_control_add_extra_data(service,
+                    (const char*)key.c_str(), arr[0]));
+                if (ret != APP_CONTROL_ERROR_NONE) {
+                    LOGW("Platform error while adding extra data to appControl: %d, %s",
+                        ret, PushUtil::getPushErrorMessage(ret).c_str());
+                }
+            } else {
+                ret = _P(registerService, app_control_add_extra_data_array(
+                    service, (const char*)key.c_str(), arr, size));
+                if (ret != APP_CONTROL_ERROR_NONE) {
+                    LOGW("Platform error while adding extra data array to appControl: %d, %s",
+                        ret, PushUtil::getPushErrorMessage(ret).c_str());
+                }
+            }
+
+            if (arr) {
+                free(arr);
+            }
+        }
+    }
+
+    std::lock_guard<std::mutex> lock(s_registered_mutex);
+    m_registeredCallback[context] = callback;
+
+    PushMultiCallbackUserDataHolder* holder =
+        new(std::nothrow) PushMultiCallbackUserDataHolder();
+    if (!holder) {
+        LOGE("Failed to allocate memory");
+
+        ret = app_control_destroy(service);
+        if (ret != APP_CONTROL_ERROR_NONE) {
+            LOGE("Failed to destroy app control: %d, %s", ret,
+                PushUtil::getPushErrorMessage(ret).c_str());
+        }
+        throw UnknownException("Failed to allocate memory");
+    }
+    holder->ptr = callback;
+
+    ret = _P(registerService, push_register(m_connectionHandle, service,
+                push_registration_result_cb, (void*)holder));
+    if (ret != PUSH_ERROR_NONE) {
+        delete holder;
+        holder = NULL;
+
+        int r = app_control_destroy(service);
+        if (r != APP_CONTROL_ERROR_NONE) {
+            LOGE("Failed to destroy app control: %d, %s", ret,
+                PushUtil::getPushErrorMessage(ret).c_str());
+        }
+        LOGE("Platform error while registering the application: %d, %s", ret,
+            PushUtil::getPushErrorMessage(ret).c_str());
+        PushUtil::throwPushException(ret,
+            "Platform error while registering the application.");
+    }
+
+    _P(registerService, app_control_destroy(service));
+}
+
+void PushManager::unregisterService(MultiCallbackUserDataPtr callback, JSContextRef context,
+        bool is_callback_obj)
+{
+    LOGD("Entered");
+    int ret;
+
+    std::lock_guard<std::mutex> lock(s_registered_mutex);
+    std::map<JSContextRef, MultiCallbackUserDataPtr>::iterator itr =
+        m_registeredCallback.find(context);
+    if (itr != m_registeredCallback.end()) {
+        LOGD("context will be removed");
+        m_registeredCallback.erase(context);
+    }
+
+    if (!is_callback_obj) {
+        return;
+    }
+
+    PushMultiCallbackUserDataHolder* holder =
+        new(std::nothrow) PushMultiCallbackUserDataHolder();
+    if (!holder) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    holder->ptr = callback;
+
+    if (!m_registeredCallback.empty() || m_connectionState == PUSH_STATE_UNREGISTERED) {
+        if (!g_idle_add(push_unregistration_result_cb1, (void*)holder)) {
+            LOGE("g_idle_add failed");
+            delete holder;
+            holder = NULL;
+            return;
+        }
+    } else {
+        ret = _P(unregisterService, push_deregister(m_connectionHandle,
+                    push_unregistration_result_cb, (void*)holder));
+        if (ret != PUSH_ERROR_NONE) {
+            LOGD("push_deregister failed: %d", ret);
+            delete holder;
+            holder = NULL;
+            PushUtil::throwPushException(ret,
+                    "Platform error while unregistering the application");
+        }
+    }
+}
+
+void PushManager::connectService(MultiCallbackUserDataPtr notificationCallback,
+        JSContextRef context)
+{
+    LOGD("Entered");
+    if (notificationCallback) {
+        std::lock_guard<std::mutex> lock(s_notification_mutex);
+        m_notificationCallback[context] = notificationCallback;
+    } else {
+        LOGE("notificationCallback of arguments is NULL.");
+        throw UnknownException("notificationCallback of arguments is NULL.");
+    }
+}
+
+void PushManager::disconnectService(JSContextRef context)
+{
+    LOGD("Entered");
+    std::lock_guard<std::mutex> lock(s_notification_mutex);
+    std::map<JSContextRef, MultiCallbackUserDataPtr>::iterator itr =
+        m_notificationCallback.find(context);
+    if (itr != m_registeredCallback.end()) {
+        LOGD("context will be removed");
+        m_notificationCallback.erase(context);
+    }
+}
+
+std::string PushManager::getRegistrationId(JSContextRef context)
+{
+    LOGD("Entered");
+    int ret;
+    char *regId = NULL;
+    std::string str = "";
+
+    s_registered_mutex.lock();
+    std::map<JSContextRef, MultiCallbackUserDataPtr>::iterator itr =
+        m_registeredCallback.find(context);
+    if (itr == m_registeredCallback.end()) {
+        s_registered_mutex.unlock();
+        return str;
+    }
+    s_registered_mutex.unlock();
+
+    ret = _P(getRegistrationId, push_get_registration_id(m_connectionHandle, &regId));
+    if (ret != PUSH_ERROR_NONE) {
+        LOGE("Platform error while getting registration id: %d, %s", ret,
+            PushUtil::getPushErrorMessage(ret).c_str());
+    } else {
+        if (regId) {
+            str = regId;
+            free(regId);
+        }
+    }
+
+    return str;
+}
+
+void PushManager::getUnreadNotifications()
+{
+    LOGD("Enter");
+
+    int ret = push_request_unread_notification(m_connectionHandle);
+    if (ret != PUSH_ERROR_NONE) {
+        LOGE("Failed to request unread push messages: %d, %s", ret,
+                PushUtil::getPushErrorMessage(ret).c_str());
+        PushUtil::throwPushException(ret,
+                "Failed to request unread push messages");
+    }
+}
+
+} // Push
+} // DeviceAPI
diff --git a/src/Push/PushManager.h b/src/Push/PushManager.h
new file mode 100755 (executable)
index 0000000..d05808d
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_PUSH_MANAGER_H__
+#define __TIZEN_PUSH_MANAGER_H__
+
+#include <MultiCallbackUserData.h>
+
+#include <JSApplicationControl.h>
+
+#include <push.h>
+#include <map>
+#include <glib.h>
+#include <mutex>
+#include "PushTypes.h"
+
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Application;
+
+namespace DeviceAPI {
+namespace Push {
+
+struct PushMultiCallbackUserDataHolder {
+    MultiCallbackUserDataPtr ptr;
+};
+
+class PushManager
+{
+public:
+    void registerService(ApplicationControlPtr appControl, MultiCallbackUserDataPtr callback,
+            JSContextRef context);
+    void unregisterService(MultiCallbackUserDataPtr callback, JSContextRef context,
+            bool is_callback_obj);
+    void connectService(MultiCallbackUserDataPtr notificationCallback, JSContextRef context);
+    void disconnectService(JSContextRef context);
+    std::string getRegistrationId(JSContextRef context);
+    void getUnreadNotifications();
+
+    static PushManager* getInstance();
+    static void setAppId();
+
+private:
+    PushManager();
+    virtual ~PushManager();
+
+public:
+    push_state_e m_connectionState;
+    push_connection_h m_connectionHandle;
+    std::map<JSContextRef, MultiCallbackUserDataPtr> m_registeredCallback;
+    std::map<JSContextRef, MultiCallbackUserDataPtr> m_notificationCallback;
+    static std::mutex s_registered_mutex;
+    static std::mutex s_notification_mutex;
+
+private:
+    static std::string m_appId;
+    static std::string m_pkgId;
+};
+
+} // Push
+} // DeviceAPI
+
+#endif // __TIZEN_PUSH_MANAGER_H__
diff --git a/src/Push/PushMessage.cpp b/src/Push/PushMessage.cpp
new file mode 100644 (file)
index 0000000..f846158
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "PushMessage.h"
+
+namespace DeviceAPI {
+namespace Push {
+
+PushMessage::PushMessage():
+    m_appData(""),
+    m_alertMessage("")
+{
+}
+
+PushMessage::PushMessage(const std::string &appData,
+                         const std::string &alertMessage,
+                         time_t date):
+    m_appData(appData),
+    m_alertMessage(alertMessage),
+    m_date(date)
+{
+}
+
+PushMessage::~PushMessage()
+{
+}
+
+std::string PushMessage::getAppData() const
+{
+    return m_appData;
+}
+
+void PushMessage::setAppData(std::string appData)
+{
+    m_appData = appData;
+}
+
+std::string PushMessage::getAlertMessage() const
+{
+    return m_alertMessage;
+}
+
+void PushMessage::setAlertMessage(std::string alertMessage)
+{
+    m_alertMessage = alertMessage;
+}
+
+time_t PushMessage::getDate() const
+{
+    return m_date;
+}
+
+void PushMessage::setDate(time_t date)
+{
+    m_date = date;
+}
+
+
+} // Push
+} // DeviceAPI
diff --git a/src/Push/PushMessage.h b/src/Push/PushMessage.h
new file mode 100644 (file)
index 0000000..f8e402c
--- /dev/null
@@ -0,0 +1,59 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_PUSH_MESSAGE_H__
+#define __TIZEN_PUSH_MESSAGE_H__
+
+#include <MultiCallbackUserData.h>
+
+#include "PushTypes.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Push {
+
+class PushMessage
+{
+public:
+    PushMessage();
+    PushMessage(const std::string &appData,
+                const std::string &alertMessage,
+                time_t date);
+    virtual ~PushMessage();
+
+    std::string getAppData() const;
+    void setAppData(std::string appData);
+
+    std::string getAlertMessage() const;
+    void setAlertMessage(std::string alertMessage);
+
+    time_t getDate() const;
+    void setDate(time_t date);
+
+private:
+    std::string m_appData;
+    std::string m_alertMessage;
+    time_t m_date;
+};
+
+typedef std::shared_ptr<PushMessage> PushMessagePtr;
+
+} // Push
+} // DeviceAPI
+
+#endif // __TIZEN_PUSH_MESSAGE_H__
diff --git a/src/Push/PushTypes.h b/src/Push/PushTypes.h
new file mode 100644 (file)
index 0000000..2048323
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _PUSH_TYPES_H_
+#define _PUSH_TYPES_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace DeviceAPI {
+namespace Push {
+
+// typedef PushRegistrationId
+typedef std::string PushRegistrationId;
+
+} // Push
+} // DeviceAPI
+
+#endif // _PUSH_TYPES_H_
diff --git a/src/Push/PushUtil.cpp b/src/Push/PushUtil.cpp
new file mode 100644 (file)
index 0000000..ac1a0d6
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PushUtil.h"
+
+#include <sstream>
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Push {
+
+using namespace DeviceAPI::Common;
+
+void PushUtil::throwPushException(const int errorCode,
+                                        const std::string &hint)
+{
+    LOGD("Enter");
+
+    std::stringstream ss;
+    ss << hint << " : " << getPushErrorMessage(errorCode);
+    LOGE("%s", ss.str().c_str());
+
+    switch(errorCode) {
+        case PUSH_ERROR_NOT_CONNECTED:
+            throw ServiceNotAvailableException(ss.str().c_str());
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+std::string PushUtil::getPushErrorMessage(const int errorCode)
+{
+    std::string msg = "";
+
+    switch (errorCode) {
+        case PUSH_ERROR_INVALID_PARAMETER:
+            msg = "Invalid parameter";
+            break;
+        case PUSH_ERROR_OUT_OF_MEMORY:
+            msg = "Out of memory";
+            break;
+        case PUSH_ERROR_NOT_CONNECTED:
+            msg = "Network is unreachable";
+            break;
+        case PUSH_ERROR_NO_DATA:
+            msg = "No data available";
+            break;
+        case PUSH_ERROR_OPERATION_FAILED:
+            msg = "Internal operation failed";
+            break;
+        case APP_CONTROL_ERROR_APP_NOT_FOUND:
+            msg = "The application was not found";
+            break;
+        case APP_CONTROL_ERROR_KEY_NOT_FOUND:
+            msg = "Specified key not found";
+            break;
+        case APP_CONTROL_ERROR_KEY_REJECTED:
+            msg = "Not available key";
+            break;
+        case APP_CONTROL_ERROR_INVALID_DATA_TYPE:
+            msg = "Invalid data type";
+            break;
+        case PUSH_ERROR_NONE:
+            break;
+        default:
+            msg = "Unknown error";
+    }
+
+    return msg;
+}
+
+} // Push
+} // DeviceAPI
diff --git a/src/Push/PushUtil.h b/src/Push/PushUtil.h
new file mode 100644 (file)
index 0000000..0b01949
--- /dev/null
@@ -0,0 +1,37 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_ACCOUNT_ACCOUNT_UTIL_H_
+#define __TIZEN_ACCOUNT_ACCOUNT_UTIL_H_
+
+#include <string>
+#include <push.h>
+#include <app_control.h>
+
+namespace DeviceAPI {
+namespace Push {
+
+class PushUtil {
+public:
+    static void throwPushException(const int errorCode, const std::string &hint);
+    static std::string getPushErrorMessage(const int errorCode);
+};
+
+} // Account
+} // DeviceAPI
+
+#endif // __TIZEN_ACCOUNT_ACCOUNT_UTIL_H_
diff --git a/src/Push/config.xml b/src/Push/config.xml
new file mode 100644 (file)
index 0000000..f50c830
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-push.so</library-name>
+    <feature-install-uri>push.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/push</name>
+        <device-capability>push</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/Push/plugin_config.cpp b/src/Push/plugin_config.cpp
new file mode 100644 (file)
index 0000000..b65440b
--- /dev/null
@@ -0,0 +1,135 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define PUSH_FEATURE_API "http://tizen.org/privilege/push"
+
+#define PUSH_DEVICE_CAP "push"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Push {
+
+static FunctionMapping createPushFunctions();
+static FunctionMapping PushFunctions = createPushFunctions();
+
+#pragma GCC visibility push(default)
+DEFINE_FUNCTION_GETTER(Push, PushFunctions);
+#pragma GCC visibility pop
+
+static FunctionMapping createPushFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_PUSH, PUSH_DEVICE_CAP);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_PUSH);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_PUSH, DEVICE_CAP_PUSH);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_PUSH, PUSH_FEATURE_API);
+
+    ACE_CREATE_FEATURE_LIST(PUSH_FEATURES);
+    ACE_ADD_API_FEATURE(PUSH_FEATURES, FEATURE_PUSH);
+
+    /**
+     * Functions
+     */
+    FunctionMapping pushMapping;
+
+    // registerService
+    AceFunction registerServiceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_REGISTER_SERVICE,
+            PUSH_MANAGER_API_REGISTER_SERVICE,
+            PUSH_FEATURES,
+            DEVICE_LIST_PUSH);
+
+    pushMapping.insert(std::make_pair(
+                               PUSH_MANAGER_API_REGISTER_SERVICE,
+                               registerServiceFunc));
+
+    // unregisterService
+    AceFunction unregisterServiceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_UNREGISTER_SERVICE,
+            PUSH_MANAGER_API_UNREGISTER_SERVICE,
+            PUSH_FEATURES,
+            DEVICE_LIST_PUSH);
+
+    pushMapping.insert(std::make_pair(
+                               PUSH_MANAGER_API_UNREGISTER_SERVICE,
+                               unregisterServiceFunc));
+
+    // connectService
+    AceFunction connectServiceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_CONNECT_SERVICE,
+            PUSH_MANAGER_API_CONNECT_SERVICE,
+            PUSH_FEATURES,
+            DEVICE_LIST_PUSH);
+
+    pushMapping.insert(std::make_pair(
+                               PUSH_MANAGER_API_CONNECT_SERVICE,
+                               connectServiceFunc));
+
+    // disconnectService
+    AceFunction disconnectServiceFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_DISCONNECT_SERVICE,
+            PUSH_MANAGER_API_DISCONNECT_SERVICE,
+            PUSH_FEATURES,
+            DEVICE_LIST_PUSH);
+
+    pushMapping.insert(std::make_pair(
+                               PUSH_MANAGER_API_DISCONNECT_SERVICE,
+                               disconnectServiceFunc));
+
+    // getRegistrationId
+    AceFunction getRegistrationIdFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_REGISTRATION_ID,
+            PUSH_MANAGER_API_GET_REGISTRATION_ID,
+            PUSH_FEATURES,
+            DEVICE_LIST_PUSH);
+
+    pushMapping.insert(std::make_pair(
+                               PUSH_MANAGER_API_GET_REGISTRATION_ID,
+                               getRegistrationIdFunc));
+
+    // getUnreadNotifications
+    AceFunction getUnreadNotificationsFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_UNREAD_NOTIFICATIONS,
+            PUSH_MANAGER_API_GET_UNREAD_NOTIFICATIONS,
+            PUSH_FEATURES,
+            DEVICE_LIST_PUSH);
+
+    pushMapping.insert(std::make_pair(
+                               PUSH_MANAGER_API_GET_UNREAD_NOTIFICATIONS,
+                               getUnreadNotificationsFunc));
+
+    return pushMapping;
+}
+
+} // Push
+} // DeviceAPI
diff --git a/src/Push/plugin_config.h b/src/Push/plugin_config.h
new file mode 100644 (file)
index 0000000..f998c27
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _PUSH_PLUGIN_CONFIG_H_
+#define _PUSH_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+#include <Logger.h>
+
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Push {
+
+// attributes
+#define PUSH_MESSAGE_APP_DATA "appData"
+#define PUSH_MESSAGE_ALERT_MESSAGE "alertMessage"
+#define PUSH_MESSAGE_DATE "date"
+
+// functions
+#define PUSH_MANAGER_API_REGISTER_SERVICE "registerService"
+#define PUSH_MANAGER_API_UNREGISTER_SERVICE "unregisterService"
+#define PUSH_MANAGER_API_CONNECT_SERVICE "connectService"
+#define PUSH_MANAGER_API_DISCONNECT_SERVICE "disconnectService"
+#define PUSH_MANAGER_API_GET_REGISTRATION_ID "getRegistrationId"
+#define PUSH_MANAGER_API_GET_UNREAD_NOTIFICATIONS "getUnreadNotifications"
+
+DECLARE_FUNCTION_GETTER(Push);
+
+#define PUSH_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getPushFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _PUSH_PLUGIN_CONFIG_H_
diff --git a/src/Push/plugin_config_impl.h b/src/Push/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..dbe31ad
--- /dev/null
@@ -0,0 +1,23 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _PUSH_PLUGIN_CONFIG_IMPL_H_
+#define _PUSH_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_PUSH_PUSH_MANAGER_CLASS "push"
+
+#endif // _PUSH_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/Push/plugin_initializer.cpp b/src/Push/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..13376b9
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <dpl/string.h>
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+
+#include "JSPushManager.h"
+#include "plugin_config.h"
+#include "PushManager.h"
+
+#include <TimeTracer.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Push {
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Push] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Push] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "Push";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Push] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Push] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_PUSH_PUSH_MANAGER_CLASS,
+        (js_class_template_getter)JSPushManager::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_END
+
+} // Push
+} // DeviceAPI
diff --git a/src/RefImpl/CMakeLists.txt b/src/RefImpl/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..570be8b
--- /dev/null
@@ -0,0 +1,50 @@
+SET(TARGET_NAME ${refimpl_target})
+SET(DESTINATION_NAME ${refimpl_dest})
+SET(TARGET_IMPL_NAME ${refimpl_impl})
+
+SET(CMAKE_INSTALL_RPATH
+       ${CMAKE_INSTALL_RPATH}
+       ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+       ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+       JSRefImplManager.cpp
+       RefImplManager.cpp
+       mock.cpp
+       JSSuper.cpp
+       JSSub.cpp
+       Super.cpp
+       Sub.cpp
+    NestedValue.cpp
+    JSNestedValue.cpp
+)
+
+INCLUDE_DIRECTORIES(
+       ${INCLUDE_COMMON}
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+       ${LIBS_COMMON}
+)
+
+SET(SRCS
+       plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+       ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/power
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
+
+add_subdir(test)
diff --git a/src/RefImpl/JSNestedValue.cpp b/src/RefImpl/JSNestedValue.cpp
new file mode 100755 (executable)
index 0000000..2f917c7
--- /dev/null
@@ -0,0 +1,174 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSNestedValue.h"
+#include "NestedValue.h"
+
+#include <ArgumentValidator.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+
+#include <string>
+
+using namespace DeviceAPI::Common;
+using namespace std;
+
+namespace DeviceAPI {
+namespace Reference {
+
+JSClassRef JSNestedValue::m_jsClassRef = NULL;
+
+JSClassDefinition JSNestedValue::m_jsClassInfo = {
+    0, // current (and only) version is 0
+    kJSClassAttributeNone, //attributes
+    "NestedValue", //class name
+    NULL, // parent class
+    JSNestedValue::m_property, //static values
+    JSNestedValue::m_function, // static functions
+    JSNestedValue::initialize, // initialize
+    JSNestedValue::finalize, //finalize
+    NULL, //hasProperty
+    NULL, //getProperty
+    NULL, //setProperty
+    NULL, //deleteProperty
+    NULL, //getPropertyNames
+    NULL, // callAsFunction
+    NULL, // constructor
+    NULL,
+    NULL // convertToType
+};
+
+
+JSStaticValue JSNestedValue::m_property[] = {
+       { "Number", JSNestedValue::getProperty, JSNestedValue::setProperty, kJSPropertyAttributeNone},
+       { "Message", JSNestedValue::getProperty, JSNestedValue::setProperty, kJSPropertyAttributeNone},
+       { 0, 0, 0, 0 }
+};
+
+
+JSStaticFunction JSNestedValue::m_function[] = {
+    { "print", JSNestedValue::print, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+
+const JSClassRef JSNestedValue::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+const JSClassDefinition* JSNestedValue::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+
+boost::shared_ptr<NestedValue> JSNestedValue::getNative(JSContextRef ctx, JSValueRef value){
+    JSObjectRef object = JSUtil::JSValueToObject(ctx, value);    
+    NestedValueHolder* priv = static_cast<NestedValueHolder*>(JSObjectGetPrivate(object));
+    if( priv == NULL || priv->obj == NULL )
+        throw TypeMismatchException("Not NestedValue Type");
+    return priv->obj;
+}
+
+JSObjectRef JSNestedValue::makeJSObject(JSContextRef ctx,  boost::shared_ptr < NestedValue > native){
+    NestedValueHolder *priv = new NestedValueHolder;
+    priv->obj = native;
+    JSObjectRef obj = JSObjectMake(ctx, getClassRef(), priv);
+    return obj;
+}
+
+JSObjectRef JSNestedValue::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        
+        boost::shared_ptr<NestedValue> native( new NestedValue(validator.toLong(0), validator.toString(1).c_str()) );
+        JSObjectRef obj = makeJSObject(ctx, native);
+        JSUtil::setProperty(ctx, obj, "constructor", constructor, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete|kJSPropertyAttributeDontEnum);
+        return obj;
+    }catch( const BasePlatformException &err){
+        JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(ctx, err);
+        *exception = error;
+        return error;
+    }
+}
+
+void JSNestedValue::initialize(JSContextRef ctx, JSObjectRef object)
+{
+    printf("JSNestedValue::initialize()\n");
+}
+
+void JSNestedValue::finalize(JSObjectRef object)
+{
+    printf("JSNestedValue::finalize()\n");
+    NestedValueHolder * priv = static_cast<NestedValueHolder*>(JSObjectGetPrivate(object));
+    if( priv ){
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSNestedValue::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception){
+    printf("JSNestedValue::getProperty()\n");
+    NestedValueHolder* priv = static_cast<NestedValueHolder*>(JSObjectGetPrivate(object));
+    
+    string name = JSUtil::JSStringToString(context, propertyName);
+    if( name == "Number" ){
+        return JSUtil::toJSValueRef(context, priv->obj->getNumber());
+    }else if( name == "Message"){
+        return JSUtil::toJSValueRef(context, priv->obj->getMessage());
+    }
+    return NULL;
+}
+
+bool JSNestedValue::setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception){
+    printf("JSNestedValue::setProperty()\n");
+    NestedValueHolder* priv = static_cast<NestedValueHolder*>(JSObjectGetPrivate(object));
+    string name = JSUtil::JSStringToString(context, propertyName);
+    try{
+        JSValueRef values[1] = { value };
+        ArgumentValidator validator(context, 1, values);
+        if( name == "Number" ){
+            priv->obj->setNumber( validator.toLong(0));
+            return true;
+        }else if( name == "Message"){
+            priv->obj->setMessage( validator.toString(0));
+            return true;
+        }
+    }catch( const BasePlatformException& err){
+        printf("Silently error\n"); 
+        return true;
+    }
+    return false;
+}
+
+
+JSValueRef JSNestedValue::print(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    printf("JSNestedValue::print()\n");
+    NestedValueHolder* priv = static_cast<NestedValueHolder*>(JSObjectGetPrivate(thisObject));
+    if( priv && priv->obj){
+        printf("Number : %d , Message: %s\n" , priv->obj->getNumber(), priv->obj->getMessage().c_str());
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+
+} // Reference
+} // TizenApis
+
diff --git a/src/RefImpl/JSNestedValue.h b/src/RefImpl/JSNestedValue.h
new file mode 100755 (executable)
index 0000000..a9ed474
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _REFIMPL_JS_NESTEDVALUE_H_
+#define _REFIMPL_JS_NESTEDVALUE_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+#include <boost/shared_ptr.hpp>
+
+namespace DeviceAPI {
+namespace Reference {
+
+class NestedValue;
+
+struct NestedValueHolder{
+    boost::shared_ptr<NestedValue> obj;
+};
+
+class JSNestedValue
+{
+  public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef makeJSObject(JSContextRef ctx, boost::shared_ptr<NestedValue> native);
+    static boost::shared_ptr<NestedValue> getNative(JSContextRef ctx, JSValueRef value);
+    static JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+  private:
+
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+    static JSStaticFunction m_function[];
+    static JSStaticValue m_property[];
+
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+       static bool setProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);
+
+    static JSValueRef print(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+};
+
+}
+}
+
+#endif /* _REFIMPL_JS_NESTEDVALUE_H_ */
+
+
diff --git a/src/RefImpl/JSRefImplManager.cpp b/src/RefImpl/JSRefImplManager.cpp
new file mode 100755 (executable)
index 0000000..f465d91
--- /dev/null
@@ -0,0 +1,596 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <SecurityExceptions.h>
+#include <CommonsJavaScript/Converter.h>
+#include <GlobalContextManager.h>
+#include <ArgumentValidator.h>
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include <MultiCallbackUserData.h>
+#include <boost/shared_ptr.hpp>
+#include <string>
+#include <vector>
+#include <JSArray.h>
+
+#include "TimeTracer.h"
+#include "JSRefImplManager.h"
+#include "RefImplManager.h"
+#include "JSSub.h"
+#include "JSSuper.h"
+#include "Sub.h"
+#include "NestedValue.h"
+#include "JSNestedValue.h"
+
+using namespace std;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+
+namespace DeviceAPI {
+namespace Reference {
+
+JSClassRef JSRefImplManager::m_jsClassRef = NULL;
+
+JSClassDefinition JSRefImplManager::m_jsClassInfo = {
+    0,                                       // current (and only) version is 0
+    kJSClassAttributeNone,        //attributes
+    "RefImplManager",                        //class name
+    NULL,                                 // parent class
+    JSRefImplManager::m_property,                                 //static values
+    JSRefImplManager::m_function,     // static functions
+    JSRefImplManager::initialize,         // initialize
+    JSRefImplManager::finalize,          //finalize
+    NULL,                                //hasProperty
+    JSRefImplManager::getNormalProperty,   //getProperty
+    JSRefImplManager::setNormalProperty,  //setProperty
+    NULL,                                //deleteProperty
+    NULL,                                //getPropertyNames
+    NULL,                               // callAsConstructor
+    NULL,                               // constructor
+    NULL,
+    NULL // convertToType
+};
+
+JSStaticValue JSRefImplManager::m_property[] = {
+       { "Number", getReadOnlyNumber, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+       { "Sub", getReadOnlySub, NULL, kJSPropertyAttributeNone|kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete},
+       { 0, 0, 0, 0 }
+};
+
+
+
+JSStaticFunction JSRefImplManager::m_function[] = {
+    { "syncToSync", JSRefImplManager::syncToSync, kJSPropertyAttributeNone },
+    { "syncToAsync", JSRefImplManager::syncToAsync, kJSPropertyAttributeNone },
+    { "asyncToAsync", JSRefImplManager::asyncToAsync, kJSPropertyAttributeNone },
+    { "addListener", JSRefImplManager::addListener, kJSPropertyAttributeNone },
+    { "removeListener", JSRefImplManager::removeListener, kJSPropertyAttributeNone },
+    { "fire", JSRefImplManager::fire, kJSPropertyAttributeNone },
+    { "argtest", JSRefImplManager::argtest, kJSPropertyAttributeNone },
+    { "arraytest", JSRefImplManager::arraytest, kJSPropertyAttributeNone },
+    { "isSuper", JSRefImplManager::isSuper, kJSPropertyAttributeNone },
+    { "isSub", JSRefImplManager::isSub, kJSPropertyAttributeNone },
+    { "setCallback", JSRefImplManager::setCallback, kJSPropertyAttributeNone },
+    { "unsetCallback", JSRefImplManager::unsetCallback, kJSPropertyAttributeNone },
+    { "fireCallback", JSRefImplManager::fireCallback, kJSPropertyAttributeNone },
+    { "callbackObjectTest", JSRefImplManager::callbackObjectTest, kJSPropertyAttributeNone },
+    { "updateNumber", JSRefImplManager::updateNumber, kJSPropertyAttributeNone },
+    { "updateSub", JSRefImplManager::updateSub, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSRefImplManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSRefImplManager::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+void JSRefImplManager::initialize(JSContextRef ctx, JSObjectRef object)
+{
+       TIME_TRACER_INIT();
+}
+
+void JSRefImplManager::finalize(JSObjectRef object)
+{
+       TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"RefImpl");
+       TIME_TRACER_RELEASE();
+}
+
+
+JSValueRef JSRefImplManager::getReadOnlyNumber(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception){
+    return RefImplManager::getInstance()->mLocalProperty.getProperty(context,propertyName);
+}
+
+JSValueRef JSRefImplManager::getReadOnlySub(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception){
+    return RefImplManager::getInstance()->mLocalProperty.getProperty(context,propertyName);
+}
+
+JSValueRef JSRefImplManager::getNormalProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception){
+    string name = JSUtil::JSStringToString(context, propertyName);
+    if( name == "Number" )
+        return NULL;
+    if( name == "Sub")
+        return NULL;
+    return RefImplManager::getInstance()->mLocalProperty.getProperty(context,propertyName);
+}
+
+bool JSRefImplManager::setNormalProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception){
+    string name = JSUtil::JSStringToString(context, propertyName);
+    if( name == "Number" )
+        return false;
+    if( name == "Sub")
+        return false;
+    return RefImplManager::getInstance()->mLocalProperty.setProperty(context,propertyName, value);
+}
+
+JSValueRef JSRefImplManager::syncToSync(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+       TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+    try{
+        Converter convert(ctx);
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+
+        int a = validator.toLong(0);
+        int b = validator.toLong(1);
+        int result = RefImplManager::getInstance()->syncToSync(a,b);
+       TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+        return convert.toJSValueRef(result);
+    }catch( const TypeMismatchException& err ){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }catch( const ConversionException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception,  "TypeMismatchError" , "can't convert to int");    
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSRefImplManager::syncToAsync(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+       TIME_TRACER_ITEM_BEGIN(__FUNCTION__, 1);
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+
+        int a = validator.toLong(0);
+        int b = validator.toLong(1);
+        RefCallbackUserData *callback = new RefCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(ctx),a,b);
+        callback->setSuccessCallback(validator.toFunction(2));
+        callback->setErrorCallback(validator.toFunction(3, true));
+
+        RefImplManager::getInstance()->syncToAsync(callback);
+        
+    }catch( const TypeMismatchException& err ){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+       TIME_TRACER_ITEM_END(__FUNCTION__, 1);
+       TIME_TRACER_EXPORT_REPORT();
+       TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"RefImpl");
+    return JSValueMakeUndefined(ctx);
+
+}
+
+JSValueRef JSRefImplManager::asyncToAsync(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        int a = validator.toLong(0);
+        int b = validator.toLong(1);
+        RefCallbackUserData *callback = new RefCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(ctx),a,b);
+        callback->setSuccessCallback(validator.toFunction(2));
+        callback->setErrorCallback(validator.toFunction(3, true));
+
+        RefImplManager::getInstance()->asyncToAsync(callback);
+
+    }catch( const TypeMismatchException& err ){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+
+    return JSValueMakeUndefined(ctx);
+
+}
+
+JSValueRef JSRefImplManager::argtest(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        string tocheck = validator.toString(0);
+
+        if( validator.isOmitted(0) || validator.isNull(0)){
+            printf("argument is omitted\n");
+        }
+
+        if( tocheck == "Boolean"){
+            bool value = validator.toBool(1);
+            printf("arg[1] = %d\n", value);
+            return JSUtil::toJSValueRef(ctx, value);
+        }
+        else if( tocheck == "Long"){
+            long value = validator.toLong(1);
+            printf("arg[1] = %ld\n", value);
+            return JSUtil::toJSValueRef(ctx, value);
+        }
+        else if( tocheck == "ULong"){
+            unsigned long value = validator.toULong(1);
+            printf("arg[1] = %lu\n", value);
+            return JSUtil::toJSValueRef(ctx, value);
+        }
+        else if( tocheck == "ULongLong"){
+            unsigned long long value = validator.toULongLong(1);
+            printf("arg[1] = %llu\n", value);
+            return JSUtil::toJSValueRef(ctx, value);
+        }
+        else if( tocheck == "Byte"){
+            signed char value = (int)validator.toByte(1);
+            printf("arg[1] = %d\n", value);
+            return JSUtil::toJSValueRef(ctx, value);
+        }
+        else if( tocheck == "Octet"){
+            unsigned char value = (int)validator.toOctet(1);
+            printf("arg[1] = %d\n", value);
+            return JSUtil::toJSValueRef(ctx, value);
+        }
+        else if( tocheck == "String"){
+            string value = validator.toString(1);
+            printf("arg[1] = %s\n", value.c_str());
+            return JSUtil::toJSValueRef(ctx, value);
+        }else if( tocheck == "Object"){
+            JSObjectRef value = validator.toObject(1);
+            printf("arg[1] = %p\n", value);
+            return value;
+        }else if( tocheck == "Date"){
+            time_t value = validator.toTimeT(1);
+            printf("arg[1] = %ld\n", value);
+            return JSUtil::makeDateObject(ctx, value);
+        }else if( tocheck == "Double" ){
+            double value = validator.toDouble(1);
+            printf("arg[1] = %f\n", value);
+            return JSUtil::toJSValueRef(ctx, value);
+        }else if( tocheck == "Function"){
+            JSObjectRef value = validator.toFunction(1);
+            printf("arg[1] = %p\n", value);
+            return value;
+        }else if( tocheck == "Array"){
+            JSObjectRef value = validator.toArrayObject(1);
+            printf("arg[1] = %p\n", value);
+            return value;
+        }else{
+            printf("usage: argtest([Long|String|Object|Date|Double|Function], ...)\n");
+            return JSUtil::toJSValueRef(ctx, "usage: argtest([Long|String|Object|Date|Double|Function], ...)");
+        }
+    }catch( const TypeMismatchException& err ){
+        printf("TypeMismatch exception %s : %s\n", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef makeJSBool(JSContextRef ctx, bool v){
+    return JSUtil::toJSValueRef(ctx, v);
+}
+
+JSValueRef makeNestedValue(JSContextRef ctx,  boost::shared_ptr < NestedValue > native){
+    return JSNestedValue::makeJSObject(ctx, native);
+}
+
+JSValueRef JSRefImplManager::arraytest(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        string type = validator.toString(0);
+        JSObjectRef jsArray = validator.toArrayObject(1, true);
+        if( type == "String" && jsArray != NULL){
+            JSStringArray receivedArray(ctx, jsArray);
+
+            // basic getting test
+            for( unsigned int i = 0 ; i < receivedArray.size() ; i++){
+                string element = receivedArray[i];
+                printf("received array[%d] = %s\n", i, element.c_str());
+            }
+
+            // JSArray to JSArray Copy test
+            JSStringArray copyTest(ctx);
+            copyTest = receivedArray;
+
+            for( unsigned int i = 0 ; i < copyTest.size() ; i++){
+                string element = copyTest[i];
+                printf("copyTest array[%d] = %s\n", i, element.c_str());
+            }
+
+            // to Native Vector converting test
+            vector<string> tmp = receivedArray;
+            for( unsigned int i = 0 ; i < tmp.size() ; i++){
+                printf("to Native Vector [%d] = %s\n", i, tmp[i].c_str());
+            }
+
+            //Copy from vector
+            vector<string> aa;
+            aa.push_back("one");
+            aa.push_back("two");
+            aa.push_back("three");
+            JSStringArray newArray(ctx);
+            newArray = aa;
+            for( unsigned int i = 0 ; i < newArray.size() ; i++){
+                string element = newArray[i];
+                printf("Copy from Vector[%d] = %s\n", i, element.c_str());
+            }
+
+            // Modification test
+            newArray[newArray.size()] = "last";
+            newArray[0] = "zero";
+            printf("Modification test\n");
+            printf("except:zero,two,three,last\n");
+
+            return newArray;
+        }
+        else if( type == "Long" && jsArray != NULL ){
+            JSLongArray receivedArray(ctx, jsArray);
+
+            //Basic getting test
+            for( unsigned int i = 0 ; i < receivedArray.size() ; i++){
+                long v = receivedArray[i];
+                printf("received array[%d] = %d\n", i, v );
+            }
+
+            // JSArray to JSArray Copy test
+            JSLongArray copyTest(ctx);
+            copyTest = receivedArray;
+
+            for( unsigned int i = 0 ; i < copyTest.size() ; i++){
+                long v = copyTest[i];
+                printf("copyTest array[%d] = %d\n", i, v);
+            }
+
+            // to Native Vector converting test
+            vector<long> tmp = receivedArray;
+            for( unsigned int i = 0 ; i < tmp.size() ; i++){
+                printf("to Native Vector [%d] = %d\n", i, tmp[i]);
+            }
+
+            //Copy from vector
+            vector<long> aa;
+            aa.push_back(1);
+            aa.push_back(2);
+            aa.push_back(3);
+            JSLongArray newArray(ctx);
+            newArray = aa;
+            for( unsigned int i = 0 ; i < newArray.size() ; i++){
+                long v = newArray[i];
+                printf("Copy from Vector[%d] = %d\n", i, v);
+            }
+
+            // Modification test
+            newArray[newArray.size()] = 99;
+            newArray[0] = 0;
+            printf("Modification test\n");
+            printf("except:0,2,3,99\n");
+
+            return newArray;
+        }
+        else if( type == "Boolean" && jsArray != NULL ){
+            JSArray<bool> receivedArray(ctx, jsArray, JSUtil::JSValueToBoolean, makeJSBool);
+
+            //Basic getting test
+            for( unsigned int i = 0 ; i < receivedArray.size() ; i++){
+                printf("received array[%d] = %s\n", i, receivedArray[i] ? "true" : "false" );
+            }
+
+            // JSArray to JSArray Copy test
+            JSArray<bool> copyTest(ctx,  JSUtil::JSValueToBoolean, makeJSBool);
+            copyTest = receivedArray;
+
+            for( unsigned int i = 0 ; i < copyTest.size() ; i++){
+                printf("copyTest array[%d] = %s\n", i, copyTest[i] ? "true" : "false" );
+            }
+
+            // to Native Vector converting test
+            vector<bool> tmp = receivedArray;
+            for( unsigned int i = 0 ; i < tmp.size() ; i++){
+                printf("to Native Vector[%d] = %s\n", i, tmp[i] ? "true" : "false" );
+            }
+
+            //Copy from vector
+            vector<bool> aa;
+            aa.push_back(true);
+            aa.push_back(false);
+            aa.push_back(true);
+            JSArray<bool> newArray(ctx,  JSUtil::JSValueToBoolean, makeJSBool);
+            newArray = aa;
+            for( unsigned int i = 0 ; i < newArray.size() ; i++){
+                printf("Copy from Vector[%d] = %s\n", i, newArray[i] ? "true" : "false" );
+            }
+
+            // Modification test
+            newArray[newArray.size()] = true;
+            newArray[0] = false;
+            printf("Modification test\n");
+            printf("except:false,false,true,false\n");
+            return newArray;
+
+        }
+        else if( type == "NestedValue" && jsArray != NULL ){
+            JSArray<boost::shared_ptr<NestedValue>> receivedArray(ctx, jsArray, JSNestedValue::getNative, makeNestedValue);
+            for( unsigned int i = 0 ; i< receivedArray.size() ; i++){
+                boost::shared_ptr<NestedValue> ptr = receivedArray[i];
+                ptr->print();
+            }
+            JSArray<boost::shared_ptr<NestedValue>> newArray(ctx, JSNestedValue::getNative, makeNestedValue);
+            newArray = receivedArray;
+            newArray[0] = boost::shared_ptr<NestedValue>(new NestedValue(0, "newAdded!"));
+            for( unsigned int i = 0 ; i< newArray.size() ; i++){
+                boost::shared_ptr<NestedValue> ptr = newArray[i];
+                ptr->print();
+            }
+            return newArray;
+        }
+        else{
+            printf("usage: arraytest([Long|String|Boolean], array)\n");
+            return JSUtil::toJSValueRef(ctx, "usage: arraytest([Long|String|Boolean], array)");
+        }
+        return JSValueMakeUndefined(ctx);
+    }catch( const TypeMismatchException& err ){
+        printf("TypeMismatch exception %s : %s\n", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }catch( const BasePlatformException& err){
+        printf("exception %s : %s\n", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+
+}
+
+JSValueRef JSRefImplManager::addListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        JSObjectRef fun = validator.toFunction(0);
+        boost::shared_ptr<CallbackUserData> callback(new CallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(ctx)));
+        callback->setSuccessCallback(fun);
+        long id = RefImplManager::getInstance()->addListener(callback);
+        return JSUtil::toJSValueRef(ctx, id);
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSRefImplManager::removeListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        int id = validator.toLong(0);
+        RefImplManager::getInstance()->removeListener(id);
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSRefImplManager::fire(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    RefImplManager::getInstance()->fireListener();
+    return JSValueMakeUndefined(ctx);
+}
+
+
+
+JSValueRef JSRefImplManager::isSuper(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        JSObjectRef test = validator.toObject(0);
+        if( JSValueIsObjectOfClass(ctx, test, JSSuper::getClassRef()) )
+            return JSUtil::toJSValueRef(ctx, true);
+        else
+            return JSUtil::toJSValueRef(ctx, false);
+    }catch( const BasePlatformException& err){
+        printf("exception %s %s\n", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSRefImplManager::isSub(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        JSObjectRef test = validator.toObject(0);
+        if( JSValueIsObjectOfClass(ctx, test, JSSub::getClassRef()) )
+            return JSUtil::toJSValueRef(ctx, true);
+        else
+            return JSUtil::toJSValueRef(ctx, false);
+    }catch( const BasePlatformException& err){
+        printf("exception %s %s\n", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSRefImplManager::setCallback(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        JSObjectRef jsCallbackObj = validator.toObject(0);
+        boost::shared_ptr<MultiCallbackUserData> callback(new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(ctx), jsCallbackObj));
+        RefImplManager::getInstance()->setCallbackObject(GlobalContextManager::getInstance()->getGlobalContext(ctx), callback);
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+JSValueRef JSRefImplManager::unsetCallback(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    RefImplManager::getInstance()->unsetCallbackObject(GlobalContextManager::getInstance()->getGlobalContext(ctx));
+    return JSValueMakeUndefined(ctx);
+}
+JSValueRef JSRefImplManager::fireCallback(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        string functionName= validator.toString(0);
+        RefImplManager::getInstance()->namedCallbackFire(GlobalContextManager::getInstance()->getGlobalContext(ctx), functionName.c_str());
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSRefImplManager::callbackObjectTest(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        printf("validator.toCallbackObject(0, true, \"fun1\", \"fun2\", \"fun3\", NULL);\n");
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        JSObjectRef obj = validator.toCallbackObject(0, true, "fun1", "fun2", "fun3", NULL);
+        printf("returnd obj = %p\n", obj);
+    }catch( const BasePlatformException& err){
+        printf("exception %s %s\n", err.getName().c_str(), err.getMessage().c_str());
+    }
+    try{
+        printf("validator.toCallbackObject(0, false, \"fun1\", \"fun2\", \"fun3\", NULL);\n");
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        JSObjectRef obj = validator.toCallbackObject(0, false, "fun1", "fun2", "fun3", NULL);
+        printf("returnd obj = %p\n", obj);
+    }catch( const BasePlatformException& err){
+        printf("exception %s %s\n", err.getName().c_str(), err.getMessage().c_str());
+    }
+
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSRefImplManager::updateNumber(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        int readonlyValue= validator.toLong(0);
+        RefImplManager::getInstance()->mLocalProperty.setProperty(ctx, "Number", (double)readonlyValue);
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSRefImplManager::updateSub(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    try{
+        ArgumentValidator validator(ctx, argumentCount, arguments);
+        JSObjectRef o = validator.toObject(0, JSSub::getClassRef());
+        RefImplManager::getInstance()->mLocalProperty.setProperty(ctx, "Sub", o);
+    }catch( const BasePlatformException& err){
+        return JSWebAPIErrorFactory::postException(ctx, exception, err);
+    }
+    return JSValueMakeUndefined(ctx);
+}
+
+} // Reference
+} // TizenApis
+
diff --git a/src/RefImpl/JSRefImplManager.h b/src/RefImpl/JSRefImplManager.h
new file mode 100644 (file)
index 0000000..97084d0
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifndef _JS_REFIMPL_MANAGER_H_
+#define _JS_REFIMPL_MANAGER_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Reference {
+
+class JSRefImplManager
+{
+  public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+  private:
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+
+    static JSStaticFunction m_function[];
+    static JSStaticValue m_property[];
+
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getReadOnlyNumber(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    static JSValueRef getReadOnlySub(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    static JSValueRef getNormalProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+       static bool setNormalProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef value, JSValueRef* exception);
+
+    static JSValueRef syncToSync(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef syncToAsync(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef asyncToAsync(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef argtest(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef arraytest(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef callbackObjectTest(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+
+    
+    static JSValueRef addListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef removeListener(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef fire(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+    static JSValueRef isSuper(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef isSub(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+    static JSValueRef setCallback(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef unsetCallback(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef fireCallback(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+    static JSValueRef updateNumber(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef updateSub(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+
+
+};
+
+}
+}
+
+#endif /* _JS_REFIMPL_MANAGER_H_ */
+
+
diff --git a/src/RefImpl/JSSub.cpp b/src/RefImpl/JSSub.cpp
new file mode 100755 (executable)
index 0000000..6534769
--- /dev/null
@@ -0,0 +1,101 @@
+#include "JSSuper.h"
+#include "JSSub.h"
+
+#include <ArgumentValidator.h>
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include "Sub.h"
+
+using namespace DeviceAPI::Common;
+
+
+namespace DeviceAPI {
+namespace Reference {
+
+JSClassRef JSSub::m_jsClassRef = NULL;
+
+JSClassDefinition JSSub::m_jsClassInfo = {
+    0, // current (and only) version is 0
+    kJSClassAttributeNone, //attributes
+    "Sub", //class name
+    JSSuper::getClassRef(), // parent class
+    NULL, //static values
+    JSSub::m_function, // static functions
+    JSSub::initialize, // initialize
+    JSSub::finalize, //finalize
+    NULL, //hasProperty
+    NULL, //getProperty
+    NULL, //setProperty
+    NULL, //deleteProperty
+    NULL, //getPropertyNames
+    NULL, // callAsFunction
+    NULL, // constructor
+    NULL,
+    NULL // convertToType
+};
+
+
+JSStaticFunction JSSub::m_function[] = {
+    { "extend", JSSub::extend, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+
+const JSClassRef JSSub::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+const JSClassDefinition* JSSub::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+JSObjectRef JSSub::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    printf("JSSub::constructor()\n");
+    ArgumentValidator validator(ctx, argumentCount, arguments);
+    try{
+        int a = validator.toLong(0);
+        if( a == 2)
+            throw InvalidValuesException("2 is invalid value");
+    }catch(const BasePlatformException& err){
+        JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(ctx, err);
+        *exception = error;
+        return error;
+    }
+    Sub *priv = new Sub();
+    JSObjectRef obj = JSObjectMake(ctx, getClassRef(), priv);
+    JSUtil::setProperty(ctx, obj, "constructor", constructor, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete|kJSPropertyAttributeDontEnum);
+    return obj;
+}
+
+void JSSub::initialize(JSContextRef ctx, JSObjectRef object)
+{
+    printf("JSSub::initialize()\n");
+}
+
+void JSSub::finalize(JSObjectRef object)
+{
+    printf("JSSub::finalize()\n");
+    Sub * priv = static_cast<Sub*>(JSObjectGetPrivate(object));
+    if( priv ){
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSValueRef JSSub::extend(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    printf("JSSub::extend()\n");
+    Sub * priv = static_cast<Sub*>(JSObjectGetPrivate(thisObject));
+    if( priv )
+        priv->extend();
+    return JSValueMakeUndefined(ctx);
+}
+
+
+} // Reference
+} // TizenApis
+
diff --git a/src/RefImpl/JSSub.h b/src/RefImpl/JSSub.h
new file mode 100755 (executable)
index 0000000..96e5dd8
--- /dev/null
@@ -0,0 +1,39 @@
+#ifndef _JS_SUB_H_
+#define _JS_SUB_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Reference {
+
+class JSSub
+{
+  public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+  private:
+
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+    static JSStaticFunction m_function[];
+
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef extend(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+};
+
+}
+}
+
+#endif /* _JS_SUB_H_ */
+
+
+
diff --git a/src/RefImpl/JSSuper.cpp b/src/RefImpl/JSSuper.cpp
new file mode 100755 (executable)
index 0000000..2fe9503
--- /dev/null
@@ -0,0 +1,97 @@
+#include "JSSuper.h"
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include "Super.h"
+
+using namespace DeviceAPI::Common;
+
+
+
+namespace DeviceAPI {
+namespace Reference {
+
+JSClassRef JSSuper::m_jsClassRef = NULL;
+
+JSClassDefinition JSSuper::m_jsClassInfo = {
+    0, // current (and only) version is 0
+    kJSClassAttributeNone, //attributes
+    "Super", //class name
+    NULL, // parent class
+    NULL, //static values
+    JSSuper::m_function, // static functions
+    JSSuper::initialize, // initialize
+    JSSuper::finalize, //finalize
+    NULL, //hasProperty
+    NULL, //getProperty
+    NULL, //setProperty
+    NULL, //deleteProperty
+    NULL, //getPropertyNames
+    NULL, // callAsFunction
+    NULL, // constructor
+    NULL, //hasInstance
+    NULL // convertToType
+};
+
+
+JSStaticFunction JSSuper::m_function[] = {
+    { "base", JSSuper::base, kJSPropertyAttributeNone },
+    { "override", JSSuper::override, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSSuper::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_jsClassInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSSuper::getClassInfo()
+{
+    return &m_jsClassInfo;
+}
+
+void JSSuper::initialize(JSContextRef ctx, JSObjectRef object)
+{
+    printf("JSSuper::initialize()\n");
+}
+
+void JSSuper::finalize(JSObjectRef object)
+{
+    printf("JSSuper::finalize()\n");
+    Super * priv = static_cast<Super*>(JSObjectGetPrivate(object));
+    if( priv ){
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSObjectRef JSSuper::constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    printf("JSSuper::constructor()\n");
+    Super * priv = new Super();
+    JSObjectRef obj = JSObjectMake(ctx, getClassRef(), priv);
+    JSUtil::setProperty(ctx, obj, "constructor", constructor, kJSPropertyAttributeReadOnly|kJSPropertyAttributeDontDelete|kJSPropertyAttributeDontEnum);
+    return obj;
+}
+
+JSValueRef JSSuper::base(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    printf("JSSuper::base()\n");
+    Super * priv = static_cast<Super*>(JSObjectGetPrivate(thisObject));
+    if( priv )
+        priv->base();
+    return JSValueMakeUndefined(ctx);
+}
+
+JSValueRef JSSuper::override(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception){
+    printf("JSSuper::override()\n");
+    Super * priv = static_cast<Super*>(JSObjectGetPrivate(thisObject));
+    priv->override();
+    return JSValueMakeUndefined(ctx);
+}
+
+
+
+} // Reference
+} // TizenApis
+
diff --git a/src/RefImpl/JSSuper.h b/src/RefImpl/JSSuper.h
new file mode 100755 (executable)
index 0000000..5345b4a
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _JS_SUPER_H_
+#define _JS_SUPER_H_
+
+#include <string>
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace Reference {
+
+class JSSuper
+{
+  public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef constructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+  private:
+
+    static JSClassDefinition m_jsClassInfo;
+    static JSClassRef m_jsClassRef;
+    static JSStaticFunction m_function[];
+
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+    static JSValueRef base(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+    static JSValueRef override(JSContextRef ctx, JSObjectRef object, JSObjectRef thisObject, size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+
+};
+
+}
+}
+
+#endif /* _JS_SUPER_H_ */
+
+
+
diff --git a/src/RefImpl/NestedValue.cpp b/src/RefImpl/NestedValue.cpp
new file mode 100755 (executable)
index 0000000..24856b2
--- /dev/null
@@ -0,0 +1,38 @@
+#include "NestedValue.h"
+
+using namespace std;
+
+namespace DeviceAPI {
+namespace Reference {
+
+NestedValue::NestedValue():mNumber(0){
+}
+
+NestedValue::NestedValue(long number, const string &message ):mNumber(number), mMessage(message){
+}
+
+NestedValue::~NestedValue(){
+}
+
+long NestedValue::getNumber() const{
+    return mNumber;
+}
+
+const string& NestedValue::getMessage() const{
+    return mMessage;
+}
+
+void NestedValue::setNumber(long v){
+    mNumber = v;
+}
+
+void NestedValue::setMessage(const  string & msg){
+    mMessage = msg;
+}
+
+void NestedValue::print(){
+    printf("%d)%s\n", mNumber, mMessage.c_str());
+}
+
+}
+}
diff --git a/src/RefImpl/NestedValue.h b/src/RefImpl/NestedValue.h
new file mode 100755 (executable)
index 0000000..3be2be6
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef _REFIMPL_NESTEDVALUE_H_
+#define _REFIMPL_NESTEDVALUE_H_
+
+#include <string>
+
+namespace DeviceAPI {
+namespace Reference {
+
+class NestedValue{
+public:
+    NestedValue();
+    NestedValue(long number, const std::string &message);
+    virtual ~NestedValue();
+    long getNumber() const;
+    const std::string& getMessage() const;
+
+    void setNumber(long v);
+    void setMessage(const std::string &msg);
+    void print();
+
+private:
+    long mNumber;
+    std::string mMessage;
+    
+};
+
+}
+}
+
+#endif //_REFIMPL_NESTEDVALUE_H_
diff --git a/src/RefImpl/RefImplManager.cpp b/src/RefImpl/RefImplManager.cpp
new file mode 100755 (executable)
index 0000000..9723a4a
--- /dev/null
@@ -0,0 +1,190 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. 
+ */
+
+#include "RefImplManager.h"
+#include "mock.h"
+#include <Ecore.h>
+#include <CommonsJavaScript/Converter.h>
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+
+
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace DeviceAPI::Common;
+using namespace std;
+
+namespace DeviceAPI {
+namespace Reference{
+
+static void* workerThread(void *data);
+//static void workerThread(void *data, Ecore_Thread *thread);
+static Eina_Bool jobCompleteCB(void *data);
+//static void jobCompleteCB(void *data, Ecore_Thread *thread);
+static void platformCB( int result , void *user_data);
+
+//static void workerThread(void *data, Ecore_Thread *thread){
+static void* workerThread(void *data){
+    RefCallbackUserData * callback = static_cast<RefCallbackUserData*>(data);
+    callback->result = mock_delayed_sync_function(callback->a, callback->b);
+    ecore_idler_add(jobCompleteCB, data);
+    return NULL;
+}
+
+//static void jobCompleteCB(void *data, Ecore_Thread *thread){
+static Eina_Bool jobCompleteCB(void *data){
+    RefCallbackUserData * callback = static_cast<RefCallbackUserData*>(data);
+    Converter convert(callback->getContext());
+    if( callback->result == 44 ){
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::IO_ERROR, "44 is I/O Error");
+        callback->callErrorCallback(errobj);
+    }else{
+        JSValueRef result = convert.toJSValueRef(callback->result);
+        callback->callSuccessCallback(result);
+    }
+    delete callback;
+    return false;
+}
+
+int RefImplManager::syncToSync(int a, int b){
+    if( a == 5 )
+        throw InvalidValuesException("5 is not allowed");
+
+    int ret = mock_sync_function(a,b);
+    if( ret == 44 )
+        throw IOException("44 is I/O error");
+    return ret;
+}
+
+void RefImplManager::syncToAsync( RefCallbackUserData * callback ){
+    if( callback->a == 5 )
+        throw InvalidValuesException("5 is not allowed");
+    //Ecore_Thread *tid = ecore_thread_run( workerThread, jobCompleteCB, NULL, callback);
+    pthread_t thread;
+    pthread_create(&thread, NULL, workerThread, callback);
+    pthread_detach(thread);
+}
+
+
+static void platformCB( int result , void *user_data){
+    RefCallbackUserData * callback = static_cast<RefCallbackUserData*>(user_data);
+    Converter convert(callback->getContext());
+    if( result == 44 ){
+        JSObjectRef errobj = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::IO_ERROR, "44 is I/O Error");
+        callback->callErrorCallback(errobj);
+    }else{
+        JSValueRef jsresult = convert.toJSValueRef(result);
+        callback->callSuccessCallback(jsresult);
+    }
+    delete callback;
+}
+
+void RefImplManager::asyncToAsync( RefCallbackUserData * callback ){
+    if( callback->a == 5 )
+        throw InvalidValuesException("5 is not allowed");
+
+    mock_async_function(callback->a, callback->b, platformCB, callback);
+}
+
+
+RefImplManager* RefImplManager::getInstance(){
+    static RefImplManager instance;
+    return &instance;
+}
+
+int RefImplManager::onFire(void* user_data){
+    RefImplManager* obj = static_cast<RefImplManager*>(user_data);
+    obj->broadCast();
+    return false;
+}
+
+void RefImplManager::fireListener(){
+    g_idle_add(onFire, this);
+}
+
+int RefImplManager::addListener(boost::shared_ptr<CallbackUserData> callback){
+    int id = mCounter++;
+    mListenerList.insert(listenerT(id, callback));
+    return id;
+}
+
+void RefImplManager::removeListener(int id){
+    map<int, boost::shared_ptr<Common::CallbackUserData>>::iterator itr;
+    itr = mListenerList.find(id);
+    if( itr != mListenerList.end() ){
+        mListenerList.erase(itr);
+    }
+}
+
+void RefImplManager::broadCast(){
+    map<int, boost::shared_ptr<Common::CallbackUserData>> tmplist(mListenerList);
+    map<int, boost::shared_ptr<Common::CallbackUserData>>::iterator itr;
+    itr = tmplist.begin();
+    while( itr != tmplist.end() ){
+        boost::shared_ptr<Common::CallbackUserData> callback = (*itr).second;
+        callback->callSuccessCallback();
+        ++itr;
+    }
+}
+
+
+void RefImplManager::setCallbackObject( JSContextRef context, boost::shared_ptr<Common::MultiCallbackUserData> callback){
+    mCallbackList[context] = callback;
+}
+void RefImplManager::unsetCallbackObject( JSContextRef context ){
+    mCallbackList.erase(context);
+}
+
+struct NamedCallbackData{
+    JSContextRef context;
+    std::string name;
+    RefImplManager* obj;
+};
+
+void RefImplManager::namedCallbackFire(JSContextRef context, const char *callbackName){
+    struct NamedCallbackData * data = new NamedCallbackData();
+    data->context = context;
+    data->name = callbackName;
+    data->obj = this;
+    g_idle_add(onNamedFire, data);
+}
+
+int RefImplManager::onNamedFire(void* user_data){
+    struct NamedCallbackData * data = static_cast<NamedCallbackData*>(user_data);
+    data->obj->namedBroadCast(data->context, data->name.c_str());
+    delete data;
+    return false;
+}
+
+void RefImplManager::namedBroadCast(JSContextRef context, const char *callbackName){
+    map<JSContextRef, boost::shared_ptr<Common::MultiCallbackUserData>>::iterator itr;
+    itr = mCallbackList.find(context);
+    if( itr != mCallbackList.end() ){
+        mCallbackList[context]->invokeCallback(callbackName);
+    }
+}
+
+
+RefImplManager::RefImplManager():mCounter(0){
+}
+RefImplManager::~RefImplManager(){
+}
+
+
+
+}
+}
+
diff --git a/src/RefImpl/RefImplManager.h b/src/RefImpl/RefImplManager.h
new file mode 100755 (executable)
index 0000000..7e4da9a
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. 
+ */
+
+#ifndef _REFIMPLMANAGER_
+#define _REFIMPLMANAGER_
+
+#include <string>
+#include <stdio.h>
+#include <CallbackUserData.h>
+#include <MultiCallbackUserData.h>
+#include <boost/shared_ptr.hpp>
+#include <map>
+#include <PropertyBag.h>
+
+namespace DeviceAPI {
+namespace Reference{
+
+class RefCallbackUserData : public Common::CallbackUserData{
+    public:
+        RefCallbackUserData(JSContextRef globalCtx, int aa, int bb):CallbackUserData(globalCtx), a(aa), b(bb), result(0){}
+        int a;
+        int b;
+        int result;
+};
+
+class RefImplManager{
+    public:
+        int syncToSync(int a, int b);
+        void syncToAsync(RefCallbackUserData *callback);
+        void asyncToAsync(RefCallbackUserData *callback);
+
+        //for multiple callback
+        int addListener(boost::shared_ptr<Common::CallbackUserData> callback);
+        void removeListener(int id);
+        void fireListener();
+
+        // for single callbcak object per one global context
+        void setCallbackObject( JSContextRef context, boost::shared_ptr<Common::MultiCallbackUserData> callback);
+        void unsetCallbackObject( JSContextRef context );
+        void namedCallbackFire(JSContextRef context, const char *callbackName);
+        
+        static RefImplManager* getInstance();
+        Common::PropertyBag mLocalProperty;
+
+    private:
+        int mCounter;
+        typedef std::pair<int, boost::shared_ptr<Common::CallbackUserData>> listenerT;
+        std::map<int, boost::shared_ptr<Common::CallbackUserData>> mListenerList;
+        typedef std::pair<JSContextRef, boost::shared_ptr<Common::MultiCallbackUserData>> callbackObjectT;
+        std::map<JSContextRef, boost::shared_ptr<Common::MultiCallbackUserData>> mCallbackList;
+
+        RefImplManager();
+        ~RefImplManager();
+        static int onFire(void* user_data);
+        static int onNamedFire(void* user_data);
+        void broadCast();
+        void namedBroadCast(JSContextRef context, const char *callbackName);
+        
+};
+    
+
+
+}
+}
+
+#endif //_REFIMPLMANAGER_
+
diff --git a/src/RefImpl/Sub.cpp b/src/RefImpl/Sub.cpp
new file mode 100755 (executable)
index 0000000..2782941
--- /dev/null
@@ -0,0 +1,17 @@
+#include "Sub.h"
+#include <stdio.h>
+Sub::Sub(){
+    printf("Sub C++ constructor\n");
+}
+
+Sub::~Sub(){
+    printf("Sub C++ destroy\n");
+}
+
+void Sub::extend(){
+    printf("Sub::extend()\n");    
+}
+
+void Sub::override(){
+    printf("Sub::override()\n");
+}
diff --git a/src/RefImpl/Sub.h b/src/RefImpl/Sub.h
new file mode 100755 (executable)
index 0000000..d9e39ef
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef _SUB_H_
+#define _SUB_H_
+
+#include "Super.h"
+
+class Sub : public Super {
+public:
+    Sub();
+    virtual ~Sub();
+    void extend();
+    virtual void override();
+};
+
+#endif //_SUB_H_
+
diff --git a/src/RefImpl/Super.cpp b/src/RefImpl/Super.cpp
new file mode 100755 (executable)
index 0000000..81e47ee
--- /dev/null
@@ -0,0 +1,18 @@
+#include "Super.h"
+#include <stdio.h>
+
+
+Super::Super(){
+    printf("Super c++ constructor\n");
+}
+Super::~Super(){
+    printf("Super c++ destroy\n");
+}
+
+void Super::base(){
+    printf("Super::base()\n");
+}
+
+void Super::override(){
+    printf("Super::override()\n");
+}
diff --git a/src/RefImpl/Super.h b/src/RefImpl/Super.h
new file mode 100755 (executable)
index 0000000..21c45e1
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef _SUPER_H_
+#define _SUPER_H_
+
+class Super {
+public:
+    Super();
+    virtual ~Super();
+    void base();
+    virtual void override();
+};
+
+#endif //_SUPER_H_
\ No newline at end of file
diff --git a/src/RefImpl/config.xml b/src/RefImpl/config.xml
new file mode 100755 (executable)
index 0000000..f13ba9c
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-refimpl.so</library-name>
+    <feature-install-uri>efimpl.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/refimpl</name>
+        <device-capability>refimpl</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/RefImpl/mock.cpp b/src/RefImpl/mock.cpp
new file mode 100755 (executable)
index 0000000..c5854b8
--- /dev/null
@@ -0,0 +1,61 @@
+#include "mock.h"
+#include <Ecore.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <dlog.h>
+#include <glib.h>
+
+#undef LOG_TAG
+#define LOG_TAG "TIZEN_DEVICEAPI"
+
+
+struct worker_data{
+    int a;
+    int b;
+    async_cb callback;
+    void * user_data;
+    int result;
+};
+
+static void* worker_function(void *arg);
+static int threadsafe_function(void *arg);
+
+
+int mock_sync_function(int a, int b){
+    return a+b;
+}
+int mock_delayed_sync_function(int a, int b){
+    sleep(2);
+    return a+b;
+}
+
+
+int mock_async_function( int a, int b, async_cb callback, void *user_data){
+    pthread_t thread;
+    worker_data *data = new worker_data();
+    data->a = a;
+    data->b = b;
+    data->callback = callback;
+    data->user_data = user_data;
+    pthread_create(&thread, NULL, worker_function,  data);
+    pthread_detach(thread);
+    return 0;
+}
+
+
+static void* worker_function(void *arg){
+    static int count = 0;
+    worker_data *data = (worker_data*)arg;
+    data->result = mock_delayed_sync_function(data->a, data->b);
+    g_idle_add(threadsafe_function, data);
+    return NULL;
+}
+
+static int threadsafe_function(void *arg){
+    worker_data *data = (worker_data*)arg;
+    if( data->callback )
+        data->callback(data->result, data->user_data);
+    delete data;
+    return false;
+}
+
diff --git a/src/RefImpl/mock.h b/src/RefImpl/mock.h
new file mode 100755 (executable)
index 0000000..5711ec0
--- /dev/null
@@ -0,0 +1,8 @@
+
+typedef void (* async_cb)( int result , void *user_data);
+
+
+int mock_sync_function(int a, int b);
+int mock_delayed_sync_function(int a, int b);
+int mock_async_function(int a, int b, async_cb callback, void *user_data);
+
diff --git a/src/RefImpl/plugin_initializer.cpp b/src/RefImpl/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..12cabd1
--- /dev/null
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+#include "JSRefImplManager.h"
+#include "JSSub.h"
+#include "JSSuper.h"
+#include "JSNestedValue.h"
+#include <GlobalContextManager.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Reference {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+class_definition_options_t TizenInterfaceOptions = {
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL, // JSWidget::acquireGlobalContext,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LoggerD("[Tizen\\Power] on_widget_start_callback (" << widgetId << ")");
+
+       Try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+       } Catch (Exception) {
+               LoggerE("WrtAccess initialization failed");
+       }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LoggerD("[Tizen\\Power] on_widget_stop_callback (" << widgetId << ")");
+
+       Try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+       } Catch (Exception) {
+               LoggerE("WrtAccess deinitialization failed");
+       }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LoggerD("[Tizen\\Power] on_frame_load_callback (" << context << ")");
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LoggerD("[Tizen\\Power] on_frame_unload_callback (" << context << ")");
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "RefImpl",
+        (js_class_template_getter)JSRefImplManager::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "Sub",
+        (js_class_template_getter)DeviceAPI::Reference::JSSub::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Reference::JSSub::constructor,
+        &TizenInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "Super",
+        (js_class_template_getter)DeviceAPI::Reference::JSSuper::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Reference::JSSuper::constructor,
+        &TizenInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "NestedValue",
+        (js_class_template_getter)DeviceAPI::Reference::JSNestedValue::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Reference::JSNestedValue::constructor,
+        &TizenInterfaceOptions)
+PLUGIN_CLASS_MAP_END
+
+}
+}
+
diff --git a/src/RefImpl/test/CMakeLists.txt b/src/RefImpl/test/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..4cfb2aa
--- /dev/null
@@ -0,0 +1,26 @@
+SET(TARGET_NAME ${refimpl_target}_test)
+
+include_directories(
+  ${TOP}/Common
+  ${TOP}/RefImpl  
+  ${TOP}/Common/StandaloneConsole
+)
+
+set(CMAKE_INSTALL_RPATH
+  ${CMAKE_INSTALL_RPATH}
+  ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+  ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${refimpl_dest}
+)
+
+set(SRCS
+    main.cpp
+)
+
+ADD_EXECUTABLE(${TARGET_NAME} ${SRCS})
+
+target_link_libraries(${TARGET_NAME}
+  ${refimpl_impl}
+  ${LIBS_COMMON}
+  ${LIBS_TEST}
+)
+
diff --git a/src/RefImpl/test/main.cpp b/src/RefImpl/test/main.cpp
new file mode 100755 (executable)
index 0000000..6a5d316
--- /dev/null
@@ -0,0 +1,80 @@
+#include <stdio.h>
+#include <string.h>
+#include <JavaScriptCore/JavaScript.h>
+#include "StandaloneConsole.h"
+#include <Ecore.h>
+#include <GlobalContextManager.h>
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <pthread.h>
+#include <JSRefImplManager.h>
+#include <JSSub.h>
+#include <JSSuper.h>
+#include <JSNestedValue.h>
+
+using namespace std;
+using namespace DeviceAPI::Test;
+using namespace DeviceAPI::Common;
+using namespace DeviceAPI::Reference;
+using namespace WrtDeviceApis::Commons;
+
+
+void fun1(void *data, Ecore_Thread *thread){
+    printf("fun1 %p\n", pthread_self());
+}
+void fun2(void *data, Ecore_Thread *thread){
+    printf("fun2 %p\n", pthread_self());
+}
+
+static Eina_Bool fun3(void *data){
+    ecore_thread_run(fun1, fun2, NULL, NULL);
+    return false;
+}
+
+
+void loopQuit(void *data, Ecore_Thread *thread){
+    ecore_main_loop_quit();
+}
+
+void threadRun(void *data, Ecore_Thread *thread){
+    StandaloneConsole *console = (StandaloneConsole*)data;
+    StandaloneConsole::commandline(console);
+
+}
+
+int main(int argc, char** argv){
+
+    if (!ecore_init())
+    {
+        printf("ERROR: Cannot init Ecore!\n");
+        return -1;
+    }
+    ecore_main_loop_glib_integrate();
+
+    DPL::Log::LogSystemSingleton::Instance().SetTag("STANDALONE");
+    //DPL::Event::GetMainEventDispatcherInstance().ResetCrossEventCallHandler();
+    WrtAccessSingleton::Instance().initialize(0);
+
+
+    StandaloneConsole console;
+    console.initialize();
+    GlobalContextManager::getInstance()->addGlobalContext(console.getGlobalContext());
+    console.registModule("ref", JSRefImplManager::getClassRef(), NULL);
+    JSObjectRef Sub = JSObjectMakeConstructor(console.getGlobalContext(), JSSub::getClassRef(), JSSub::constructor);
+    JSObjectRef Super = JSObjectMakeConstructor(console.getGlobalContext(), JSSuper::getClassRef(), JSSuper::constructor);
+    JSObjectRef Nested = JSObjectMakeConstructor(console.getGlobalContext(), JSNestedValue::getClassRef(), JSNestedValue::constructor);
+    console.appendModule("Sub", Sub);
+    console.appendModule("Super", Super);
+    console.appendModule("NestedValue", Nested);
+
+    if( argc > 1 ){
+        console.RunScript(argv[1]);
+    }
+    printf("main thread = %p\n", pthread_self());
+    ecore_thread_run(threadRun, loopQuit, NULL, &console);
+
+    ecore_main_loop_begin();
+    ecore_shutdown();
+    return 0;
+}
diff --git a/src/RefImpl/test/test.js b/src/RefImpl/test/test.js
new file mode 100755 (executable)
index 0000000..1883bea
--- /dev/null
@@ -0,0 +1,52 @@
+
+if( ref.syncToSync(1,1) == 2 )
+       console.log("PASS 1");
+else
+       console.log("FAIL 1");
+       
+if( ref.syncToSync(1,2) == 3 )
+       console.log("PASS 2");
+else
+       console.log("FAIL 2");
+       
+
+try{
+       ref.syncToSync(5,1);
+       console.log("FAIL 3");
+}catch(e){
+       console.log("PASS 3");
+}      
+
+try{
+       ref.syncToSync(4,40);
+       console.log("FAIL 4");
+}catch(e){
+       console.log("PASS 4");
+}      
+
+ref.syncToAsync(1,2 ,function(r){ if(r == 3)console.log("PASS 5");else console.log("FAIL 5");}, function(e){ console.log("FAIL 5");});
+ref.syncToAsync(3,2 ,function(r){ if(r == 5)console.log("PASS 6");else console.log("FAIL 6");}, function(e){ console.log("FAIL 6");});
+
+try{
+       ref.syncToAsync(5,1, function(r){ console.log("FAIL 7"); }, function(e){ console.log("FAIL 7");});
+       console.log("FAIL 7");
+}catch(e){
+       console.log("PASS 7");
+}
+
+ref.syncToAsync(4,40 ,function(r){ console.log("FAIL 8");}, function(e){ console.log("PASS 8");});
+
+
+ref.asyncToAsync(1,2 ,function(r){ if(r == 3)console.log("PASS 9");else console.log("FAIL 9 "+r);}, function(e){ console.log("FAIL 9(2)");});
+ref.asyncToAsync(3,2 ,function(r){ if(r == 5)console.log("PASS 10");else console.log("FAIL 10 "+r);}, function(e){ console.log("FAIL 10(2)");});
+
+try{
+       ref.asyncToAsync(5,1, function(r){ console.log("FAIL 11"); }, function(e){ console.log("FAIL 11");});
+       console.log("FAIL 11");
+}catch(e){
+       console.log("PASS 11");
+}
+
+ref.asyncToAsync(4,40 ,function(r){ console.log("FAIL 12");}, function(e){ console.log("PASS 12");});
+
+
diff --git a/src/SecureElement/CMakeLists.txt b/src/SecureElement/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..f8010c0
--- /dev/null
@@ -0,0 +1,58 @@
+SET(TARGET_NAME ${secureelement_target})
+SET(DESTINATION_NAME ${secureelement_dest})
+SET(TARGET_IMPL_NAME ${secureelement_impl})
+
+IF(ENABLE_OPTIONAL_SE)
+PKG_CHECK_MODULES(platform_pkgs_secureelement REQUIRED smartcard-service smartcard-service-common)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_secureelement_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSSEService.cpp
+    JSReader.cpp
+    JSSession.cpp
+    JSChannel.cpp
+    Session.cpp
+    SEChannel.cpp
+    SEReader.cpp
+    SEService.cpp
+    SECallbackData.cpp
+    SEChangeListener.cpp
+    SEUtils.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${platform_pkgs_secureelement_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_initializer.cpp
+    plugin_config.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+ENDIF(ENABLE_OPTIONAL_SE)
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/secureelement
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/SecureElement/JSChannel.cpp b/src/SecureElement/JSChannel.cpp
new file mode 100755 (executable)
index 0000000..a5b9559
--- /dev/null
@@ -0,0 +1,297 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Logger.h>
+#include <ArgumentValidator.h>
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <GlobalContextManager.h>
+#include <TimeTracer.h>
+
+#include "JSChannel.h"
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace{
+const char* CLASS_NAME = "Channel";
+const char* CHANNEL_ISBASICCHANNEL = "isBasicChannel";
+const char* CHANNEL_FUN_CLOSE = "close";
+const char* CHANNEL_FUN_TRANSMIT = "transmit";
+const char* CHANNEL_FUN_GET_SELECT_RESPONSE = "getSelectResponse";
+}
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace DeviceAPI::Common;
+
+struct SEChannelHolder {
+    SEChannelPtr ptr;
+};
+
+JSClassDefinition JSChannel::m_classInfo =
+{
+        0,                      // version
+        kJSClassAttributeNone,  // attributes
+        CLASS_NAME,             // class name
+        NULL,                   // parent class
+        m_property,             // static values
+        m_function,             // static functions
+        initialize,             // initialize
+        finalize,               // finalize
+        NULL,                   // hasProperty
+        NULL,                   // getProperty
+        NULL,                   // setProperty
+        NULL,                   // deleteProperty
+        NULL,                   // getPropertyNames
+        NULL,                   // callAsFunction
+        NULL,                   // constructor
+        NULL,                   // hasInstance
+        NULL                    // convertToType
+};
+
+JSStaticFunction JSChannel::m_function[] = {
+        {CHANNEL_FUN_CLOSE, close, kJSPropertyAttributeNone},
+        {CHANNEL_FUN_TRANSMIT, transmit, kJSPropertyAttributeNone},
+        {CHANNEL_FUN_GET_SELECT_RESPONSE, getSelectResponse, kJSPropertyAttributeNone},
+        { 0, 0, 0}
+};
+
+JSStaticValue JSChannel::m_property[] =
+{
+        {CHANNEL_ISBASICCHANNEL, isBasicChannel, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+        { 0, 0, 0, 0 }
+};
+JSClassRef JSChannel::m_jsClassRef = JSClassCreate(JSChannel::getClassInfo());
+
+SEChannelPtr JSChannel::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SEChannelHolder* priv = static_cast<SEChannelHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSChannel::setPrivateObject(JSObjectRef object, SEChannelPtr native)
+{
+    SEChannelHolder* priv = static_cast<SEChannelHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSChannel::makeJSObject(JSContextRef context, SEChannelPtr native)
+{
+    LOGD("Entered");
+    if (!native) {
+        LOGW("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    SEChannelHolder* priv = new(std::nothrow) SEChannelHolder();
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSChannel::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSChannel::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SEChannelHolder* priv = static_cast<SEChannelHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+
+const JSClassRef JSChannel::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSChannel::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSChannel::isBasicChannel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SEChannelPtr priv = JSChannel::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->isBasicChannel());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s, %s", error.getName().c_str(),
+                error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSChannel::close(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SEChannelPtr priv = JSChannel::getPrivateObject(context, thisObject);
+        priv->close();
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("close BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("close fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "close fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSChannel::transmit(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    TransmitCallbackData *callback = NULL;
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        std::vector<unsigned char> command = validator.toUCharVector(0, false);
+
+        callback = new TransmitCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(1, false));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setCommand(UCharVectorPtr(new UCharVector(command)));
+
+        SEChannelPtr priv = JSChannel::getPrivateObject(context, thisObject);
+
+        priv->transmit(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("transmit BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("transmit fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "transmit fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+JSValueRef JSChannel::getSelectResponse(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SEChannelPtr priv = JSChannel::getPrivateObject(context, thisObject);
+        UCharVectorPtr to_ret = priv->getSelectResponse();
+        return JSUtil::toJSValueRef_<unsigned char>(context, *to_ret);
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("Error during getSelectResponse() , Name: %s, Message: %s",
+                e.getName().c_str(), e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+    catch (...) {
+        LOGE("Error during getSelectResponse()");
+        UnknownException err("Error during getSelectResponse()");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} // SecureElement
+} // DeviceAPI
diff --git a/src/SecureElement/JSChannel.h b/src/SecureElement/JSChannel.h
new file mode 100755 (executable)
index 0000000..80ddffb
--- /dev/null
@@ -0,0 +1,98 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef _TIZEN_SECUREELEMENT_JS_CHANNEL_H_
+#define _TIZEN_SECUREELEMENT_JS_CHANNEL_H_
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "SEChannel.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+class JSChannel
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef makeJSObject(JSContextRef context, SEChannelPtr native);
+
+    static SEChannelPtr getPrivateObject(JSContextRef context, JSValueRef value);
+    static void setPrivateObject(JSObjectRef object, SEChannelPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef isBasicChannel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef close(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef transmit(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getSelectResponse(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // SecureElement
+} // DeviceAPI
+
+#endif /* _TIZEN_SECUREELEMENT_JS_CHANNEL_H_ */
diff --git a/src/SecureElement/JSReader.cpp b/src/SecureElement/JSReader.cpp
new file mode 100755 (executable)
index 0000000..051423b
--- /dev/null
@@ -0,0 +1,282 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Logger.h>
+#include <SecurityExceptions.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <TimeTracer.h>
+
+#include "JSReader.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace{
+const char* CLASS_NAME = "Reader";
+const char* READER_ATTR_ISPRESENT = "isPresent";
+const char* READER_FUN_GET_NAME = "getName";
+const char* READER_FUN_OPEN_SESSION = "openSession";
+const char* READER_FUN_CLOSE_SESSIONS = "closeSessions";
+}
+
+struct SEReaderHolder {
+    SEReaderPtr ptr;
+};
+
+JSClassDefinition JSReader::m_classInfo = {
+        0,                      // version
+        kJSClassAttributeNone,  // attributes
+        CLASS_NAME,             // class name
+        NULL,                   // parent class
+        m_property,             // static values
+        m_function,             // static functions
+        initialize,             // initialize
+        finalize,               // finalize
+        NULL,                   // hasProperty
+        NULL,                   // getProperty
+        NULL,                   // setProperty
+        NULL,                   // deleteProperty
+        NULL,                   // getPropertyNames
+        NULL,                   // callAsFunction
+        NULL,                   // constructor
+        NULL,                   // hasInstance,
+        NULL                    // convertToType
+};
+
+JSStaticFunction JSReader::m_function[] = {
+        {READER_FUN_GET_NAME, getName, kJSPropertyAttributeNone},
+        {READER_FUN_OPEN_SESSION, openSession, kJSPropertyAttributeNone},
+        {READER_FUN_CLOSE_SESSIONS, closeSessions, kJSPropertyAttributeNone},
+        { 0, 0, 0}
+};
+
+JSStaticValue JSReader::m_property[] =
+{
+        {READER_ATTR_ISPRESENT, isPresent, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+        { 0, 0, 0, 0 }
+};
+
+JSClassRef JSReader::m_jsClassRef = JSClassCreate(JSReader::getClassInfo());
+
+SEReaderPtr JSReader::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGW("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SEReaderHolder* priv = static_cast<SEReaderHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    return priv->ptr;
+}
+
+void JSReader::setPrivateObject(JSObjectRef object, SEReaderPtr native)
+{
+    SEReaderHolder* priv = static_cast<SEReaderHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSReader::makeJSObject(JSContextRef context, SEReaderPtr native)
+{
+    LOGD("Entered");
+    if (!native) {
+        LOGW("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    SEReaderHolder* priv = new(std::nothrow) SEReaderHolder();
+    if (!priv) {
+        LOGW("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSReader::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSReader::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+const JSClassRef JSReader::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSReader::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSReader::isPresent(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SEReaderPtr priv = JSReader::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->isPresent());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSReader::getName(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SEReaderPtr priv = JSReader::getPrivateObject(context, thisObject);
+        return JSUtil::toJSValueRef(context, priv->getName());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getName BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("getName fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getName fails");
+    }
+}
+
+JSValueRef JSReader::openSession(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    OpenSessionCallbackData *callback = NULL;
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new OpenSessionCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+        callback->setSuccessCallback(validator.toFunction(0, false));
+        callback->setErrorCallback(validator.toFunction(1, true));
+
+        SEReaderPtr priv = JSReader::getPrivateObject(context, thisObject);
+        priv->openSession(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("openSession BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("openSession fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "openSession fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSReader::closeSessions(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SEReaderPtr priv = JSReader::getPrivateObject(context, thisObject);
+        priv->closeSessions();
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("closeSessions BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("closeSessions fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "closeSessions fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // SecureElement
+} // DeviceAPI
diff --git a/src/SecureElement/JSReader.h b/src/SecureElement/JSReader.h
new file mode 100755 (executable)
index 0000000..5b7f066
--- /dev/null
@@ -0,0 +1,98 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef _TIZEN_SECUREELEMENT_JS_READER_H_
+#define _TIZEN_SECUREELEMENT_JS_READER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "SEReader.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+class JSReader
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef makeJSObject(JSContextRef context, SEReaderPtr native);
+
+    static SEReaderPtr getPrivateObject(JSContextRef context, JSValueRef value);
+    static void setPrivateObject(JSObjectRef object, SEReaderPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef isPresent(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getName(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef openSession(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef closeSessions(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // SecureElement
+} // DeviceAPI
+
+#endif /* _TIZEN_SECUREELEMENT_JS_READER_H_*/
diff --git a/src/SecureElement/JSSEService.cpp b/src/SecureElement/JSSEService.cpp
new file mode 100755 (executable)
index 0000000..64dcaad
--- /dev/null
@@ -0,0 +1,258 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Logger.h>
+#include <ArgumentValidator.h>
+#include <SecurityExceptions.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Export.h>
+#include <TimeTracer.h>
+
+#include "JSSEService.h"
+#include "SEService.h"
+#include "SECallbackData.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace{
+const char* CLASS_NAME = "SEService";
+const char* SERVICE_GETREADERS = "getReaders";
+const char* SERVICE_REGISTER_LISTENER = "registerSEListener";
+const char* SERVICE_UNREGISTER_LISTENER = "unregisterSEListener";
+const char* SERVICE_SHUTDOWN = "shutdown";
+}
+
+JSClassDefinition JSSEService::m_classInfo =
+{
+        0,                      // version
+        kJSClassAttributeNone,  // attributes
+        CLASS_NAME,             // class name
+        NULL,                   // parent class
+        NULL,                   // static values
+        m_function,             // static functions
+        initialize,             // initialize
+        finalize,               // finalize
+        NULL,                   // hasProperty
+        NULL,                   // getProperty
+        NULL,                   // setProperty
+        NULL,                   // deleteProperty
+        NULL,                   // getPropertyNames
+        NULL,                   // callAsFunction
+        NULL,                   // constructor
+        NULL,                   // hasInstance,
+        NULL                    // convertToType
+};
+
+JSStaticFunction JSSEService::m_function[] = {
+        {SERVICE_GETREADERS, getReaders, kJSPropertyAttributeNone},
+        {SERVICE_REGISTER_LISTENER, registerSEListener, kJSPropertyAttributeNone},
+        {SERVICE_UNREGISTER_LISTENER, unregisterSEListener, kJSPropertyAttributeNone},
+        {SERVICE_SHUTDOWN, shutdown, kJSPropertyAttributeNone},
+        { 0, 0, 0}
+};
+
+JSClassRef JSSEService::m_jsClassRef = JSClassCreate(JSSEService::getClassInfo());
+
+void JSSEService::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSEService::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+const JSClassRef DLL_EXPORT JSSEService::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSSEService::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSSEService::getReaders(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    GetReadersCallbackData* callback = NULL;
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        callback = new GetReadersCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        callback->setSuccessCallback(validator.toFunction(0, false));
+        callback->setErrorCallback(validator.toFunction(1, true));
+
+        SEService::getInstance().getReaders(callback);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getReaders BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("getReaders fails");
+        delete callback;
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "getReaders fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSEService::registerSEListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        JSObjectRef contactCallbackObj = validator.toCallbackObject(0,
+                false,
+                SEChangeListener::ON_SE_READY,
+                SEChangeListener::ON_SE_NOT_READY,
+                NULL);
+
+        SEChangeListenerPtr listener_ptr = SEChangeListenerPtr(
+                new(std::nothrow) SEChangeListener(
+                        GlobalContextManager::getInstance()->getGlobalContext(context),
+                        contactCallbackObj));
+
+        if(!listener_ptr) {
+            LOGE("Memory allocation error");
+            throw UnknownException("Memory allocation error");
+        }
+
+        long listener_id = SEService::getInstance().registerSEListener(listener_ptr);
+
+        return JSUtil::toJSValueRef(context, listener_id);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("registerSEListener BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("registerSEListener fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "registerSEListener fails");
+    }
+}
+
+JSValueRef JSSEService::unregisterSEListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        SEService::getInstance().unregisterSEListener(validator.toLong(0, false));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("unregisterSEListener BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("unregisterSEListener fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "unregisterSEListener fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSEService::shutdown(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SEService::getInstance().shutdown();
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("shutdown BasePlarformException caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        LOGE("shutdown fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR, "shutdown fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // SecureElement
+} // DeviceAPI
diff --git a/src/SecureElement/JSSEService.h b/src/SecureElement/JSSEService.h
new file mode 100755 (executable)
index 0000000..e09eee2
--- /dev/null
@@ -0,0 +1,89 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef _TIZEN_SECUREELEMENT_JS_SESERVICE_H_
+#define _TIZEN_SECUREELEMENT_JS_SESERVICE_H_
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "SEService.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+class JSSEService
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getReaders(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef registerSEListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unregisterSEListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef shutdown(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // SecureElement
+} // DeviceAPI
+
+#endif /* _TIZEN_SECUREELEMENT_JS_SESERVICE_H_ */
diff --git a/src/SecureElement/JSSession.cpp b/src/SecureElement/JSSession.cpp
new file mode 100755 (executable)
index 0000000..bb4f7bd
--- /dev/null
@@ -0,0 +1,368 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Logger.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <SecurityExceptions.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <TimeTracer.h>
+
+#include "JSSession.h"
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace DeviceAPI::Common;
+
+namespace{
+const char* CLASS_NAME = "Session";
+const char* SESSION_ISCLOSED = "isClosed";
+const char* SESSION_OPENBASIC_CH = "openBasicChannel";
+const char* SESSION_OPENLOGICAL_CH = "openLogicalChannel";
+const char* SESSION_GETATTR = "getATR";
+const char* SESSION_CLOSE = "close";
+const char* SESSION_CLOSE_CH = "closeChannels";
+}
+
+struct SessionHolder{
+    SessionPtr ptr;
+};
+
+JSClassDefinition JSSession::m_classInfo =
+{
+        0,                      // version
+        kJSClassAttributeNone,  // attributes
+        CLASS_NAME,             // class name
+        NULL,                   // parent class
+        m_property,             // static values
+        m_function,             // static functions
+        initialize,             // initialize
+        finalize,               // finalize
+        NULL,                   // hasProperty
+        NULL,                   // getProperty
+        NULL,                   // setProperty
+        NULL,                   // deleteProperty
+        NULL,                   // getPropertyNames
+        NULL,                   // callAsFunction
+        NULL,                   // constructor
+        NULL,                   // hasInstance,
+        NULL                    // convertToType
+};
+
+JSStaticFunction JSSession::m_function[] = {
+        {SESSION_OPENBASIC_CH, openBasicChannel, kJSPropertyAttributeNone},
+        {SESSION_OPENLOGICAL_CH, openLogicalChannel, kJSPropertyAttributeNone},
+        {SESSION_GETATTR, getATR, kJSPropertyAttributeNone},
+        {SESSION_CLOSE, close, kJSPropertyAttributeNone},
+        {SESSION_CLOSE_CH, closeChannels, kJSPropertyAttributeNone},
+        { 0, 0, 0}
+};
+
+JSStaticValue JSSession::m_property[] =
+{
+        {SESSION_ISCLOSED, isClosed, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly},
+        { 0, 0, 0, 0 }
+};
+
+JSClassRef JSSession::m_jsClassRef = JSClassCreate(JSSession::getClassInfo());
+
+SessionPtr JSSession::getPrivateObject(JSContextRef context,
+        JSValueRef value_ref)
+{
+    if (!JSValueIsObjectOfClass(context, value_ref, getClassRef())) {
+        LOGE("TypeMismatch");
+        throw TypeMismatchException("TypeMismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value_ref);
+    SessionHolder* priv = static_cast<SessionHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+
+    if (!(priv->ptr)) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    return priv->ptr;
+}
+
+JSObjectRef JSSession::makeJSObject(JSContextRef context, SessionPtr native)
+{
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    SessionHolder* priv = new SessionHolder();
+    if(!priv){
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context,
+            getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSession::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSession::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+const JSClassRef JSSession::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSSession::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSSession::isClosed(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SessionPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->isClosed());
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("Error during isClosed() , Name: %s, Message: %s",
+                e.getName().c_str(), e.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Unknown error during isClosed()");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSession::getATR(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SessionPtr priv = getPrivateObject(context, thisObject);
+        UCharVectorPtr to_ret = priv->getATR();
+        return JSUtil::toJSValueRef_<unsigned char>(context, *to_ret);
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("Error during getATR() , Name: %s, Message: %s",
+                e.getName().c_str(), e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+    catch (...) {
+        LOGE("Error during getATR()");
+        UnknownException err("Error during getATR()");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSSession::close(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SessionPtr priv = getPrivateObject(context, thisObject);
+        priv->close();
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("Error during close() , Name: %s, Message: %s",
+                e.getName().c_str(), e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+    catch (...) {
+        LOGE("Error during close()");
+        return JSWebAPIErrorFactory::postException(context,
+                exception, UnknownException("Error during close()"));
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSession::closeChannels(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SessionPtr priv = getPrivateObject(context, thisObject);
+        priv->closeChannels();
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("Error during closeChannels() , Name: %s, Message: %s",
+                e.getName().c_str(), e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+    catch (...) {
+        LOGE("Error during closeChannels()");
+        return JSWebAPIErrorFactory::postException(context,
+                exception, UnknownException("Error during closeChannels()"));
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSession::openBasicChannel(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SessionPtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        UCharVectorPtr aid(new std::vector<unsigned char>(validator.toUCharVector(0, false)));
+
+        unsigned int size  = aid->size();
+        if (size < 5 || size > 16) {
+            LOGE("Wrong AID length");
+            throw InvalidValuesException("Wrong AID length");
+        }
+
+        ChannelCallbackDataPtr callback = ChannelCallbackDataPtr(new ChannelCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context), aid, true));
+
+        callback->setSuccessCallback(validator.toFunction(1, false));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        priv->openChannel(callback);
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("Error during openBasicChannel() , Name: %s, Message: %s",
+                e.getName().c_str(), e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+    catch (...) {
+        LOGE("Error during openBasicChannel()");
+        return JSWebAPIErrorFactory::postException(context,
+                exception, UnknownException("Error during openBasicChannel()"));
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSession::openLogicalChannel(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    ACE_ACCESS_CHECK(
+        AceSecurityStatus status = SECURE_ELEMENT_CHECK_ACCESS(SECUREELEMENT_FUNCTION_API_FUNCS);
+        TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    );
+
+    try {
+        SessionPtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        UCharVectorPtr aid(new std::vector<unsigned char>(validator.toUCharVector(0, false)));
+
+        unsigned int size  = aid->size();
+        if (size < 5 || size > 16) {
+            LOGE("Wrong AID length");
+            throw InvalidValuesException("Wrong AID length");
+        }
+
+        ChannelCallbackDataPtr callback = ChannelCallbackDataPtr(new ChannelCallbackData(
+                GlobalContextManager::getInstance()->getGlobalContext(context), aid, false));
+
+        callback->setSuccessCallback(validator.toFunction(1, false));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        priv->openChannel(callback);
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("Error during openLogicalChannel() , Name: %s, Message: %s",
+                e.getName().c_str(), e.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, e);
+    }
+    catch (...) {
+        LOGE("Error during openLogicalChannel()");
+        return JSWebAPIErrorFactory::postException(context,
+                exception, UnknownException("Error during openLogicalChannel()"));
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // SecureElement
+} // DeviceAPI
diff --git a/src/SecureElement/JSSession.h b/src/SecureElement/JSSession.h
new file mode 100755 (executable)
index 0000000..bd8e4ba
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef _TIZEN_SECUREELEMENT_JS_SESSION_H_
+#define _TIZEN_SECUREELEMENT_JS_SESSION_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "Session.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+class JSSession
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSObjectRef makeJSObject(JSContextRef context, SessionPtr native);
+    static SessionPtr getPrivateObject(JSContextRef context, JSValueRef value_ref);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef isClosed(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef openBasicChannel(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef openLogicalChannel(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getATR(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef close(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef closeChannels(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+};
+
+} // SecureElement
+} // DeviceAPI
+
+#endif /* _TIZEN_SECUREELEMENT_JS_SESSION_H_ */
diff --git a/src/SecureElement/SECallbackData.cpp b/src/SecureElement/SECallbackData.cpp
new file mode 100644 (file)
index 0000000..c66e0fa
--- /dev/null
@@ -0,0 +1,201 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        SECallbackData.cpp
+ */
+
+#include "SECallbackData.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+//========================BASE_CALLBACK_DATA========================
+
+BaseCallbackData::BaseCallbackData(JSContextRef globalCtx):
+                Common::CallbackUserData(globalCtx),
+                m_is_error(false)
+{
+}
+
+BaseCallbackData::~BaseCallbackData()
+{
+}
+
+void BaseCallbackData::setError(const std::string &err_name,
+        const std::string &err_message)
+{
+    m_err_name = err_name;
+    m_err_message = err_message;
+    m_is_error = true;
+}
+
+bool BaseCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+const std::string& BaseCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+const std::string& BaseCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+//========================TRANSMIT_CALLBACK_DATA========================
+
+TransmitCallbackData::TransmitCallbackData(JSContextRef globalCtx):
+                BaseCallbackData(globalCtx)
+{
+}
+
+TransmitCallbackData::~TransmitCallbackData()
+{
+}
+
+void TransmitCallbackData::setCommand(UCharVectorPtr command)
+{
+    m_command = command;
+}
+
+UCharVectorPtr TransmitCallbackData::getCommand() const
+{
+    return m_command;
+}
+
+void TransmitCallbackData::setResponse(UCharVectorPtr response)
+{
+    m_response = response;
+}
+
+UCharVectorPtr TransmitCallbackData::getResponse() const
+{
+    return m_response;
+}
+
+void TransmitCallbackData::setChannel(Channel* channel)
+{
+    m_channel = channel;
+}
+
+Channel* TransmitCallbackData::getChannel() const
+{
+    return m_channel;
+}
+
+//========================CHANNEL_CALLBACK_DATA========================
+
+ChannelCallbackData::ChannelCallbackData(JSContextRef global_ctx,
+        UCharVectorPtr aid,
+        bool is_basic) :
+                BaseCallbackData(global_ctx),
+                m_aid(aid),
+                m_is_basic(is_basic)
+{
+}
+
+ChannelCallbackData::~ChannelCallbackData()
+{
+}
+
+bool ChannelCallbackData::isBasicChannel() const
+{
+    return m_is_basic;
+}
+
+void ChannelCallbackData::setChannel(SEChannelPtr channel)
+{
+    m_channel = channel;
+}
+
+SEChannelPtr ChannelCallbackData::getChannel() const
+{
+    return m_channel;
+}
+
+UCharVectorPtr ChannelCallbackData::getAid() const
+{
+    return m_aid;
+}
+
+//========================OPEN_SESSION_CALLBACK_DATA========================
+
+OpenSessionCallbackData::OpenSessionCallbackData(JSContextRef globalCtx):
+                BaseCallbackData(globalCtx)
+{
+}
+
+OpenSessionCallbackData::~OpenSessionCallbackData()
+{
+}
+
+void OpenSessionCallbackData::setSession(SessionPtr session)
+{
+    m_session = session;
+}
+
+SessionPtr OpenSessionCallbackData::getSession() const
+{
+    return m_session;
+}
+
+void OpenSessionCallbackData::setReader(Reader* reader)
+{
+    m_reader = reader;
+}
+
+Reader* OpenSessionCallbackData::getReader() const
+{
+    return m_reader;
+}
+
+//========================GET_READERS_CALLBACK_DATA========================
+
+GetReadersCallbackData::GetReadersCallbackData(JSContextRef globalCtx):
+                BaseCallbackData(globalCtx)
+{
+}
+
+GetReadersCallbackData::~GetReadersCallbackData()
+{
+}
+
+void GetReadersCallbackData::setReaders(ReaderVectorPtr readers)
+{
+    m_readers = readers;
+}
+
+ReaderVectorPtr GetReadersCallbackData::getReaders() const
+{
+    return m_readers;
+}
+
+void GetReadersCallbackData::setService(smartcard_service_api::SEService* service)
+{
+    m_service = service;
+}
+
+smartcard_service_api::SEService* GetReadersCallbackData::getService() const
+{
+    return m_service;
+}
+
+}
+}
diff --git a/src/SecureElement/SECallbackData.h b/src/SecureElement/SECallbackData.h
new file mode 100644 (file)
index 0000000..a1bdc5d
--- /dev/null
@@ -0,0 +1,149 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        SECallbackData.h
+ */
+
+#ifndef __TIZEN_SECUREELEMENT_SECALLBACKDATA_H__
+#define __TIZEN_SECUREELEMENT_SECALLBACKDATA_H__
+
+#include <CallbackUserData.h>
+#include <string>
+#include <memory>
+#include <Channel.h>
+#include <Reader.h>
+#include <SEService.h>
+#include <vector>
+
+using namespace smartcard_service_api;
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+typedef std::vector<unsigned char> UCharVector;
+typedef std::shared_ptr<UCharVector> UCharVectorPtr;
+
+class ChannelCallbackData;
+typedef std::shared_ptr<ChannelCallbackData> ChannelCallbackDataPtr;
+
+class BaseCallbackData : public Common::CallbackUserData
+{
+public:
+    BaseCallbackData(JSContextRef globalCtx);
+    virtual ~BaseCallbackData();
+
+    void setError(const std::string &err_name,
+            const std::string &err_message);
+    bool isError() const;
+    const std::string& getErrorName() const;
+    const std::string& getErrorMessage() const;
+
+private:
+    bool m_is_error;
+    std::string m_err_name;
+    std::string m_err_message;
+
+};
+
+class TransmitCallbackData : public BaseCallbackData
+{
+public:
+    TransmitCallbackData(JSContextRef globalCtx);
+    virtual ~TransmitCallbackData();
+
+    void setCommand(UCharVectorPtr command);
+    UCharVectorPtr getCommand() const;
+    void setResponse(UCharVectorPtr command);
+    UCharVectorPtr getResponse() const;
+    Channel* getChannel() const;
+    void setChannel(Channel* channel);
+
+private:
+    UCharVectorPtr m_command;
+    UCharVectorPtr m_response;
+    Channel* m_channel;
+};
+
+class SEChannel;
+typedef std::shared_ptr<SEChannel> SEChannelPtr;
+
+class ChannelCallbackData : public BaseCallbackData
+{
+public:
+    ChannelCallbackData(JSContextRef global_ctx,
+            UCharVectorPtr aid,
+            bool is_basic);
+    virtual ~ChannelCallbackData();
+
+    bool isBasicChannel() const;
+    SEChannelPtr getChannel() const;
+    void setChannel(SEChannelPtr channel);
+    UCharVectorPtr getAid() const;
+
+private:
+    bool m_is_basic;
+    UCharVectorPtr m_aid;
+    SEChannelPtr m_channel;
+};
+
+class Session;
+typedef std::shared_ptr<Session> SessionPtr;
+
+class OpenSessionCallbackData: public BaseCallbackData
+{
+public:
+    OpenSessionCallbackData(JSContextRef globalCtx);
+    virtual ~OpenSessionCallbackData();
+
+    void setSession(SessionPtr session);
+    SessionPtr getSession() const;
+    Reader* getReader() const;
+    void setReader(Reader* reader);
+
+private:
+    SessionPtr m_session;
+    Reader* m_reader;
+
+};
+
+class SEReader;
+typedef std::shared_ptr<SEReader> SEReaderPtr;
+typedef std::vector<SEReaderPtr> ReaderVector;
+typedef std::shared_ptr<ReaderVector> ReaderVectorPtr;
+
+class GetReadersCallbackData: public BaseCallbackData
+{
+public:
+    GetReadersCallbackData(JSContextRef globalCtx);
+    virtual ~GetReadersCallbackData();
+
+    void setReaders(ReaderVectorPtr readers);
+    ReaderVectorPtr getReaders() const;
+    smartcard_service_api::SEService* getService() const;
+    void setService(smartcard_service_api::SEService* service);
+
+private:
+    ReaderVectorPtr m_readers;
+    smartcard_service_api::SEService* m_service;
+
+};
+
+}
+}
+
+#endif //__TIZEN_SECUREELEMENT_SECALLBACKDATA_H__
diff --git a/src/SecureElement/SEChangeListener.cpp b/src/SecureElement/SEChangeListener.cpp
new file mode 100644 (file)
index 0000000..d050acb
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SEChangeListener.h"
+#include "JSReader.h"
+#include <GlobalContextManager.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace Common;
+
+const char* SEChangeListener::ON_SE_READY = "onSEReady";
+const char* SEChangeListener::ON_SE_NOT_READY = "onSENotReady";
+
+SEChangeListener::SEChangeListener(JSContextRef globalCtx, JSObjectRef object):
+                m_is_active(true)
+{
+    m_callback = MultiCallbackPtr(new (std::nothrow) MultiCallbackUserData(globalCtx, object));
+
+    if (!m_callback) {
+        LOGW("Callback is null");
+        throw UnknownException("Cannot allocate memory");
+    }
+}
+
+SEChangeListener::~SEChangeListener()
+{
+}
+
+void SEChangeListener::onSEReady(SEReaderPtr reader)
+{
+    if (!m_is_active) {
+        return;
+    }
+
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+    JSObjectRef jsReader = JSReader::makeJSObject(context, reader);
+
+    m_callback->invokeCallback(ON_SE_READY, jsReader);
+}
+
+void SEChangeListener::onSENotReady(SEReaderPtr reader)
+{
+    if (!m_is_active) {
+        return;
+    }
+
+    JSContextRef context = m_callback->getContext();
+    CHECK_CURRENT_CONTEXT_ALIVE(context);
+    JSObjectRef jsReader = JSReader::makeJSObject(context, reader);
+
+    m_callback->invokeCallback(ON_SE_NOT_READY, jsReader);
+}
+
+bool SEChangeListener::isActive() const
+{
+    return m_is_active;
+}
+
+void SEChangeListener::setActive(bool active)
+{
+    m_is_active = active;
+}
+
+} //SecureElement
+} //DeviceAPI
diff --git a/src/SecureElement/SEChangeListener.h b/src/SecureElement/SEChangeListener.h
new file mode 100644 (file)
index 0000000..fc90a67
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_SECURE_ELEMENT_SE_CHANGE_LISTENER_H__
+#define __TIZEN_SECURE_ELEMENT_SE_CHANGE_LISTENER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <vector>
+#include <memory>
+#include <string>
+
+#include "SEReader.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace smartcard_service_api;
+
+class SEChangeListener;
+
+typedef std::shared_ptr<SEChangeListener> SEChangeListenerPtr;
+typedef std::shared_ptr<Common::MultiCallbackUserData> MultiCallbackPtr;
+
+class SEChangeListener {
+public:
+    SEChangeListener(JSContextRef globalCtx, JSObjectRef object);
+    virtual ~SEChangeListener();
+
+    void onSEReady(SEReaderPtr reader);
+    void onSENotReady(SEReaderPtr reader);
+
+    static const char* ON_SE_READY;
+    static const char* ON_SE_NOT_READY;
+
+    bool isActive() const;
+    void setActive(bool active);
+
+private:
+    MultiCallbackPtr m_callback;
+    bool m_is_active;
+
+};
+
+} //SecureElement
+} //DeviceAPI
+
+#endif // __TIZEN_SECURE_ELEMENT_SE_CHANGE_LISTENER_H__
diff --git a/src/SecureElement/SEChannel.cpp b/src/SecureElement/SEChannel.cpp
new file mode 100755 (executable)
index 0000000..989b3d4
--- /dev/null
@@ -0,0 +1,213 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SEChannel.h"
+
+#include <ByteArray.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+#include "SEUtils.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace smartcard_service_api;
+using namespace Common;
+
+SEChannel::SEChannel(void* channel)
+{
+    if (!channel) {
+        LOGE("Channel is null");
+        throw UnknownException("Channel is null");
+    }
+
+    m_channel = static_cast<Channel*>(channel);
+}
+
+SEChannel::~SEChannel()
+{
+    try {
+        close();
+    }
+    catch (ExceptionBase& e) {
+        LOGE("Exception caught: %d, message: %s", e.getErrorCode(), e.what());
+    }
+    m_channel = NULL;
+}
+
+void SEChannel::close()
+{
+    if (!m_channel->isClosed()) {
+        m_channel->closeSync();
+    }
+}
+
+bool SEChannel::isBasicChannel() const
+{
+    return m_channel->isBasicChannel();
+}
+
+void SEChannel::transmit(TransmitCallbackData* callback)
+{
+    callback->setChannel(m_channel);
+    pthread_t thread;
+    if(pthread_create(&thread, NULL, transmitThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+    if(pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* SEChannel::transmitThread(void* data)
+{
+    auto callback = static_cast<TransmitCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    Channel* channel = callback->getChannel();
+    if (!channel) {
+        LOGE("chanel is null");
+        delete callback;
+        callback = NULL;
+        return NULL;
+    }
+
+    try {
+        ByteArray command(callback->getCommand()->data(),
+                callback->getCommand()->size());
+        ByteArray response;
+
+        try {
+            int error = channel->transmitSync(command, response);
+            if (error != 0) {
+                LOGE("ret : %d", error);
+                throwSecureElementException<UnknownException>(error, "channel->transmitSync()");
+            }
+        }
+        catch (ExceptionBase& e) {
+            LOGE("Error thrown, code: %d", e.getErrorCode());
+            throwDeducedSecureElementException(e, "channel->transmitSync()");
+        }
+
+        uint8_t* response_buf = response.getBuffer();
+        size_t response_len = response.getLength();
+
+        UCharVectorPtr response_vec(new UCharVector(response_buf,
+                response_buf + response_len));
+
+        callback->setResponse(response_vec);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("transmitThread fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch (...) {
+        LOGE("transmitThread fails");
+        callback->setError("UnknownError", "transmitThread fails");
+    }
+
+    guint id = g_idle_add(transmitCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+    }
+    return NULL;
+}
+
+gboolean SEChannel::transmitCallback(void *data)
+{
+    auto callback = static_cast<TransmitCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    auto response = callback->getResponse();
+    if (!response) {
+        LOGE("response is null");
+        callback->setError(JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "response is null");
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(error);
+        }
+        else {
+            JSValueRef arr = JSUtil::toJSValueRef_(context, *callback->getResponse());
+            callback->callSuccessCallback(arr);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("transmitCallback fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("transmitCallback fails");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+UCharVectorPtr SEChannel::getSelectResponse() const
+{
+    LOGD("Entered");
+    ByteArray byte_array;
+    UCharVectorPtr to_ret;
+    try{
+        byte_array = m_channel->getSelectResponse();
+        uint8_t* response_buf = byte_array.getBuffer();
+        size_t response_len = byte_array.getLength();
+
+        to_ret = UCharVectorPtr(new UCharVector(response_buf,
+                response_buf + response_len));
+        return to_ret;
+    }catch(ExceptionBase& e){
+        LOGE("Error during getSelectResponse(): code %d , msg %s,", e.getErrorCode(), e.what());
+        throw UnknownException(e.what());
+    }
+    catch (...) {
+        LOGE("Error during getSelectResponse()");
+        throw UnknownException("Error during getSelectResponse()");
+    }
+
+    return to_ret;
+}
+
+}
+}
diff --git a/src/SecureElement/SEChannel.h b/src/SecureElement/SEChannel.h
new file mode 100755 (executable)
index 0000000..71d9bc3
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SECURE_ELEMENT_CHANNEL_H__
+#define __TIZEN_SECURE_ELEMENT_CHANNEL_H__
+
+#include <memory>
+#include <Channel.h>
+#include "SECallbackData.h"
+
+#include <glib.h>
+
+using namespace smartcard_service_api;
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+class SEChannel;
+typedef std::shared_ptr<SEChannel> SEChannelPtr;
+
+class SEChannel
+{
+public:
+    SEChannel(void* channel);
+    virtual ~SEChannel();
+
+    bool isBasicChannel() const;
+    void close();
+    void transmit(TransmitCallbackData* callback);
+    UCharVectorPtr getSelectResponse() const;
+
+private:
+    Channel* m_channel;
+
+    static void* transmitThread(void* data);
+    static gboolean transmitCallback(void *data);
+
+};
+
+}
+}
+
+#endif /* __TIZEN_SECURE_ELEMENT_CHANNEL_H__ */
diff --git a/src/SecureElement/SEReader.cpp b/src/SecureElement/SEReader.cpp
new file mode 100644 (file)
index 0000000..d0c8c93
--- /dev/null
@@ -0,0 +1,173 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SEReader.h"
+#include "JSSession.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace smartcard_service_api;
+using namespace Common;
+
+SEReader::SEReader(void* reader)
+{
+    if (!reader) {
+        LOGE("Reader is null");
+        throw UnknownException("Reader is null");
+    }
+
+    m_reader = static_cast<Reader*>(reader);
+}
+
+SEReader::~SEReader()
+{
+    try {
+        closeSessions();
+    }
+    catch (ExceptionBase& e) {
+        LOGE("Exception caught: %d, message: %s", e.getErrorCode(), e.what());
+    }
+}
+
+bool SEReader::isPresent() const
+{
+    return m_reader->isSecureElementPresent();
+}
+
+std::string SEReader::getName() const
+{
+    return m_reader->getName();
+}
+
+void SEReader::openSession(OpenSessionCallbackData* callback)
+{
+    callback->setReader(m_reader);
+    pthread_t thread;
+    if(pthread_create(&thread, NULL, openSessionThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+    if(pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* SEReader::openSessionThread(void* data)
+{
+    auto callback = static_cast<OpenSessionCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    Reader* reader = callback->getReader();
+    if (!reader) {
+        LOGE("reader is null");
+        delete callback;
+        callback = NULL;
+        return NULL;
+    }
+
+    try {
+        SessionHelper* session = reader->openSessionSync();
+        SessionPtr session_ptr(new Session(
+                static_cast<smartcard_service_api::Session*>(session)));
+        callback->setSession(session_ptr);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("openSessionThread fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch (...) {
+        LOGE("openSessionThread fails");
+        callback->setError("UnknownError", "openSessionThread fails");
+    }
+
+    guint id = g_idle_add(openSessionCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+        callback = NULL;
+    }
+    return NULL;
+}
+
+gboolean SEReader::openSessionCallback(void *data)
+{
+    auto callback = static_cast<OpenSessionCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(error);
+        }
+        else {
+            auto session = callback->getSession();
+            if (!session) {
+                LOGE("session is null");
+                delete callback;
+                callback = NULL;
+                return false;
+            }
+
+            JSObjectRef obj = JSSession::makeJSObject(context, session);
+            callback->callSuccessCallback(obj);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("openSessionCallback fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("openSessionCallback fails");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+void SEReader::closeSessions()
+{
+    m_reader->closeSessions();
+}
+
+}
+}
diff --git a/src/SecureElement/SEReader.h b/src/SecureElement/SEReader.h
new file mode 100644 (file)
index 0000000..7ce7cb0
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SE_READER_H__
+#define __TIZEN_SE_READER_H__
+
+#include <memory>
+#include <string>
+#include <Reader.h>
+#include "SECallbackData.h"
+
+#include <glib.h>
+
+using namespace smartcard_service_api;
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+class SEReader;
+typedef std::shared_ptr<SEReader> SEReaderPtr;
+
+class SEReader
+{
+public:
+    SEReader(void* reader);
+    virtual ~SEReader();
+
+    bool isPresent() const;
+    std::string getName() const;
+    void openSession(OpenSessionCallbackData* callback);
+    void closeSessions();
+
+private:
+    Reader* m_reader;
+
+    static void* openSessionThread(void* data);
+    static gboolean openSessionCallback(void *data);
+
+};
+
+}
+}
+
+#endif /* __TIZEN_SE_CHANNEL_H__ */
diff --git a/src/SecureElement/SEService.cpp b/src/SecureElement/SEService.cpp
new file mode 100644 (file)
index 0000000..65adfb5
--- /dev/null
@@ -0,0 +1,344 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SEService.h"
+#include <Logger.h>
+#include <algorithm>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include "SEReader.h"
+#include "JSReader.h"
+#include "SEUtils.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace Common;
+
+namespace {
+class ServiceListener: public SEServiceListener {
+public:
+    void serviceConnected(SEServiceHelper *service, void *context)
+    {
+        LOGE("Service connected");
+        if (context) {
+            SEService* service = static_cast<SEService*>(context);
+            service->serviceConnected();
+        }
+        else {
+            LOGE("Context is null");
+        }
+    }
+
+    void eventHandler(SEServiceHelper *service, char *seName, int event,
+            void *context)
+    {
+        LOGE("Event handler called, seName: %s, event: %d", seName, event);
+        if (context) {
+            SEService* service = static_cast<SEService*>(context);
+            service->eventHandler(seName, event);
+        }
+        else {
+            LOGE("Context is null");
+        }
+    }
+
+    void errorHandler(SEServiceHelper *service, int error, void *context)
+    {
+        LOGE("Error handler called, code: %d", error);
+    }
+};
+static ServiceListener listener;
+}
+
+SEService::SEService():
+                m_listener_counter(1),
+                m_initialized(false)
+{
+    m_service = new smartcard_service_api::SEService(static_cast<void*>(this),
+            &listener);
+}
+
+SEService::~SEService()
+{
+    if (m_service) {
+        m_service->shutdownSync();
+        delete m_service;
+        m_service = NULL;
+    }
+}
+
+SEService& SEService::getInstance()
+{
+    static SEService instance;
+    return instance;
+}
+
+void SEService::serviceConnected()
+{
+    m_initialized = true;
+    for(size_t size = m_callbacks.size(), i = 0; i < size; ++i) {
+        GetReadersCallbackData* callback = NULL;
+        try {
+            callback = m_callbacks[i];
+            getReaders(callback);
+        }
+        catch (const BasePlatformException& e) {
+            LOGE("getReaders failed, name: %s, msg: %s", e.getName().c_str(),
+                    e.getMessage().c_str());
+            delete callback;
+            callback = NULL;
+        }
+    }
+    m_callbacks.clear();
+}
+
+void SEService::clearCallbacks()
+{
+    while (!m_callbacks.empty()) {
+        GetReadersCallbackData* callback = m_callbacks.back();
+        delete callback;
+        callback = NULL;
+        m_callbacks.pop_back();
+    }
+}
+
+void SEService::eventHandler(char* seName, int event)
+{
+    if (!m_listeners.empty()) {
+        std::vector<smartcard_service_api::ReaderHelper*> readers =
+                m_service->getReaders();
+
+        size_t i = 0;
+        for (i = readers.size(); i > 0; i--) {
+            if ((strlen(readers[i-1]->getName()) == strlen(seName))
+                    && !strncmp(readers[i-1]->getName(), seName, strlen(seName))) {
+                if (((event == 1) && readers[i-1]->isSecureElementPresent())
+                        ||((event == 2) && !readers[i-1]->isSecureElementPresent()))
+                    break;
+            }
+        }
+        if (!i) {
+            LOGE("No readers found");
+            return;
+        }
+
+        for_each(m_listeners.begin(), m_listeners.end(),
+                [event, i, &readers](ListenerPair listener) {
+            SEChangeListenerHolder* holder = new SEChangeListenerHolder();
+            holder->listener = listener.second;
+            holder->reader = SEReaderPtr(new SEReader(readers[i-1]));
+            holder->event = event;
+            if (!g_idle_add(changeListenerFunc, holder)) {
+                LOGE("g_idle_add_fails");
+                delete holder;
+                holder = NULL;
+            }
+        });
+    }
+}
+
+gboolean SEService::changeListenerFunc(void *data)
+{
+    auto hold = static_cast<SEChangeListenerHolder*>(data);
+    if (!hold) {
+        LOGE("listener holder is null");
+        return false;
+    }
+
+    std::unique_ptr<SEChangeListenerHolder> holder(hold);
+
+    auto listener = holder->listener;
+    if (!listener) {
+        LOGE("listener is null");
+        return false;
+    }
+
+    try {
+        switch (holder->event) {
+        case 1:
+            listener->onSEReady(holder->reader);
+            break;
+        case 2:
+            listener->onSENotReady(holder->reader);
+            break;
+        default:
+            LOGD("Incorrect event");
+            break;
+        }
+    }
+    catch (const Common::BasePlatformException &err) {
+        LOGE("Persons change listener failed: %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+
+    return false;
+}
+
+void SEService::getReaders(GetReadersCallbackData *callback)
+{
+    if (!m_initialized) {
+        m_callbacks.push_back(callback);
+        return;
+    }
+
+    callback->setService(m_service);
+    pthread_t thread;
+    if(pthread_create(&thread, NULL, getReadersThread,
+            static_cast<void*>(callback))) {
+        LOGE("Thread creation failed");
+        throw UnknownException("Thread creation failed");
+    }
+    if(pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* SEService::getReadersThread(void *data)
+{
+    auto callback = static_cast<GetReadersCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return NULL;
+    }
+
+    smartcard_service_api::SEService* service = callback->getService();
+    if (!service) {
+        LOGE("service is null");
+        delete callback;
+        callback = NULL;
+        return NULL;
+    }
+
+    try {
+        std::vector<ReaderHelper*> readers = service->getReaders();
+        ReaderVectorPtr readers_ptr(new ReaderVector());
+
+        size_t size = readers.size();
+        for(size_t i = 0; i < size; i++) {
+            readers_ptr->push_back(SEReaderPtr(new SEReader(readers[i])));
+        }
+        callback->setReaders(readers_ptr);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getReadersThread fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+        callback->setError(err.getName(), err.getMessage());
+    }
+    catch (...) {
+        LOGE("openSessionThread fails");
+        callback->setError("UnknownError", "getReadersThread fails");
+    }
+
+    guint id = g_idle_add(getReadersCallback, data);
+    if (!id) {
+        LOGE("g_idle_add fails");
+        delete callback;
+        callback = NULL;
+    }
+    return NULL;
+}
+
+gboolean SEService::getReadersCallback(void *data)
+{
+    auto callback = static_cast<GetReadersCallbackData*>(data);
+    if (!callback) {
+        LOGE("callback is null");
+        return false;
+    }
+
+    auto readers = callback->getReaders();
+    if (!readers) {
+        LOGE("readers is null");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete callback;
+        callback = NULL;
+        return false;
+    }
+    try {
+        if (callback->isError()) {
+            JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(error);
+        }
+        else {
+            JSObjectRef arr = ptrVectorToJSObjectArray<JSReader, SEReaderPtr>(
+                    *readers, context);
+            callback->callSuccessCallback(arr);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("getReadersCallback fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getReadersCallback fails");
+    }
+
+    delete callback;
+    callback = NULL;
+
+    return false;
+}
+
+long SEService::registerSEListener(SEChangeListenerPtr listener)
+{
+    long listener_id = m_listener_counter++;
+
+    m_listeners.insert(ListenerPair(listener_id, listener));
+
+    return listener_id;
+}
+
+void SEService::unregisterSEListener(long listener_id)
+{
+    ListenersMap::iterator it = m_listeners.find(listener_id);
+
+    if (it != m_listeners.end()) {
+        it->second->setActive(false);
+        m_listeners.erase(it);
+    }
+    else {
+        LOGE("No listener with id: %d", listener_id);
+        throw InvalidValuesException("No listener with such id");
+    }
+}
+
+void SEService::shutdown()
+{
+    if (m_initialized) {
+        m_service->shutdownSync();
+        clearCallbacks();
+
+        delete m_service;
+
+        // re-generate m_service since it belongs to singletone object
+        m_service = new smartcard_service_api::SEService(
+                static_cast<void*>(this), &listener);
+        m_initialized = false;
+    }
+}
+
+}
+}
diff --git a/src/SecureElement/SEService.h b/src/SecureElement/SEService.h
new file mode 100644 (file)
index 0000000..f7935a9
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_SECURE_ELEMENT_SE_SERVICE_H__
+#define __TIZEN_SECURE_ELEMENT_SE_SERVICE_H__
+
+#include <memory>
+#include <mutex>
+#include <vector>
+#include <map>
+#include <SEService.h>
+#include <glib.h>
+
+#include "SEChangeListener.h"
+#include "SECallbackData.h"
+#include "SEReader.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+class SEService;
+typedef std::shared_ptr<SEService> SEServicePtr;
+
+class SEService {
+public:
+    static SEService& getInstance();
+
+    virtual ~SEService();
+
+    void getReaders(GetReadersCallbackData *callback);
+    long registerSEListener(SEChangeListenerPtr listener);
+    void unregisterSEListener(long id);
+    void shutdown();
+
+    void serviceConnected();
+    void eventHandler(char *seName, int event);
+
+private:
+    SEService();
+    SEService(const SEService&);
+    SEService& operator=(const SEService&);
+    void clearCallbacks();
+
+    long m_listener_counter;
+
+    typedef std::pair<long, SEChangeListenerPtr> ListenerPair;
+    typedef std::map<long, SEChangeListenerPtr> ListenersMap;
+    ListenersMap m_listeners;
+
+    std::vector<GetReadersCallbackData*> m_callbacks;
+
+    bool m_initialized;
+    bool m_shutdown;
+    smartcard_service_api::SEService *m_service;
+
+    static void* getReadersThread(void *data);
+    static gboolean getReadersCallback(void *data);
+    static gboolean changeListenerFunc(void *data);
+
+    struct SEChangeListenerHolder {
+        SEReaderPtr reader;
+        SEChangeListenerPtr listener;
+        int event;
+    };
+};
+
+} //SecureElement
+} //DeviceAPI
+
+#endif //__TIZEN_SECURE_ELEMENT_SE_SERVICE_H__
diff --git a/src/SecureElement/SEUtils.cpp b/src/SecureElement/SEUtils.cpp
new file mode 100644 (file)
index 0000000..6852cce
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SEUtils.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace Common;
+using namespace smartcard_service_api;
+
+namespace {
+static std::string SUCCESS_MESSAGE = "OK";
+static std::string IO_EXCEPTION_MESSAGE = "IOError";
+static std::string SECURITY_EXCEPTION_MESSAGE = "SecurityError";
+static std::string INVALID_STATE_EXCEPTION_MESSAGE = "InvalidStateError";
+static std::string INVALID_VALUES_EXCEPTION_MESSAGE = "InvalidValuesError";
+static std::string UNKNOWN_EXCEPTION_MESSAGE = "UnknownError";
+}
+
+const std::string& getSecureElementErrorMessage(const int errorCode){
+    switch (errorCode)
+    {
+    case SCARD_ERROR_OK :
+        /* do nothing */
+        return SUCCESS_MESSAGE;
+    case SCARD_ERROR_IPC_FAILED :
+    case SCARD_ERROR_IO_FAILED :
+    case SCARD_ERROR_OPERATION_TIMEOUT :
+        return IO_EXCEPTION_MESSAGE;
+    case SCARD_ERROR_SECURITY_NOT_ALLOWED :
+        return SECURITY_EXCEPTION_MESSAGE;
+    case SCARD_ERROR_UNAVAILABLE :
+    case SCARD_ERROR_NOT_SUPPORTED :
+    case SCARD_ERROR_NOT_INITIALIZED :
+    case SCARD_ERROR_SE_NOT_INITIALIZED :
+    case SCARD_ERROR_ILLEGAL_STATE :
+    case SCARD_ERROR_OPERATION_NOT_SUPPORTED :
+        return INVALID_STATE_EXCEPTION_MESSAGE;
+    case SCARD_ERROR_ILLEGAL_PARAM :
+    case SCARD_ERROR_ILLEGAL_REFERENCE :
+        return INVALID_VALUES_EXCEPTION_MESSAGE;
+    default :
+        return UNKNOWN_EXCEPTION_MESSAGE;
+    }
+}
+
+void throwDeducedSecureElementException(ExceptionBase& e, const std::string &hint) {
+    const int errorCode = e.getErrorCode();
+    switch (errorCode)
+    {
+    case SCARD_ERROR_OK :
+        /* do nothing */
+        break;
+    case SCARD_ERROR_IPC_FAILED :
+    case SCARD_ERROR_IO_FAILED :
+    case SCARD_ERROR_OPERATION_TIMEOUT :
+        throwSecureElementException<IOException>(errorCode, hint);
+        break;
+    case SCARD_ERROR_SECURITY_NOT_ALLOWED :
+        throwSecureElementException<SecurityException>(errorCode, hint);
+        break;
+    case SCARD_ERROR_UNAVAILABLE :
+    case SCARD_ERROR_NOT_SUPPORTED :
+    case SCARD_ERROR_NOT_INITIALIZED :
+    case SCARD_ERROR_SE_NOT_INITIALIZED :
+    case SCARD_ERROR_ILLEGAL_STATE :
+    case SCARD_ERROR_OPERATION_NOT_SUPPORTED :
+        throwSecureElementException<BasePlatformException>(errorCode, hint);
+        break;
+    case SCARD_ERROR_ILLEGAL_PARAM :
+    case SCARD_ERROR_ILLEGAL_REFERENCE :
+        throwSecureElementException<InvalidValuesException>(errorCode, hint);
+        break;
+    default :
+        throwSecureElementException<UnknownException>(errorCode, hint);
+        break;
+    }
+}
+
+std::string getSecureElementLogMessage(const int errorCode, const std::string &hint){
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getSecureElementErrorMessage(errorCode)
+                    << ", " << errorCode;
+    return std::string(ss.str());
+}
+
+template <>
+void throwSecureElementException<DeviceAPI::Common::BasePlatformException>(
+        const int errorCode, const std::string &hint){
+    std::string log = getSecureElementLogMessage(errorCode, hint);
+    LOGE("%s", log.c_str());
+    throw DeviceAPI::Common::BasePlatformException(INVALID_STATE_EXCEPTION_MESSAGE.c_str(), log.c_str());
+}
+
+}
+}
diff --git a/src/SecureElement/SEUtils.h b/src/SecureElement/SEUtils.h
new file mode 100644 (file)
index 0000000..135c7f9
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __TIZEN_SECURE_ELEMENT_UTILS_H__
+#define __TIZEN_SECURE_ELEMENT_UTILS_H__
+
+#include <PlatformException.h>
+#include <string>
+#include <Logger.h>
+#include <vector>
+#include <Exception.h>
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+template <class JSType, class NativeTypePtr>
+JSObjectRef ptrVectorToJSObjectArray(const std::vector<NativeTypePtr> &objs,
+        JSContextRef context) {
+
+    unsigned int size = objs.size();
+
+    JSObjectRef objArray[size];
+    for(unsigned int i = 0 ; i < size; i++) {
+        objArray[i] = JSType::makeJSObject(context, objs[i]);
+    }
+
+    JSValueRef exception = NULL;
+    JSObjectRef jsResult = JSObjectMakeArray(context, size,
+            size > 0 ? objArray : NULL, &exception);
+    if (NULL != exception) {
+        LOGE("Exception occured");
+        throw Common::UnknownException(context, exception);
+    }
+
+    return jsResult;
+}
+
+const std::string& getSecureElementErrorMessage(const int errorCode);
+void throwDeducedSecureElementException(smartcard_service_api::ExceptionBase& e,
+        const std::string &hint);
+std::string getSecureElementLogMessage(const int errorCode, const std::string &hint);
+
+template <class T>
+void throwSecureElementException(const int errorCode, const std::string &hint){
+    std::string log = getSecureElementLogMessage(errorCode, hint);
+    LOGE("%s", log.c_str());
+    throw T(log.c_str());
+}
+
+template <>
+void throwSecureElementException<DeviceAPI::Common::BasePlatformException>(
+        const int errorCode, const std::string &hint);
+
+}
+}
+
+#endif
diff --git a/src/SecureElement/Session.cpp b/src/SecureElement/Session.cpp
new file mode 100755 (executable)
index 0000000..d2d94e8
--- /dev/null
@@ -0,0 +1,269 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Logger.h>
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+
+#include "Session.h"
+#include "SEUtils.h"
+#include "JSChannel.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace smartcard_service_api;
+using namespace DeviceAPI::Common;
+
+namespace {
+struct ChannelCallbackHolder {
+    ChannelCallbackHolder(ChannelCallbackDataPtr callback, Session* session)
+    {
+        ptr = callback;
+        this->session = session;
+    }
+    ChannelCallbackDataPtr ptr;
+    Session* session;
+};
+}
+
+Session::Session(smartcard_service_api::Session* session)
+{
+    LOGD("Entered");
+    if (NULL == session){
+        LOGE("Session is null");
+        throw Common::UnknownException("Session is null");
+    }
+    m_session = session;
+}
+
+Session::~Session()
+{
+    LOGD("Entered");
+    close();
+    m_session = NULL;
+}
+
+void Session::openChannel(ChannelCallbackDataPtr callback)
+{
+    LOGD("Entered");
+    ChannelCallbackHolder* holder = new ChannelCallbackHolder(callback, this);
+    pthread_t thread;
+    if(pthread_create(&thread, NULL, threadWorker,
+            static_cast<void*>(holder))) {
+        LOGE("Thread creation failed");
+        delete holder;
+        throw UnknownException("Thread creation failed");
+    }
+
+    if(pthread_detach(thread)) {
+        LOGE("Thread detachment failed");
+    }
+}
+
+void* Session::threadWorker(void* data)
+{
+    auto holder = static_cast<ChannelCallbackHolder*>(data);
+    if (!holder) {
+        LOGE("Holder is null");
+        return NULL;
+    }
+
+    auto callback = holder->ptr;
+    if (!callback) {
+        LOGE("Callback is null");
+        delete holder;
+        holder = NULL;
+        return NULL;
+    }
+
+    auto session = holder->session;
+    if(!session){
+        LOGE("Session is null");
+        delete holder;
+        holder = NULL;
+        return NULL;
+    }
+
+    try {
+
+        if (callback->isBasicChannel()) {
+            try {
+                Channel* channel = session->m_session->openBasicChannelSync(
+                        ByteArray(callback->getAid()->data(), callback->getAid()->size()));
+                SEChannelPtr channel_ptr(new SEChannel(channel));
+                callback->setChannel(channel_ptr);
+            }
+            catch (ExceptionBase& e) {
+                LOGE("Error thrown, code: %d", e.getErrorCode());
+                throwDeducedSecureElementException(e, "channel->openBasicChannelSync()");
+            }
+        }
+        else {
+            try {
+                Channel* channel = session->m_session->openLogicalChannelSync(
+                        ByteArray(callback->getAid()->data(), callback->getAid()->size()));
+                SEChannelPtr channel_ptr(new SEChannel(channel));
+                callback->setChannel(channel_ptr);
+            }
+            catch (ExceptionBase& e) {
+                LOGE("Error thrown, code: %d", e.getErrorCode());
+                throwDeducedSecureElementException(e, "channel->openLogicalChannelSync()");
+            }
+        }
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("error during execution threadWorker, %s, %s",
+                e.getName().c_str(), e.getMessage().c_str());
+        callback->setError(e.getName(), e.getMessage());
+    }
+    catch(...){
+        LOGE("error during openChannel");
+        callback->setError("UnknownError", "UnknownError");
+    }
+
+    guint id = g_idle_add(gidleWorker, data);
+    if(!id){
+        LOGE("g_idle_add fails");
+        delete holder;
+    }
+
+    return NULL;
+}
+gboolean Session::gidleWorker(void *data)
+{
+    auto holder = static_cast<ChannelCallbackHolder*>(data);
+    if (!holder) {
+        LOGE("Holder is null");
+        return false;
+    }
+
+    auto callback = holder->ptr;
+    if (!callback) {
+        LOGE("Callback is null");
+        delete holder;
+        holder = NULL;
+        return false;
+    }
+
+    auto session = holder->session;
+    if(!session){
+        LOGE("Session is null");
+        delete holder;
+        holder= NULL;
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete holder;
+        holder = NULL;
+        return false;
+    }
+
+    try {
+        if (callback->isError()) {
+            JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context,
+                    callback->getErrorName(),
+                    callback->getErrorMessage());
+            callback->callErrorCallback(error);
+        }
+        else {
+            JSValueRef obj = JSChannel::makeJSObject(context, callback->getChannel());
+            callback->callSuccessCallback(obj);
+        }
+    }
+    catch (const BasePlatformException& e) {
+        LOGE("error during openChannel: %s, %s",
+                e.getName().c_str(), e.getMessage().c_str());
+    } catch(...){
+        LOGE("error during openChannel");
+    }
+
+    delete holder;
+    holder = NULL;
+
+    return false;
+}
+
+UCharVectorPtr Session::getATR() const
+{
+    LOGD("Entered");
+    ByteArray byte_array;
+    UCharVectorPtr to_ret;
+    try{
+        byte_array = m_session->getATRSync();
+        uint8_t* response_buf = byte_array.getBuffer();
+        size_t response_len = byte_array.getLength();
+
+        to_ret = UCharVectorPtr(new UCharVector(response_buf,
+                response_buf + response_len));
+        return to_ret;
+    }catch(ExceptionBase& e){
+        LOGE("Error during getATR(): code %d , msg %s,", e.getErrorCode(), e.what());
+        throw UnknownException(e.what());
+    }
+    catch (...) {
+        LOGE("Error during getATR()");
+        throw UnknownException("Error during getATR()");
+    }
+
+    return to_ret;
+}
+
+void Session::close()
+{
+    LOGD("Entered");
+    try {
+        if (!isClosed()) {
+            m_session->closeSync();
+        }
+    }
+    catch(ExceptionBase& e){
+        LOGE("Error during close(): code %d , msg %s,", e.getErrorCode(), e.what());
+        throw UnknownException(e.what());
+    }
+    catch (...) {
+        LOGE("Error during close()");
+        throw UnknownException("Error during close()");
+    }
+}
+
+void Session::closeChannels()
+{
+    LOGD("Entered");
+    try {
+        m_session->closeChannels();
+    }
+    catch (ExceptionBase& e) {
+        LOGE("Error during closeChannels(): code %d , msg %s,", e.getErrorCode(), e.what());
+        throw UnknownException(e.what());
+    }
+    catch (...) {
+        LOGE("Error during closeChannels()");
+        throw UnknownException("Error during closeChannels()");
+    }
+}
+
+bool Session::isClosed() const
+{
+    LOGD("Entered");
+    return m_session->isClosed();
+}
+
+} // SecureElement
+} // DeviceAPI
diff --git a/src/SecureElement/Session.h b/src/SecureElement/Session.h
new file mode 100755 (executable)
index 0000000..eb72ce6
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef _TIZEN_SECUREELEMENT_SESSION_H__
+#define _TIZEN_SECUREELEMENT_SESSION_H__
+
+#include <vector>
+#include <Security.h>
+#include <Session.h> // Core API
+#include "SEChannel.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+class Session;
+typedef std::shared_ptr<Session> SessionPtr;
+
+class Session : public DeviceAPI::Common::SecurityAccessor
+{
+public:
+    Session(smartcard_service_api::Session* session);
+    virtual ~Session();
+    void openChannel(ChannelCallbackDataPtr callback);
+    UCharVectorPtr getATR() const;
+    void close();
+    void closeChannels();
+    bool isClosed() const;
+private:
+    static void* threadWorker(void* data);
+    static gboolean gidleWorker(void *data);
+    smartcard_service_api::Session* m_session;
+};
+
+} // SecureElement
+} // DeviceAPI
+
+#endif /* _TIZEN_SECUREELEMENT_SESSION_H__ */
diff --git a/src/SecureElement/config.xml b/src/SecureElement/config.xml
new file mode 100755 (executable)
index 0000000..0c4b9dd
--- /dev/null
@@ -0,0 +1,17 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-secureelement.so</library-name>
+    <feature-install-uri>secureelement.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/secureelement</name>
+        <device-capability>secureelement</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/se</name>
+        <device-capability>se</device-capability>
+    </api-feature>
+</plugin-properties>
+
diff --git a/src/SecureElement/plugin_config.cpp b/src/SecureElement/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..57f0ef2
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <map>
+#include <Commons/FunctionDefinition.h>
+
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+namespace{
+const char* SECUREELEMENT_FEATURE_API_SECUREELEMENT = "http://tizen.org/privilege/secureelement";
+const char* SECUREELEMENT_FEATURE_API_SE = "http://tizen.org/privilege/se";
+
+const char* SECUREELEMENT_DEVICE_CAP_SECUREELEMENT = "secureelement";
+const char* SECUREELEMENT_DEVICE_CAP_SE = "se";
+}
+
+using namespace WrtDeviceApis::Commons;
+
+static FunctionMapping createSecureElementFunctions();
+
+static FunctionMapping SecureElementFunctions =
+        createSecureElementFunctions();
+
+#pragma GCC visibility push(default)
+DEFINE_FUNCTION_GETTER(SecureElement, SecureElementFunctions);
+#pragma GCC visibility pop
+
+static FunctionMapping createSecureElementFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_SECUREELEMENT, SECUREELEMENT_DEVICE_CAP_SECUREELEMENT);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_SE, SECUREELEMENT_DEVICE_CAP_SE);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_SECUREELEMENT);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_SECUREELEMENT, DEVICE_CAP_SECUREELEMENT);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_SECUREELEMENT, DEVICE_CAP_SE);
+
+    /**
+     * API features
+     */
+    ACE_CREATE_FEATURE(FEATURE_SECUREELEMENT, SECUREELEMENT_FEATURE_API_SECUREELEMENT);
+    ACE_CREATE_FEATURE(FEATURE_SE, SECUREELEMENT_FEATURE_API_SE);
+
+    ACE_CREATE_FEATURE_LIST(SECUREELEMENT_FEATURES_SECUREELEMENT);
+    ACE_ADD_API_FEATURE(SECUREELEMENT_FEATURES_SECUREELEMENT, FEATURE_SECUREELEMENT);
+    ACE_ADD_API_FEATURE(SECUREELEMENT_FEATURES_SECUREELEMENT, FEATURE_SE);
+
+    /**
+     * Functions
+     */
+    FunctionMapping SecureElementFunctions;
+
+    AceFunction seFunctions = ACE_CREATE_FUNCTION(
+            FUNCTION_SECUREELEMENT_FUNCTIONS,
+            SECUREELEMENT_FUNCTION_API_FUNCS,
+            SECUREELEMENT_FEATURES_SECUREELEMENT,
+            DEVICE_LIST_SECUREELEMENT);
+
+    SecureElementFunctions.insert(std::make_pair(
+            SECUREELEMENT_FUNCTION_API_FUNCS,
+            seFunctions));
+
+    return SecureElementFunctions;
+}
+} 
+} 
diff --git a/src/SecureElement/plugin_config.h b/src/SecureElement/plugin_config.h
new file mode 100755 (executable)
index 0000000..5eeb7be
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _SECUREELEMENT_PLUGIN_CONFIG_H_
+#define _SECUREELEMENT_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+#define SECUREELEMENT_FUNCTION_API_FUNCS "SecureElementFunctions"
+
+DECLARE_FUNCTION_GETTER(SecureElement);
+
+#define SECURE_ELEMENT_CHECK_ACCESS(functionName) \
+        aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+                getSecureElementFunctionData, \
+                functionName)
+}
+}
+
+#endif //  _SECUREELEMENT_PLUGIN_CONFIG_H_
diff --git a/src/SecureElement/plugin_config_impl.h b/src/SecureElement/plugin_config_impl.h
new file mode 100644 (file)
index 0000000..d275282
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef _SECUREELEMENT_PLUGIN_CONFIG_IMPL_H_
+#define _SECUREELEMENT_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_SECUREELEMENT_SE_SERVICE "seService"
+
+#endif //  _SECUREELEMENT_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/SecureElement/plugin_initializer.cpp b/src/SecureElement/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..04e9756
--- /dev/null
@@ -0,0 +1,79 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include "JSSEService.h"
+#include <Logger.h>
+#include <TimeTracer.h>
+
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace SecureElement {
+
+using namespace WrtDeviceApis::Commons;
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[TIZEN\\SE] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    }
+    catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[TIZEN\\SE ] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "SecureElement";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    }
+    catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\SE] on_frame_unload_callback ( %p )", context);
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\SE] on_frame_unload_callback ( %p )", context);
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_SECUREELEMENT_SE_SERVICE,
+        (js_class_template_getter)JSSEService::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_END
+
+} // SecureElement
+} // DeviceAPI
diff --git a/src/Sensor/CMakeLists.txt b/src/Sensor/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..8aba654
--- /dev/null
@@ -0,0 +1,50 @@
+SET(TARGET_NAME ${sensor_target})
+SET(DESTINATION_NAME ${sensor_dest})
+SET(TARGET_IMPL_NAME ${sensor_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_sensor REQUIRED capi-system-sensor)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_sensor_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSSensorService.cpp
+    SensorService.cpp
+    JSSensorData.cpp
+    SensorData.cpp
+    SensorUtil.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${platform_pkgs_sensor_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/sensor
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Sensor/JSSensorData.cpp b/src/Sensor/JSSensorData.cpp
new file mode 100755 (executable)
index 0000000..4b60690
--- /dev/null
@@ -0,0 +1,478 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+
+#include "plugin_config.h"
+#include "JSSensorData.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sensor {
+
+JSClassDefinition JSLightData::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "LightData",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSLightData::m_property[] = {
+    { TIZEN_LIGHT_DATA_LIGHT_LEVEL, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSLightData::m_jsClassRef = JSClassCreate(JSLightData::getClassInfo());
+
+const JSClassRef JSLightData::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSLightData::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSLightData::createJSObject(JSContextRef context, LightData* lightData)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(lightData));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+    return jsValueRef;
+}
+
+
+void JSLightData::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+
+}
+
+void JSLightData::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+    LightData* priv = static_cast<LightData*>(JSObjectGetPrivate(object));
+    if (priv) {
+        delete priv;
+    }
+}
+
+JSValueRef JSLightData::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    LOGD("enter");
+    double value = 0;
+    LightData* priv = static_cast<LightData*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Private object is NULL");
+        throw TypeMismatchException("Private object is NULL");
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_LIGHT_DATA_LIGHT_LEVEL)) {
+        value = priv->getLightLevel();
+        return JSUtil::toJSValueRef(context, value);
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+
+//Proximity
+JSClassDefinition JSProximityData::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "ProximityData",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSProximityData::m_property[] = {
+    { TIZEN_PROXIMITY_DATA_PROXIMITY_LEVEL, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSProximityData::m_jsClassRef = JSClassCreate(JSProximityData::getClassInfo());
+
+const JSClassRef JSProximityData::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSProximityData::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSProximityData::createJSObject(JSContextRef context, ProximityData* proximityData)
+{
+    LOGD("enter : %d",proximityData->getProximityLevel());
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(proximityData));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+    return jsValueRef;
+}
+
+
+void JSProximityData::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+void JSProximityData::finalize(JSObjectRef object)
+{
+    ProximityData* priv = static_cast<ProximityData*>(JSObjectGetPrivate(object));
+    if (priv) {
+        delete priv;
+    }
+}
+
+JSValueRef JSProximityData::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    int value = 0;
+    std::string proximityLevel("");
+    LOGD("enter");
+
+    ProximityData* priv = static_cast<ProximityData*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is NULL");
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PROXIMITY_DATA_PROXIMITY_LEVEL)) {
+        value = priv->getProximityLevel();
+        if(value){
+            proximityLevel.append("NEAR");
+        }else{
+            proximityLevel.append("FAR");
+        }
+        return JSUtil::toJSValueRef(context, proximityLevel);
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+// Magnetic
+JSClassDefinition JSMagneticData::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "MagneticData",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSMagneticData::m_property[] = {
+    { TIZEN_PROXIMITY_DATA_MAGNETIC_X, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PROXIMITY_DATA_MAGNETIC_Y, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PROXIMITY_DATA_MAGNETIC_Z, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { TIZEN_PROXIMITY_DATA_MAGNETIC_ACCURACY, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSMagneticData::m_jsClassRef = JSClassCreate(JSMagneticData::getClassInfo());
+
+const JSClassRef JSMagneticData::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSMagneticData::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSMagneticData::createJSObject(JSContextRef context, MagneticData* magneticData)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(magneticData));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+    return jsValueRef;
+}
+
+
+void JSMagneticData::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+void JSMagneticData::finalize(JSObjectRef object)
+{
+    MagneticData* priv = static_cast<MagneticData*>(JSObjectGetPrivate(object));
+    if (priv) {
+        delete priv;
+    }
+}
+
+JSValueRef JSMagneticData::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    double value = 0;
+    std::string accuracy("");
+
+    MagneticData* priv = static_cast<MagneticData*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is NULL");
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PROXIMITY_DATA_MAGNETIC_X)) {
+        value = priv->getMagneticX();
+        return JSUtil::toJSValueRef(context, value);
+    }else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PROXIMITY_DATA_MAGNETIC_Y)) {
+        value = priv->getMagneticY();
+        return JSUtil::toJSValueRef(context, value);
+    }else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PROXIMITY_DATA_MAGNETIC_Z)) {
+        value = priv->getMagneticZ();
+        return JSUtil::toJSValueRef(context, value);
+    }else if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PROXIMITY_DATA_MAGNETIC_ACCURACY)) {
+        accuracy.append(priv->getMagneticAccuracy());
+        return JSUtil::toJSValueRef(context, accuracy);
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+
+// Pressure
+
+JSClassDefinition JSPressureData::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "PressureData",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSPressureData::m_property[] = {
+    { TIZEN_PRESSURE_DATA_PRESSURE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSPressureData::m_jsClassRef = JSClassCreate(JSPressureData::getClassInfo());
+
+const JSClassRef JSPressureData::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSPressureData::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSPressureData::createJSObject(JSContextRef context, PressureData* pressureData)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(pressureData));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+    return jsValueRef;
+}
+
+
+void JSPressureData::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+void JSPressureData::finalize(JSObjectRef object)
+{
+    PressureData* priv = static_cast<PressureData*>(JSObjectGetPrivate(object));
+    if (priv) {
+        delete priv;
+    }
+}
+
+JSValueRef JSPressureData::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    double value = 0;
+    LOGD("enter");
+
+    PressureData* priv = static_cast<PressureData*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is NULL");
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_PRESSURE_DATA_PRESSURE)) {
+        value = priv->getPressure();
+        return JSUtil::toJSValueRef(context, value);
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+// Ultraviolet
+JSClassDefinition JSUltravioletData::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "UltravioletData",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    NULL, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //getProperty, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSUltravioletData::m_property[] = {
+    { TIZEN_ULTRAVIOLET_DATA_ULTRAVIOLET_LEVEL, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSUltravioletData::m_jsClassRef = JSClassCreate(JSUltravioletData::getClassInfo());
+
+const JSClassRef JSUltravioletData::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSUltravioletData::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSUltravioletData::createJSObject(JSContextRef context, UltravioletData* ultravioletData)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(ultravioletData));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+    return jsValueRef;
+}
+
+
+void JSUltravioletData::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+
+}
+
+void JSUltravioletData::finalize(JSObjectRef object)
+{
+    UltravioletData* priv = static_cast<UltravioletData*>(JSObjectGetPrivate(object));
+    if (priv) {
+        delete priv;
+    }
+}
+
+JSValueRef JSUltravioletData::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    double value = 0;
+    UltravioletData* priv = static_cast<UltravioletData*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        throw TypeMismatchException("Private object is NULL");
+    }
+
+    if (JSStringIsEqualToUTF8CString(propertyName, TIZEN_ULTRAVIOLET_DATA_ULTRAVIOLET_LEVEL)) {
+        value = priv->getUltraviolet();
+        return JSUtil::toJSValueRef(context, value);
+    }
+    return JSValueMakeUndefined(context);
+
+}
+
+} // Sensor
+} // DeviceAPI
diff --git a/src/Sensor/JSSensorData.h b/src/Sensor/JSSensorData.h
new file mode 100755 (executable)
index 0000000..78400fc
--- /dev/null
@@ -0,0 +1,210 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_SENSOR_DATA_H__
+#define __TIZEN_JS_SENSOR_DATA_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "SensorData.h"
+
+namespace DeviceAPI {
+namespace Sensor {
+
+class JSLightData
+{
+    public:
+        static const JSClassDefinition* getClassInfo();
+        static const JSClassRef getClassRef();
+        static JSValueRef createJSObject(JSContextRef context, LightData* lightData);
+        static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    private:
+
+        /**
+         * The callback invoked when an object is first created.
+         */
+        static void initialize(JSContextRef context, JSObjectRef object);
+
+        /**
+         * The callback invoked when an object is finalized.
+         */
+        static void finalize(JSObjectRef object);
+
+        /**
+         * This member variable contains the values which has to be passed
+         * when the this class is embedded into JS Engine.
+         */
+        static JSClassDefinition m_classInfo;
+
+        /**
+         * This member variable contains the initialization values for the
+         * properties of this class. The values are given according to
+         * the data structure JSPropertySpec
+         */
+        static JSStaticValue m_property[];
+
+        static JSClassRef m_jsClassRef;
+};
+
+
+class JSProximityData
+{
+    public:
+        static const JSClassDefinition* getClassInfo();
+        static const JSClassRef getClassRef();
+        static JSValueRef createJSObject(JSContextRef context, ProximityData* proximityData);
+        static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    private:
+
+        /**
+         * The callback invoked when an object is first created.
+         */
+        static void initialize(JSContextRef context, JSObjectRef object);
+
+        /**
+         * The callback invoked when an object is finalized.
+         */
+        static void finalize(JSObjectRef object);
+
+        /**
+         * This member variable contains the values which has to be passed
+         * when the this class is embedded into JS Engine.
+         */
+        static JSClassDefinition m_classInfo;
+
+        /**
+         * This member variable contains the initialization values for the
+         * properties of this class. The values are given according to
+         * the data structure JSPropertySpec
+         */
+        static JSStaticValue m_property[];
+
+        static JSClassRef m_jsClassRef;
+};
+
+
+class JSMagneticData
+{
+    public:
+        static const JSClassDefinition* getClassInfo();
+        static const JSClassRef getClassRef();
+        static JSValueRef createJSObject(JSContextRef context, MagneticData* magneticData);
+        static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    private:
+
+        /**
+         * The callback invoked when an object is first created.
+         */
+        static void initialize(JSContextRef context, JSObjectRef object);
+
+        /**
+         * The callback invoked when an object is finalized.
+         */
+        static void finalize(JSObjectRef object);
+
+        /**
+         * This member variable contains the values which has to be passed
+         * when the this class is embedded into JS Engine.
+         */
+        static JSClassDefinition m_classInfo;
+
+        /**
+         * This member variable contains the initialization values for the
+         * properties of this class. The values are given according to
+         * the data structure JSPropertySpec
+         */
+        static JSStaticValue m_property[];
+
+        static JSClassRef m_jsClassRef;
+};
+
+class JSPressureData
+{
+    public:
+        static const JSClassDefinition* getClassInfo();
+        static const JSClassRef getClassRef();
+        static JSValueRef createJSObject(JSContextRef context, PressureData* pressureData);
+        static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    private:
+
+        /**
+         * The callback invoked when an object is first created.
+         */
+        static void initialize(JSContextRef context, JSObjectRef object);
+
+        /**
+         * The callback invoked when an object is finalized.
+         */
+        static void finalize(JSObjectRef object);
+
+        /**
+         * This member variable contains the values which has to be passed
+         * when the this class is embedded into JS Engine.
+         */
+        static JSClassDefinition m_classInfo;
+
+        /**
+         * This member variable contains the initialization values for the
+         * properties of this class. The values are given according to
+         * the data structure JSPropertySpec
+         */
+        static JSStaticValue m_property[];
+
+        static JSClassRef m_jsClassRef;
+};
+
+
+class JSUltravioletData
+{
+    public:
+        static const JSClassDefinition* getClassInfo();
+        static const JSClassRef getClassRef();
+        static JSValueRef createJSObject(JSContextRef context, UltravioletData* ultravioletData);
+        static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+    private:
+
+        /**
+         * The callback invoked when an object is first created.
+         */
+        static void initialize(JSContextRef context, JSObjectRef object);
+
+        /**
+         * The callback invoked when an object is finalized.
+         */
+        static void finalize(JSObjectRef object);
+
+        /**
+         * This member variable contains the values which has to be passed
+         * when the this class is embedded into JS Engine.
+         */
+        static JSClassDefinition m_classInfo;
+
+
+        /**
+         * This member variable contains the initialization values for the
+         * properties of this class. The values are given according to
+         * the data structure JSPropertySpec
+         */
+        static JSStaticValue m_property[];
+
+        static JSClassRef m_jsClassRef;
+};
+
+} // Sensor
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Sensor/JSSensorService.cpp b/src/Sensor/JSSensorService.cpp
new file mode 100755 (executable)
index 0000000..d740b6c
--- /dev/null
@@ -0,0 +1,1339 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <SecurityExceptions.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "plugin_config.h"
+#include "JSSensorService.h"
+#include "SensorService.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sensor {
+
+JSClassDefinition JSSensorService::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "SensorService",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSSensorService::m_function[] = {
+    { SENSOR_SERVICE_API_GET_DEFAULT_SENSOR, getDefaultSensor, kJSPropertyAttributeNone },
+    { SENSOR_SERVICE_API_GET_AVAILABLE_SENSOR, getAvailableSensor, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSSensorService::m_jsClassRef = JSClassCreate(JSSensorService::getClassInfo());
+
+const JSClassRef JSSensorService::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSSensorService::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSSensorService::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+void JSSensorService::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+JSValueRef JSSensorService::getDefaultSensor(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        LOGD("enter");
+
+        bool supported = false;
+        ArgumentValidator validator(context, argumentCount, arguments);
+        std::string sensorType = validator.toString(0);
+        std::string proximityType = "PROXIMITY";
+        std::string lightType = "LIGHT";
+        std::string magneticType = "MAGNETIC";
+        std::string pressureType = "PRESSURE";
+        std::string ultravioletType = "ULTRAVIOLET";
+
+        // perform
+        if(proximityType.compare(sensorType) == 0){
+            ProximitySensor* proximitySensor = ProximitySensor::getInstance();
+
+            supported = proximitySensor->isSupported();
+            if(false == supported){
+                LOGE("Not supported");
+                throw NotSupportedException("Not supported");
+            }
+
+            JSValueRef proximityRef = JSProximitySensor::createJSObject(GlobalContextManager::getInstance()->getGlobalContext(context), proximitySensor);
+            return proximityRef;
+        }else if(lightType.compare(sensorType) == 0){
+            LightSensor* lightSensor = LightSensor::getInstance();
+
+            supported = lightSensor->isSupported();
+            if(false == supported){
+                LOGE("Not supported");
+                throw NotSupportedException("Not supported");
+            }
+
+            JSValueRef lightRef = JSLightSensor::createJSObject(GlobalContextManager::getInstance()->getGlobalContext(context), lightSensor);
+            return lightRef;
+        }else if(magneticType.compare(sensorType) == 0){
+            MagneticSensor* magneticSensor = MagneticSensor::getInstance();
+
+            supported = magneticSensor->isSupported();
+            if(false == supported){
+                LOGE("Not supported");
+                throw NotSupportedException("Not supported");
+            }
+
+            JSValueRef magneticRef = JSMagneticSensor::createJSObject(GlobalContextManager::getInstance()->getGlobalContext(context), magneticSensor);
+            return magneticRef;
+        }else if(pressureType.compare(sensorType) == 0){
+            PressureSensor* pressureSensor = PressureSensor::getInstance();
+
+            supported = pressureSensor->isSupported();
+            if(false == supported){
+                LOGE("Not supported");
+                throw NotSupportedException("Not supported");
+            }
+
+            JSValueRef pressureRef = JSPressureSensor::createJSObject(GlobalContextManager::getInstance()->getGlobalContext(context), pressureSensor);
+            return pressureRef;
+        }else if(ultravioletType.compare(sensorType) == 0){
+            UltravioletSensor* ultravioletSensor = UltravioletSensor::getInstance();
+
+            supported = ultravioletSensor->isSupported();
+            if(false == supported){
+                LOGE("Not supported");
+                throw NotSupportedException("Not supported");
+            }
+
+            JSValueRef uvsensorRef = JSUltravioletSensor::createJSObject(GlobalContextManager::getInstance()->getGlobalContext(context), ultravioletSensor);
+            return uvsensorRef;
+        }else{
+            LOGE("argument type mismatch");
+            throw TypeMismatchException("argument type mismatch");
+        }
+
+    } catch (const TypeMismatchException &err) {
+        LOGE("Type Mismatch Exception");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSSensorService::getAvailableSensor(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        LOGD("enter");
+        return SensorService::getInstance()->getAvailableSensor(GlobalContextManager::getInstance()->getGlobalContext(context));
+    } catch (const TypeMismatchException &err) {
+        LOGE("Type Mismatch Exception");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+// Proximity
+JSClassDefinition JSProximitySensor::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "ProximitySensor",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSProximitySensor::m_property[] = {
+    { SENSOR_ATTRIBUTE_SENSOR_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+
+JSStaticFunction JSProximitySensor::m_function[] = {
+    { SENSOR_API_START, start, kJSPropertyAttributeNone },
+    { SENSOR_API_STOP, stop, kJSPropertyAttributeNone },
+    { SENSOR_API_SET_CHANGE_LISTENER, setChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_UNSET_CHANGE_LISTENER, unsetChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_GET_PROXIMITY_SENSOR_DATA, getSensorData, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSProximitySensor::m_jsClassRef = JSClassCreate(JSProximitySensor::getClassInfo());
+
+const JSClassRef JSProximitySensor::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSProximitySensor::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSProximitySensor::createJSObject(JSContextRef context, ProximitySensor* proximitySensor)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(proximitySensor));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    return jsValueRef;
+}
+
+
+void JSProximitySensor::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+void JSProximitySensor::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+JSValueRef JSProximitySensor::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    std::string sensorType("");
+    LOGD("enter");
+
+    if (JSStringIsEqualToUTF8CString(propertyName, SENSOR_ATTRIBUTE_SENSOR_TYPE)) {
+        sensorType.append("PROXIMITY");
+        return JSUtil::toJSValueRef(context, sensorType);
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSProximitySensor::start(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        ProximitySuccessCallbackPtr proximityCB(new ProximitySuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            proximityCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            proximityCB->setErrorCallback(errorCB);
+        }
+
+        ProximitySensor::getInstance()->start(proximityCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSProximitySensor::stop(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ProximitySensor::getInstance()->stop(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSProximitySensor::setChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        ProximitySuccessCallbackPtr proximityCB(new ProximitySuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            proximityCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            proximityCB->setErrorCallback(errorCB);
+        }
+
+        ProximitySensor::getInstance()->setChangeListener(proximityCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+
+
+}
+
+JSValueRef JSProximitySensor::unsetChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ProximitySensor::getInstance()->unsetChangeListener(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+
+}
+
+JSValueRef JSProximitySensor::getSensorData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        ProximitySuccessCallbackPtr proximityCB(new ProximitySuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            proximityCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            proximityCB->setErrorCallback(errorCB);
+        }
+
+        ProximitySensor::getInstance()->getSensorData(proximityCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+// Light
+JSClassDefinition JSLightSensor::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "LightSensor",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSLightSensor::m_function[] = {
+    { SENSOR_API_START, start, kJSPropertyAttributeNone },
+    { SENSOR_API_STOP, stop, kJSPropertyAttributeNone },
+    { SENSOR_API_SET_CHANGE_LISTENER, setChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_UNSET_CHANGE_LISTENER, unsetChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_GET_LIGHT_SENSOR_DATA, getSensorData, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSStaticValue JSLightSensor::m_property[] = {
+    { SENSOR_ATTRIBUTE_SENSOR_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+JSClassRef JSLightSensor::m_jsClassRef = JSClassCreate(JSLightSensor::getClassInfo());
+
+const JSClassRef JSLightSensor::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSLightSensor::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSLightSensor::createJSObject(JSContextRef context, LightSensor* sensor)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(sensor));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    return jsValueRef;
+}
+
+
+void JSLightSensor::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+void JSLightSensor::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+JSValueRef JSLightSensor::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    std::string sensorType("");
+    LOGD("enter");
+
+    if (JSStringIsEqualToUTF8CString(propertyName, SENSOR_ATTRIBUTE_SENSOR_TYPE)) {
+        sensorType.append("LIGHT");
+        return JSUtil::toJSValueRef(context, sensorType);
+    }
+    return JSValueMakeUndefined(context);
+}
+
+
+JSValueRef JSLightSensor::start(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        LightSuccessCallbackPtr lightCB(new LightSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            lightCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            lightCB->setErrorCallback(errorCB);
+        }
+
+        LightSensor::getInstance()->start(lightCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSLightSensor::stop(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        LightSensor::getInstance()->stop(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSLightSensor::setChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        LightSuccessCallbackPtr lightCB(new LightSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            lightCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            lightCB->setErrorCallback(errorCB);
+        }
+
+        LightSensor::getInstance()->setChangeListener(lightCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+
+
+}
+
+JSValueRef JSLightSensor::unsetChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        LightSensor::getInstance()->unsetChangeListener(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSLightSensor::getSensorData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        LightSuccessCallbackPtr lightCB(new LightSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            lightCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            lightCB->setErrorCallback(errorCB);
+        }
+
+        LightSensor::getInstance()->getSensorData(lightCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+// Magnetic
+JSClassDefinition JSMagneticSensor::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "MagneticSensor",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSMagneticSensor::m_function[] = {
+    { SENSOR_API_START, start, kJSPropertyAttributeNone },
+    { SENSOR_API_STOP, stop, kJSPropertyAttributeNone },
+    { SENSOR_API_SET_CHANGE_LISTENER, setChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_UNSET_CHANGE_LISTENER, unsetChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_GET_MAGNETIC_SENSOR_DATA, getSensorData, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSStaticValue JSMagneticSensor::m_property[] = {
+    { SENSOR_ATTRIBUTE_SENSOR_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+
+JSClassRef JSMagneticSensor::m_jsClassRef = JSClassCreate(JSMagneticSensor::getClassInfo());
+
+const JSClassRef JSMagneticSensor::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSMagneticSensor::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSMagneticSensor::createJSObject(JSContextRef context, MagneticSensor* sensor)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(sensor));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    return jsValueRef;
+}
+
+
+void JSMagneticSensor::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+void JSMagneticSensor::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+
+JSValueRef JSMagneticSensor::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    std::string sensorType("");
+    LOGD("enter");
+
+    if (JSStringIsEqualToUTF8CString(propertyName, SENSOR_ATTRIBUTE_SENSOR_TYPE)) {
+        sensorType.append("MAGNETIC");
+        return JSUtil::toJSValueRef(context, sensorType);
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSMagneticSensor::start(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        MagneticSuccessCallbackPtr magneticCB(new MagneticSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            magneticCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            magneticCB->setErrorCallback(errorCB);
+        }
+
+        MagneticSensor::getInstance()->start(magneticCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSMagneticSensor::stop(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        MagneticSensor::getInstance()->stop(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSMagneticSensor::setChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        MagneticSuccessCallbackPtr magneticCB(new MagneticSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            magneticCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            magneticCB->setErrorCallback(errorCB);
+        }
+
+        MagneticSensor::getInstance()->setChangeListener(magneticCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+
+
+JSValueRef JSMagneticSensor::unsetChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        MagneticSensor::getInstance()->unsetChangeListener(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+
+}
+
+JSValueRef JSMagneticSensor::getSensorData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        MagneticSuccessCallbackPtr magneticCB(new MagneticSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            magneticCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            magneticCB->setErrorCallback(errorCB);
+        }
+
+        MagneticSensor::getInstance()->getSensorData(magneticCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+
+}
+
+// Pressure Sensor
+JSClassDefinition JSPressureSensor::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "PressureSensor",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSPressureSensor::m_function[] = {
+    { SENSOR_API_START, start, kJSPropertyAttributeNone },
+    { SENSOR_API_STOP, stop, kJSPropertyAttributeNone },
+    { SENSOR_API_SET_CHANGE_LISTENER, setChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_UNSET_CHANGE_LISTENER, unsetChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_GET_PRESSURE_SENSOR_DATA, getSensorData, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSStaticValue JSPressureSensor::m_property[] = {
+    { SENSOR_ATTRIBUTE_SENSOR_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+
+JSClassRef JSPressureSensor::m_jsClassRef = JSClassCreate(JSPressureSensor::getClassInfo());
+
+const JSClassRef JSPressureSensor::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSPressureSensor::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+
+JSValueRef JSPressureSensor::createJSObject(JSContextRef context, PressureSensor* sensor)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(sensor));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    return jsValueRef;
+}
+
+
+void JSPressureSensor::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+void JSPressureSensor::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+
+JSValueRef JSPressureSensor::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    std::string sensorType("");
+    LOGD("enter");
+
+    if (JSStringIsEqualToUTF8CString(propertyName, SENSOR_ATTRIBUTE_SENSOR_TYPE)) {
+        sensorType.append("PRESSURE");
+        return JSUtil::toJSValueRef(context, sensorType);
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSPressureSensor::start(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        PressureSuccessCallbackPtr pressureCB(new PressureSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            pressureCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            pressureCB->setErrorCallback(errorCB);
+        }
+
+        PressureSensor::getInstance()->start(pressureCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSPressureSensor::stop(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        PressureSensor::getInstance()->stop(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSPressureSensor::setChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        PressureSuccessCallbackPtr pressureCB(new PressureSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            pressureCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            pressureCB->setErrorCallback(errorCB);
+        }
+
+        PressureSensor::getInstance()->setChangeListener(pressureCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+
+
+JSValueRef JSPressureSensor::unsetChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        PressureSensor::getInstance()->unsetChangeListener(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSPressureSensor::getSensorData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("enter");
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        PressureSuccessCallbackPtr pressureCB(new PressureSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            pressureCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            pressureCB->setErrorCallback(errorCB);
+        }
+
+        PressureSensor::getInstance()->getSensorData(pressureCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+//JSUltravioletSensor
+JSClassDefinition JSUltravioletSensor::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "UltravioletSensor",
+    NULL, //ParentClass
+    m_property, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticValue JSUltravioletSensor::m_property[] = {
+    { SENSOR_ATTRIBUTE_SENSOR_TYPE, getProperty, NULL, kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+
+
+JSStaticFunction JSUltravioletSensor::m_function[] = {
+    { SENSOR_API_START, start, kJSPropertyAttributeNone },
+    { SENSOR_API_STOP, stop, kJSPropertyAttributeNone },
+    { SENSOR_API_SET_CHANGE_LISTENER, setChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_UNSET_CHANGE_LISTENER, unsetChangeListener, kJSPropertyAttributeNone },
+    { SENSOR_API_GET_ULTRAVIOLET_SENSOR_DATA, getSensorData, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSUltravioletSensor::m_jsClassRef = JSClassCreate(JSUltravioletSensor::getClassInfo());
+
+const JSClassRef JSUltravioletSensor::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSUltravioletSensor::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSValueRef JSUltravioletSensor::createJSObject(JSContextRef context, UltravioletSensor* sensor)
+{
+    JSObjectRef jsValueRef = JSObjectMake(context, getClassRef(), static_cast<void*>(sensor));
+    if (NULL == jsValueRef) {
+        LOGE("object creation error");
+        return JSValueMakeUndefined(context);
+    }
+
+    return jsValueRef;
+}
+
+void JSUltravioletSensor::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+void JSUltravioletSensor::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+}
+
+JSValueRef JSUltravioletSensor::getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception)
+{
+    std::string sensorType("");
+    LOGD("enter");
+
+    if (JSStringIsEqualToUTF8CString(propertyName, SENSOR_ATTRIBUTE_SENSOR_TYPE)) {
+        sensorType.append("ULTRAVIOLET");
+        return JSUtil::toJSValueRef(context, sensorType);
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSUltravioletSensor::start(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        UltravioletSuccessCallbackPtr ultravioletCB(new UltravioletSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            ultravioletCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            ultravioletCB->setErrorCallback(errorCB);
+        }
+
+        UltravioletSensor::getInstance()->start(ultravioletCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSUltravioletSensor::stop(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    try{
+        UltravioletSensor::getInstance()->stop(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+JSValueRef JSUltravioletSensor::setChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        UltravioletSuccessCallbackPtr ultravioletCB(new UltravioletSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            ultravioletCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            ultravioletCB->setErrorCallback(errorCB);
+        }
+
+        UltravioletSensor::getInstance()->setChangeListener(ultravioletCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+
+
+JSValueRef JSUltravioletSensor::unsetChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try{
+        UltravioletSensor::getInstance()->unsetChangeListener(GlobalContextManager::getInstance()->getGlobalContext(context));
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+
+}
+
+
+JSValueRef JSUltravioletSensor::getSensorData(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+
+    LOGD("enter");
+
+    try{
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef successCB = validator.toFunction(0);
+
+        UltravioletSuccessCallbackPtr ultravioletCB(new UltravioletSuccessCallback(GlobalContextManager::getInstance()->getGlobalContext(context)));
+        if (successCB) {
+            ultravioletCB->setSuccessCallback(successCB);
+        }
+
+        JSObjectRef errorCB = validator.toFunction(1, true);
+        if(errorCB) {
+            ultravioletCB->setErrorCallback(errorCB);
+        }
+
+        UltravioletSensor::getInstance()->getSensorData(ultravioletCB);
+        return JSValueMakeUndefined(context);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("argument is wrong.");
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+}
+
+
+} // Sensor
+} // DeviceAPI
diff --git a/src/Sensor/JSSensorService.h b/src/Sensor/JSSensorService.h
new file mode 100755 (executable)
index 0000000..8ce2baf
--- /dev/null
@@ -0,0 +1,481 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_SENSOR_SERVICE_H__
+#define __TIZEN_JS_SENSOR_SERVICE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "SensorService.h"
+
+using namespace DeviceAPI::Common;
+
+
+namespace DeviceAPI {
+namespace Sensor {
+
+class JSSensorService
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getDefaultSensor(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getAvailableSensor(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+class JSProximitySensor
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, ProximitySensor* proximitySensor);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef start(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef stop(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getSensorData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+class JSLightSensor
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, LightSensor* sensor);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef start(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef stop(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getSensorData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+class JSMagneticSensor
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, MagneticSensor* sensor);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef start(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef stop(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getSensorData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+
+class JSPressureSensor
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, PressureSensor* sensor);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef start(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef stop(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getSensorData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+class JSUltravioletSensor
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+    static JSValueRef createJSObject(JSContextRef context, UltravioletSensor* sensor);
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSStringRef propertyName, JSValueRef* exception);
+
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef start(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef stop(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getSensorData(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+} // Sensor
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Sensor/SensorData.cpp b/src/Sensor/SensorData.cpp
new file mode 100755 (executable)
index 0000000..2389669
--- /dev/null
@@ -0,0 +1,152 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <math.h>
+
+#include "SensorData.h"
+
+namespace DeviceAPI {
+namespace Sensor {
+
+LightData::LightData(double lux)
+{
+    mLightLevel = lux;
+}
+
+LightData::~LightData()
+{
+}
+
+double LightData::getLightLevel()
+{
+    return mLightLevel;
+}
+
+
+// Proximity
+ProximityData::ProximityData(int proximityLevel)
+{
+    mProximityLevel = proximityLevel;
+}
+
+ProximityData::~ProximityData()
+{
+}
+
+int ProximityData::getProximityLevel()
+{
+    return mProximityLevel;
+}
+
+// Magnetic
+MagneticData::MagneticData(double x, double y, double z, sensor_data_accuracy_e accuracy)
+{
+    LOGD("enter [ %f , %f , %f ][ %d ]",x ,y, z, accuracy);
+
+    mAccuracy = accuracy;
+    mMagneticX = convertSimpleDouble(x);
+    mMagneticY = convertSimpleDouble(y);
+    mMagneticZ = convertSimpleDouble(z);
+}
+
+MagneticData::~MagneticData()
+{
+
+}
+
+double MagneticData::getMagneticX()
+{
+    return mMagneticX;
+}
+
+double MagneticData::getMagneticY()
+{
+    return mMagneticY;
+}
+
+double MagneticData::getMagneticZ()
+{
+    return mMagneticZ;
+}
+
+char* MagneticData::getMagneticAccuracy()
+{
+    LOGD("enter : %d",mAccuracy);
+    if(SENSOR_DATA_ACCURACY_BAD == mAccuracy){
+        return "ACCURACY_BAD";
+    }else if(SENSOR_DATA_ACCURACY_NORMAL == mAccuracy){
+        return "ACCURACY_NORMAL";
+    }else if(SENSOR_DATA_ACCURACY_GOOD == mAccuracy){
+        return "ACCURACY_GOOD";
+    }else if(SENSOR_DATA_ACCURACY_VERYGOOD == mAccuracy){
+        return "ACCURACY_VERYGOOD";
+    }else{
+        return "ACCURACY_UNDEFINED";
+    }
+}
+
+
+double MagneticData::convertSimpleDouble(double origin)
+{
+    return ((int)(origin*pow(10.0,2)))/pow(10.0,2);
+}
+
+// Pressure
+PressureData::PressureData(double pressure)
+{
+    mPressure = convertSimpleDouble(pressure);
+}
+
+PressureData::~PressureData()
+{
+}
+
+double PressureData::getPressure()
+{
+    return mPressure;
+}
+
+double PressureData::convertSimpleDouble(double origin)
+{
+    return ((int)(origin*pow(10.0,2)))/pow(10.0,2);
+}
+
+// Ultraviolet
+UltravioletData::UltravioletData(double ultraviolet)
+{
+    mUltraviolet = convertSimpleDouble(ultraviolet);
+}
+
+UltravioletData::~UltravioletData()
+{
+}
+
+double UltravioletData::getUltraviolet()
+{
+    return mUltraviolet;
+}
+
+double UltravioletData::convertSimpleDouble(double origin)
+{
+    return ((int)(origin*pow(10.0,2)))/pow(10.0,2);
+}
+
+
+} // Sensor
+} // DeviceAPI
diff --git a/src/Sensor/SensorData.h b/src/Sensor/SensorData.h
new file mode 100755 (executable)
index 0000000..b80a6a8
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SENSOR_DATA_H__
+#define __TIZEN_SENSOR_DATA_H__
+
+#include <MultiCallbackUserData.h>
+#include <sensor.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sensor {
+
+class LightData{
+
+    public:
+        LightData(double lux);
+        virtual ~LightData();
+        double getLightLevel();
+
+    private:
+        double mLightLevel;
+
+};
+
+
+class ProximityData{
+
+    public:
+        ProximityData(int proximityLevel);
+        virtual ~ProximityData();
+        int getProximityLevel();
+
+    private:
+        int mProximityLevel;
+
+};
+
+class MagneticData{
+
+    public:
+        MagneticData(double x, double y, double z, sensor_data_accuracy_e accuracy);
+        virtual ~MagneticData();
+        double getMagneticX();
+        double getMagneticY();
+        double getMagneticZ();
+        char* getMagneticAccuracy();
+        double convertSimpleDouble(double origin);
+
+    private:
+        double mMagneticX;
+        double mMagneticY;
+        double mMagneticZ;
+        sensor_data_accuracy_e mAccuracy;
+
+};
+
+class PressureData{
+
+    public:
+        PressureData(double pressure);
+        virtual ~PressureData();
+        double getPressure();
+        double convertSimpleDouble(double origin);
+
+    private:
+        double mPressure;
+
+};
+
+class UltravioletData{
+
+    public:
+        UltravioletData(double ultraviolet);
+        virtual ~UltravioletData();
+        double getUltraviolet();
+        double convertSimpleDouble(double origin);
+
+    private:
+        double mUltraviolet;
+
+};
+
+} // Sensor
+} // DeviceAPI
+
+#endif // __TIZEN_SENSOR_DATA_H__
diff --git a/src/Sensor/SensorService.cpp b/src/Sensor/SensorService.cpp
new file mode 100755 (executable)
index 0000000..a8feaac
--- /dev/null
@@ -0,0 +1,1599 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <JSWebAPIErrorFactory.h>
+#include <Logger.h>
+#include <JSUtil.h>
+#include <sensor.h>
+#include <glib.h>
+
+#include "SensorService.h"
+#include "SensorData.h"
+#include "JSSensorData.h"
+
+namespace DeviceAPI {
+namespace Sensor {
+
+SensorService* SensorService::getInstance() {
+    static SensorService instance;
+    return &instance;
+}
+
+
+
+SensorService::SensorService()
+{
+    LOGD("*-* enter *-*");
+}
+
+SensorService::~SensorService()
+{
+}
+
+JSValueRef SensorService::getAvailableSensor(JSContextRef context)
+{
+    LOGD("enter");
+    int ret = SENSOR_ERROR_NONE;
+    int index = 0;
+    bool bLightSupported = false;
+    bool bMagneticSupported = false;
+    bool bPressureSupported = false;
+    bool bProximitySupported = false;
+    bool bUltravioletSupported = false;
+    std::string lightType = "LIGHT";
+    std::string magneticType = "MAGNETIC";
+    std::string pressureType = "PRESSURE";
+    std::string proximityType = "PROXIMITY";
+    std::string ultravioletType = "ULTRAVIOLET";
+
+
+    ret = sensor_is_supported(SENSOR_LIGHT, &bLightSupported);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"light sensor");
+    }
+
+    ret = sensor_is_supported(SENSOR_MAGNETIC, &bMagneticSupported);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"magnetic sensor");
+    }
+
+    ret = sensor_is_supported(SENSOR_PRESSURE, &bPressureSupported);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"pressure sensor");
+    }
+
+    ret = sensor_is_supported(SENSOR_PROXIMITY, &bProximitySupported);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"proximity sensor");
+    }
+
+    ret = sensor_is_supported(SENSOR_ULTRAVIOLET, &bUltravioletSupported);
+    if(ret != SENSOR_ERROR_NONE){
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"uv sensor");
+    }
+
+    JSObjectRef jsArray = JSCreateArrayObject(context, 0, NULL);
+    if (jsArray == NULL) {
+        LOGE("Unknown error");
+        throw UnknownException("Unknown error");
+    }
+
+    if (true == bLightSupported) {
+        JSValueRef jsLightType = JSUtil::toJSValueRef(context, lightType);
+        if (!JSSetArrayElement(context, jsArray, index, jsLightType)) {
+            LOGE("Unknown error");
+            throw UnknownException("Unknown error");
+        }else{
+            index++;
+            LOGD("Light Sensor Supported");
+        }
+    }
+
+    if (true == bMagneticSupported) {
+        JSValueRef jsMagneticType = JSUtil::toJSValueRef(context, magneticType);
+        if (!JSSetArrayElement(context, jsArray, index, jsMagneticType)) {
+            LOGE("Unknown error");
+            throw UnknownException("Unknown error");
+        }else{
+            index++;
+            LOGD("Magnetic Sensor Supported");
+        }
+    }
+
+    if (true == bPressureSupported) {
+        JSValueRef jsPressureType = JSUtil::toJSValueRef(context, pressureType);
+        if (!JSSetArrayElement(context, jsArray, index, jsPressureType)) {
+            LOGE("Unknown error");
+            throw UnknownException("Unknown error");
+        }else{
+            index++;
+            LOGD("Pressure Sensor Supported");
+        }
+    }
+
+    if (true == bProximitySupported) {
+        JSValueRef jsProximityType = JSUtil::toJSValueRef(context, proximityType);
+        if (!JSSetArrayElement(context, jsArray, index, jsProximityType)) {
+            LOGE("Unknown error");
+            throw UnknownException("Unknown error");
+        }else{
+            index++;
+            LOGD("Proximity Sensor Supported");
+        }
+    }
+
+    if(true == bUltravioletSupported){
+        JSValueRef jsUltravioletType = JSUtil::toJSValueRef(context, ultravioletType);
+        if (!JSSetArrayElement(context, jsArray, index, jsUltravioletType)) {
+            LOGE("Unknown error");
+            throw UnknownException("Unknown error");
+        }else{
+            index++;
+            LOGD("Ultraviolet Sensor Supported");
+        }
+    }
+
+    return jsArray;
+
+
+}
+
+//ProximitySuccessCallback
+ProximitySuccessCallback::ProximitySuccessCallback(JSContextRef globalCtx)
+    :CallbackUserData(globalCtx)
+{
+    LOGD("enter");
+}
+
+ProximitySuccessCallback::~ProximitySuccessCallback()
+{
+    LOGD("enter");
+}
+
+
+//LightSuccessCallback
+LightSuccessCallback::LightSuccessCallback(JSContextRef globalCtx)
+    :CallbackUserData(globalCtx)
+{
+    LOGD("enter");
+}
+
+LightSuccessCallback::~LightSuccessCallback()
+{
+    LOGD("enter");
+}
+
+//MagneticSuccessCallback
+MagneticSuccessCallback::MagneticSuccessCallback(JSContextRef globalCtx)
+    :CallbackUserData(globalCtx)
+{
+    LOGD("enter");
+}
+
+MagneticSuccessCallback::~MagneticSuccessCallback()
+{
+    LOGD("enter");
+
+}
+
+// PressureSuccessCallback
+PressureSuccessCallback::PressureSuccessCallback(JSContextRef globalCtx)
+    :CallbackUserData(globalCtx)
+{
+    LOGD("enter");
+}
+
+PressureSuccessCallback::~PressureSuccessCallback()
+{
+    LOGD("enter");
+}
+
+// UltravioletSuccessCallback
+UltravioletSuccessCallback::UltravioletSuccessCallback(JSContextRef globalCtx)
+    :CallbackUserData(globalCtx)
+{
+    LOGD("enter");
+}
+
+UltravioletSuccessCallback::~UltravioletSuccessCallback()
+{
+    LOGD("enter");
+}
+
+// ProximitySensor
+ProximitySensor* ProximitySensor::getInstance() {
+    static ProximitySensor instance;
+    return &instance;
+}
+
+
+ProximitySensor::ProximitySensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    mBStart = false;
+    mBSupported = false;
+
+    sensor_is_supported(SENSOR_PROXIMITY, &mBSupported);
+    if (mBSupported == false) {
+        LOGE("not supported");
+        return;
+    }
+
+    ret = sensor_get_default_sensor(SENSOR_PROXIMITY, &mProximityHandle);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+
+    ret = sensor_create_listener(mProximityHandle, &mProximityListener);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+
+}
+
+ProximitySensor::~ProximitySensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    if(mBSupported == false){
+        LOGE("not supported error");
+        return;
+    }
+
+    ret = sensor_destroy_listener(mProximityListener);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+}
+
+bool ProximitySensor::isSupported()
+{
+    return mBSupported;
+}
+
+void ProximitySensor::sensor_proximity_callback(sensor_h sensor, sensor_event_s *event, void *user_data)
+{
+    float distance = event->values[0];
+    LOGD("enter %f", distance);
+    ProximitySensor* proximitySensor = (ProximitySensor*)user_data;
+    proximitySensor->broadcast_proximity(distance);
+}
+
+
+gboolean ProximitySensor::callProximitySuccessCallback(void* data)
+{
+    LOGD("enter");
+    ProximitySuccessCallbackHolder* holder = static_cast<ProximitySuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback(holder->mJSProximityData);
+    JSValueUnprotect(holder->ptr->getContext(), holder->mJSProximityData);
+    delete holder;
+    return false;
+}
+
+gboolean ProximitySensor::callProximityStartSuccessCB(void* data)
+{
+    LOGD("enter");
+    ProximitySuccessCallbackHolder* holder = static_cast<ProximitySuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback();
+    delete holder;
+    return false;
+}
+
+
+void ProximitySensor::broadcast_proximity(float proximityLevel)
+{
+    LOGD("enter %f", proximityLevel);
+
+    bool started = false;
+    guint bGIdleRet = 0;
+    ProximityData* proximityData = NULL;
+    ProximitySuccessCallbackHolder* holder = NULL;
+    std::map<JSContextRef, ProximitySuccessCallbackPtr>::iterator iter;
+    int total = mProximityCallbackMap.size();
+
+    if (total <= 0) {
+        return;
+    }
+
+    for (iter = mProximityCallbackMap.begin() ; iter != mProximityCallbackMap.end() ; ++iter) {
+        started = false;
+        started = mProximityStartMap[iter->second->getContext()];
+        if (true == started) {
+            proximityData = new ProximityData((int)proximityLevel);
+            holder = new ProximitySuccessCallbackHolder();
+            if ((proximityData == NULL) || (holder == NULL)) {
+                return;
+            }
+
+            holder->ptr = iter->second;
+            holder->mJSProximityData = JSProximityData::createJSObject(holder->ptr->getContext(), proximityData);
+            JSValueProtect(holder->ptr->getContext(), holder->mJSProximityData);
+
+            bGIdleRet = g_idle_add(callProximitySuccessCallback, holder);
+            if (!bGIdleRet) {
+                LOGE("g_idle_add fails");
+            }
+        }
+    }
+
+}
+
+
+
+void ProximitySensor::start(ProximitySuccessCallbackPtr callback)
+{
+    int ret = 0;
+    guint bGIdleRet = 0;
+    ProximitySuccessCallbackHolder* holder = NULL;
+    int mapTotal = mProximityStartMap.size();
+
+    LOGD("enter");
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_start(mProximityListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("unknown error");
+            throw UnknownException("unknown error");
+        }
+        mBStart = true;
+    }
+
+    mProximityStartMap[callback->getContext()] = true;
+
+    holder = new ProximitySuccessCallbackHolder();
+    if (holder == NULL) {
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSProximityData = NULL;
+    bGIdleRet = g_idle_add(callProximityStartSuccessCB, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+
+}
+
+void ProximitySensor::stop(JSContextRef globalCtx)
+{
+    LOGD("enter ");
+
+    int ret = 0;
+    int mapTotal = 0;
+
+    mProximityStartMap.erase(globalCtx);
+    mapTotal = mProximityStartMap.size();
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_stop(mProximityListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+        mBStart = false;
+    }
+
+}
+
+void ProximitySensor::setChangeListener(ProximitySuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    int mapTotal = mProximityCallbackMap.size();
+    std::map<JSContextRef, ProximitySuccessCallbackPtr>::iterator iter;
+
+    iter = mProximityCallbackMap.find(callback->getContext());
+    if (iter != mProximityCallbackMap.end()) {
+        mProximityCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+    mProximityCallbackMap[callback->getContext()] = callback;
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_set_event_cb(mProximityListener, 100, sensor_proximity_callback, this);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+
+}
+
+void ProximitySensor::unsetChangeListener(JSContextRef globalCtx)
+{
+    int total = 0, ret = 0;
+    total = mProximityCallbackMap.size();
+    mProximityCallbackMap.erase(globalCtx);
+
+    if(total == 1){
+        ret = sensor_listener_unset_event_cb(mProximityListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+
+}
+
+void ProximitySensor::getSensorData(ProximitySuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    bool started = false;
+    float distance = 0.0;
+    guint bGIdleRet = 0;
+    ProximityData* proximityData = NULL;
+    ProximitySuccessCallbackHolder* holder = NULL;
+    sensor_event_s sensorEvent;
+
+    started = mProximityStartMap[callback->getContext()];
+    if (false == started) {
+        mProximityStartMap.erase(callback->getContext());
+
+        LOGE("Not yet start");
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "service not available");
+        callback->callErrorCallback(error);
+        return;
+
+    }
+
+    ret = sensor_listener_read_data(mProximityListener, &sensorEvent);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret %d , %s", ret, SensorUtil::getSensorErrorMessage(ret).c_str());
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, SensorUtil::getSensorErrorMessage(ret).c_str());
+        callback->callErrorCallback(error);
+        return;
+    }
+    distance = sensorEvent.values[0];
+
+    proximityData = new ProximityData((int)distance);
+    holder = new ProximitySuccessCallbackHolder();
+    if ((proximityData == NULL) || (holder == NULL)) {
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSProximityData = JSProximityData::createJSObject(holder->ptr->getContext(), proximityData);
+    JSValueProtect(callback->getContext(), holder->mJSProximityData);
+    bGIdleRet = g_idle_add(callProximitySuccessCallback, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+
+
+}
+
+void ProximitySensor::removeCallback(JSContextRef globalCtx)
+{
+    LOGD("enter");
+
+    mProximityCallbackMap.erase(globalCtx);
+    mProximityStartMap.erase(globalCtx);
+
+    LOGD("end %p : [ %d , %d ]",globalCtx ,mProximityCallbackMap.size(), mProximityStartMap.size());
+}
+
+// LightSensor
+LightSensor* LightSensor::getInstance() {
+    static LightSensor instance;
+    return &instance;
+}
+
+LightSensor::LightSensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    mBStart = false;
+    mBSupported = false;
+
+    sensor_is_supported(SENSOR_LIGHT, &mBSupported);
+    if (mBSupported == false) {
+        LOGE("not supported");
+        return;
+    }
+
+    ret = sensor_get_default_sensor(SENSOR_LIGHT, &mLightHandle);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+
+    ret = sensor_create_listener(mLightHandle, &mLightListener);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+
+}
+
+LightSensor::~LightSensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    if(mBSupported == false){
+        LOGE("not supported error");
+        return;
+    }
+
+    ret = sensor_destroy_listener(mLightListener);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+}
+
+bool LightSensor::isSupported()
+{
+    return mBSupported;
+}
+
+void LightSensor::sensor_light_callback(sensor_h sensor, sensor_event_s *event, void *user_data)
+{
+    float lux = event->values[0];
+    LOGD("enter %f", lux);
+    LightSensor* lightSensor = (LightSensor*)user_data;
+    lightSensor->broadcast_light(lux);
+
+}
+
+gboolean LightSensor::callLightSuccessCallback(void* data)
+{
+    LOGD("enter");
+    LightSuccessCallbackHolder* holder = static_cast<LightSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback(holder->mJSLightData);
+    JSValueUnprotect(holder->ptr->getContext(), holder->mJSLightData);
+    delete holder;
+    return false;
+}
+
+gboolean LightSensor::callLightStartSuccessCallback(void* data)
+{
+    LOGD("enter");
+    LightSuccessCallbackHolder* holder = static_cast<LightSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback();
+    delete holder;
+    return false;
+}
+
+void LightSensor::broadcast_light(float lux)
+{
+    LOGD("enter %f", lux);
+
+    bool started = false;
+    guint bGIdleRet = 0;
+    LightData* lightData = NULL;
+    LightSuccessCallbackHolder* holder = NULL;
+    std::map<JSContextRef, LightSuccessCallbackPtr>::iterator iter;
+    int total = mLightCallbackMap.size();
+
+    if (total <= 0) {
+        return;
+    }
+
+    for (iter = mLightCallbackMap.begin() ; iter != mLightCallbackMap.end() ; ++iter) {
+        started = false;
+        started = mLightStartMap[iter->second->getContext()];
+        if (true == started) {
+            lightData = new LightData((double)lux);
+            holder = new LightSuccessCallbackHolder();
+            if ((lightData == NULL) || (holder == NULL)) {
+                return;
+            }
+
+            holder->ptr = iter->second;
+            holder->mJSLightData = JSLightData::createJSObject(holder->ptr->getContext(), lightData);
+            JSValueProtect(holder->ptr->getContext(), holder->mJSLightData);
+
+            bGIdleRet = g_idle_add(callLightSuccessCallback, holder);
+            if (!bGIdleRet) {
+                LOGE("g_idle_add fails");
+            }
+        }
+    }
+
+}
+
+
+
+void LightSensor::start(LightSuccessCallbackPtr callback)
+{
+    int ret = 0;
+    guint bGIdleRet = 0;
+    LightSuccessCallbackHolder* holder = NULL;
+    int mapTotal = mLightStartMap.size();
+
+    LOGD("enter");
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_start(mLightListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+        mBStart = true;
+    }
+
+    mLightStartMap[callback->getContext()] = true;
+
+    holder = new LightSuccessCallbackHolder();
+    if (holder == NULL) {
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSLightData = NULL;
+    bGIdleRet = g_idle_add(callLightStartSuccessCallback, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+
+}
+
+void LightSensor::stop(JSContextRef globalCtx)
+{
+    LOGD("enter ");
+
+    int ret = 0;
+    int mapTotal = 0;
+
+    mLightStartMap.erase(globalCtx);
+    mapTotal = mLightStartMap.size();
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_stop(mLightListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+        mBStart = false;
+    }
+
+}
+
+void LightSensor::setChangeListener(LightSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    int mapTotal = mLightCallbackMap.size();
+    std::map<JSContextRef, LightSuccessCallbackPtr>::iterator iter;
+
+    iter = mLightCallbackMap.find(callback->getContext());
+    if (iter != mLightCallbackMap.end()) {
+        mLightCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+    mLightCallbackMap[callback->getContext()] = callback;
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_set_event_cb(mLightListener, 100, sensor_light_callback, this);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+
+}
+
+void LightSensor::unsetChangeListener(JSContextRef globalCtx)
+{
+    int total = 0, ret = 0;
+    total = mLightCallbackMap.size();
+    mLightCallbackMap.erase(globalCtx);
+
+    if(total == 1){
+        ret = sensor_listener_unset_event_cb(mLightListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+
+}
+
+void LightSensor::getSensorData(LightSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    bool started = false;
+    float lightLevel = 0.0;
+    guint bGIdleRet = 0;
+    LightData* lightData = NULL;
+    LightSuccessCallbackHolder* holder = NULL;
+    sensor_event_s sensorEvent;
+
+    started = mLightStartMap[callback->getContext()];
+    if (false == started) {
+        mLightStartMap.erase(callback->getContext());
+
+        LOGE("Not yet start");
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "service not available");
+        callback->callErrorCallback(error);
+        return;
+    }
+
+    ret = sensor_listener_read_data(mLightListener, &sensorEvent);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret %d , %s", ret, SensorUtil::getSensorErrorMessage(ret).c_str());
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, SensorUtil::getSensorErrorMessage(ret).c_str());
+        callback->callErrorCallback(error);
+        return;
+    }
+    lightLevel = sensorEvent.values[0];
+
+    lightData = new LightData((double)lightLevel);
+    holder = new LightSuccessCallbackHolder();
+    if ((lightData == NULL) || (holder == NULL)) {
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSLightData = JSLightData::createJSObject(holder->ptr->getContext(), lightData);
+    JSValueProtect(callback->getContext(), holder->mJSLightData);
+    bGIdleRet = g_idle_add(callLightSuccessCallback, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+
+}
+
+void LightSensor::removeCallback(JSContextRef globalCtx)
+{
+    LOGD("enter");
+
+    mLightCallbackMap.erase(globalCtx);
+    mLightStartMap.erase(globalCtx);
+
+    LOGD("end %p : [ %d , %d ]",globalCtx ,mLightCallbackMap.size(), mLightStartMap.size());
+}
+
+
+// Magnetic Sensor
+MagneticSensor* MagneticSensor::getInstance() {
+    static MagneticSensor instance;
+    return &instance;
+}
+
+MagneticSensor::MagneticSensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    mBStart = false;
+    mBSupported = false;
+
+    sensor_is_supported(SENSOR_MAGNETIC, &mBSupported);
+    if (mBSupported == false) {
+        LOGE("not supported");
+        return;
+    }
+
+    ret = sensor_get_default_sensor(SENSOR_MAGNETIC, &mMagneticHandle);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+
+    ret = sensor_create_listener(mMagneticHandle, &mMagneticListener);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+
+
+}
+
+MagneticSensor::~MagneticSensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    if(mBSupported == false){
+        LOGE("not supported error");
+        return;
+    }
+
+    ret = sensor_destroy_listener(mMagneticListener);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+}
+
+bool MagneticSensor::isSupported()
+{
+    return mBSupported;
+}
+
+
+void MagneticSensor::sensor_magnetic_callback(sensor_h sensor, sensor_event_s *event, void *user_data)
+{
+    sensor_data_accuracy_e accuracy = static_cast<sensor_data_accuracy_e>(event->accuracy);
+    float x = event ->values[0];
+    float y = event ->values[1];
+    float z = event ->values[2];
+    LOGD("enter [ %f , %f , %f ] [ %d ]",x, y, z, accuracy);
+    MagneticSensor* magneticSensor = (MagneticSensor*)user_data;
+    magneticSensor->broadcast_magnetic(x, y, z, accuracy);
+
+}
+
+void MagneticSensor::broadcast_magnetic(float x, float y, float z, sensor_data_accuracy_e accuracy)
+{
+    bool started = false;
+    guint bGIdleRet = 0;
+    MagneticData* magneticData = NULL;
+    MagneticSuccessCallbackHolder* holder = NULL;
+    std::map<JSContextRef, MagneticSuccessCallbackPtr>::iterator iter;
+    int total = mMagneticCallbackMap.size();
+
+    if (total <= 0) {
+        return;
+    }
+
+    for (iter = mMagneticCallbackMap.begin() ; iter != mMagneticCallbackMap.end() ; ++iter) {
+        started = false;
+        started = mMagneticStartMap[iter->second->getContext()];
+        if (true == started) {
+            magneticData = new MagneticData(x, y, z, accuracy);
+            holder = new MagneticSuccessCallbackHolder();
+            if ((magneticData == NULL) || (holder == NULL)) {
+                return;
+            }
+
+            holder->ptr = iter->second;
+            holder->mJSMagneticData = JSMagneticData::createJSObject(holder->ptr->getContext(), magneticData);
+            JSValueProtect(holder->ptr->getContext(), holder->mJSMagneticData);
+
+            bGIdleRet = g_idle_add(callMagneticSuccessCallback, holder);
+            if (!bGIdleRet) {
+                LOGE("g_idle_add fails");
+            }
+        }
+    }
+
+}
+
+
+gboolean MagneticSensor::callMagneticSuccessCallback(void* data)
+{
+    LOGD("enter");
+    MagneticSuccessCallbackHolder* holder = static_cast<MagneticSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback(holder->mJSMagneticData);
+    JSValueUnprotect(holder->ptr->getContext(), holder->mJSMagneticData);
+    delete holder;
+    return false;
+}
+
+gboolean MagneticSensor::callMagneticStartSuccessCallback(void* data)
+{
+    LOGD("enter");
+    MagneticSuccessCallbackHolder* holder = static_cast<MagneticSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback();
+    delete holder;
+    return false;
+}
+
+
+
+void MagneticSensor::start(MagneticSuccessCallbackPtr callback)
+{
+    int ret = 0;
+    guint bGIdleRet = 0;
+    MagneticSuccessCallbackHolder* holder = NULL;
+    int mapTotal = mMagneticStartMap.size();
+
+    LOGD("enter");
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_start(mMagneticListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+        mBStart = true;
+    }
+
+    mMagneticStartMap[callback->getContext()] = true;
+
+    holder = new MagneticSuccessCallbackHolder();
+    if (holder == NULL) {
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSMagneticData = NULL;
+    bGIdleRet = g_idle_add(callMagneticStartSuccessCallback, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+
+}
+
+void MagneticSensor::stop(JSContextRef globalCtx)
+{
+    LOGD("enter ");
+
+    int ret = 0;
+    int mapTotal = 0;
+
+    mMagneticStartMap.erase(globalCtx);
+    mapTotal = mMagneticStartMap.size();
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_stop(mMagneticListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+        mBStart = false;
+
+    }
+
+}
+
+void MagneticSensor::setChangeListener(MagneticSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    int mapTotal = mMagneticCallbackMap.size();
+    std::map<JSContextRef, MagneticSuccessCallbackPtr>::iterator iter;
+
+    iter = mMagneticCallbackMap.find(callback->getContext());
+    if (iter != mMagneticCallbackMap.end()) {
+        mMagneticCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+    mMagneticCallbackMap[callback->getContext()] = callback;
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_set_event_cb(mMagneticListener, 100, sensor_magnetic_callback, this);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+
+}
+
+void MagneticSensor::unsetChangeListener(JSContextRef globalCtx)
+{
+    int total = 0, ret = 0;
+    total = mMagneticCallbackMap.size();
+    mMagneticCallbackMap.erase(globalCtx);
+
+    if(total == 1){
+        ret = sensor_listener_unset_event_cb(mMagneticListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+}
+
+
+void MagneticSensor::getSensorData(MagneticSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    bool started = false;
+    float x = 0.0, y = 0.0, z = 0.0;
+    sensor_data_accuracy_e accuracy = SENSOR_DATA_ACCURACY_UNDEFINED;
+    guint bGIdleRet = 0;
+    MagneticData* magneticData = NULL;
+    MagneticSuccessCallbackHolder* holder = NULL;
+    sensor_event_s sensorEvent;
+
+    started = mMagneticStartMap[callback->getContext()];
+    if (false == started) {
+        mMagneticStartMap.erase(callback->getContext());
+
+        LOGE("Not yet start");
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "service not available");
+        callback->callErrorCallback(error);
+        return;
+    }
+
+    ret = sensor_listener_read_data(mMagneticListener, &sensorEvent);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret %d , %s", ret, SensorUtil::getSensorErrorMessage(ret).c_str());
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, SensorUtil::getSensorErrorMessage(ret).c_str());
+        callback->callErrorCallback(error);
+        return;
+    }
+    accuracy = static_cast<sensor_data_accuracy_e>(sensorEvent.accuracy);
+    x = sensorEvent.values[0];
+    y = sensorEvent.values[1];
+    z = sensorEvent.values[2];
+
+    magneticData = new MagneticData(x, y, z, accuracy);
+    holder = new MagneticSuccessCallbackHolder();
+    if ((magneticData == NULL) || (holder == NULL)) {
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSMagneticData = JSMagneticData::createJSObject(holder->ptr->getContext(), magneticData);
+    JSValueProtect(holder->ptr->getContext(), holder->mJSMagneticData);
+
+    bGIdleRet = g_idle_add(callMagneticSuccessCallback, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+}
+
+void MagneticSensor::removeCallback(JSContextRef globalCtx)
+{
+    LOGD("enter");
+
+    mMagneticCallbackMap.erase(globalCtx);
+    mMagneticStartMap.erase(globalCtx);
+
+    LOGD("end %p : [ %d , %d ]",globalCtx ,mMagneticCallbackMap.size(), mMagneticStartMap.size());
+}
+
+// Pressure Sensor
+PressureSensor* PressureSensor::getInstance() {
+    static PressureSensor instance;
+    return &instance;
+}
+
+PressureSensor::PressureSensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    mBStart = false;
+    mBSupported = false;
+
+    sensor_is_supported(SENSOR_PRESSURE, &mBSupported);
+    if (mBSupported == false) {
+        LOGE("not supported");
+        return;
+    }
+
+    ret = sensor_get_default_sensor(SENSOR_PRESSURE, &mPressureHandle);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+
+    ret = sensor_create_listener(mPressureHandle, &mPressureListener);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+
+}
+
+PressureSensor::~PressureSensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    if(mBSupported == false){
+        LOGE("not supported error");
+        return;
+    }
+
+    ret = sensor_destroy_listener(mPressureListener);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+}
+
+bool PressureSensor::isSupported()
+{
+    return mBSupported;
+}
+
+void PressureSensor::sensor_pressure_callback(sensor_h sensor, sensor_event_s *event, void *user_data)
+{
+    float pressure = event->values[0];
+    LOGD("enter %f", pressure);
+    PressureSensor* pressureSensor = (PressureSensor*)user_data;
+    pressureSensor->broadcast_pressure(pressure);
+
+}
+
+gboolean PressureSensor::callPressureStartSuccessCallback(void* data)
+{
+    LOGD("enter");
+    PressureSuccessCallbackHolder* holder = static_cast<PressureSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback();
+    delete holder;
+    return false;
+}
+
+gboolean PressureSensor::callPressureSuccessCallback(void* data)
+{
+    LOGD("enter");
+    PressureSuccessCallbackHolder* holder = static_cast<PressureSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback(holder->mJSPressureData);
+    JSValueUnprotect(holder->ptr->getContext(), holder->mJSPressureData);
+    delete holder;
+    return false;
+}
+
+void PressureSensor::broadcast_pressure(float pressure)
+{
+    bool started = false;
+    guint bGIdleRet = 0;
+    PressureData* pressureData = NULL;
+    PressureSuccessCallbackHolder* holder = NULL;
+    std::map<JSContextRef, PressureSuccessCallbackPtr>::iterator iter;
+    int total = mPressureCallbackMap.size();
+
+    if (total <= 0) {
+        return;
+    }
+
+    for (iter = mPressureCallbackMap.begin() ; iter != mPressureCallbackMap.end() ; ++iter) {
+        started = false;
+        started = mPressureStartMap[iter->second->getContext()];
+        if (true == started) {
+            pressureData = new PressureData((double)pressure);
+            holder = new PressureSuccessCallbackHolder();
+            if ((pressureData == NULL) || (holder == NULL)) {
+                return;
+            }
+
+            holder->ptr = iter->second;
+            holder->mJSPressureData = JSPressureData::createJSObject(holder->ptr->getContext(), pressureData);
+            JSValueProtect(holder->ptr->getContext(), holder->mJSPressureData);
+
+            bGIdleRet = g_idle_add(callPressureSuccessCallback, holder);
+            if (!bGIdleRet) {
+                LOGE("g_idle_add fails");
+            }
+        }
+    }
+
+}
+
+
+
+void PressureSensor::start(PressureSuccessCallbackPtr callback)
+{
+    int ret = 0;
+    guint bGIdleRet = 0;
+    PressureSuccessCallbackHolder* holder = NULL;
+    int mapTotal = mPressureStartMap.size();
+
+    LOGD("enter");
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_start(mPressureListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+        mBStart = true;
+    }
+
+    mPressureStartMap[callback->getContext()] = true;
+
+    holder = new PressureSuccessCallbackHolder();
+    if (holder == NULL) {
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSPressureData = NULL;
+    bGIdleRet = g_idle_add(callPressureStartSuccessCallback, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+}
+
+void PressureSensor::stop(JSContextRef globalCtx)
+{
+    LOGD("enter ");
+
+    int ret = 0;
+    int mapTotal = 0;
+
+    mPressureStartMap.erase(globalCtx);
+    mapTotal = mPressureStartMap.size();
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_stop(mPressureListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+        mBStart = false;
+    }
+
+}
+
+void PressureSensor::setChangeListener(PressureSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    int mapTotal = mPressureCallbackMap.size();
+    std::map<JSContextRef, PressureSuccessCallbackPtr>::iterator iter;
+
+    iter = mPressureCallbackMap.find(callback->getContext());
+    if (iter != mPressureCallbackMap.end()) {
+        mPressureCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+    mPressureCallbackMap[callback->getContext()] = callback;
+
+    if (mapTotal <= 0) {
+        ret = sensor_listener_set_event_cb(mPressureListener, 100, sensor_pressure_callback, this);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+
+}
+
+void PressureSensor::unsetChangeListener(JSContextRef globalCtx)
+{
+    int total = 0, ret = 0;
+    total = mPressureCallbackMap.size();
+    mPressureCallbackMap.erase(globalCtx);
+
+    if(total == 1){
+        ret = sensor_listener_unset_event_cb(mPressureListener);
+        if (ret != SENSOR_ERROR_NONE) {
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+
+}
+
+void PressureSensor::getSensorData(PressureSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    bool started = false;
+    float pressure = 0.0;
+    guint bGIdleRet = 0;
+    PressureData* pressureData = NULL;
+    PressureSuccessCallbackHolder* holder = NULL;
+    sensor_event_s sensorEvent;
+
+    started = mPressureStartMap[callback->getContext()];
+    if (false == started) {
+        mPressureStartMap.erase(callback->getContext());
+
+        LOGE("Not yet start");
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "service not available");
+        callback->callErrorCallback(error);
+        return;
+    }
+
+    ret = sensor_listener_read_data(mPressureListener, &sensorEvent);
+    if (ret != SENSOR_ERROR_NONE) {
+        LOGE("ret %d , %s", ret, SensorUtil::getSensorErrorMessage(ret).c_str());
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, SensorUtil::getSensorErrorMessage(ret).c_str());
+        callback->callErrorCallback(error);
+        return;
+    }
+    pressure = sensorEvent.values[0];
+
+    pressureData = new PressureData((double)pressure);
+    holder = new PressureSuccessCallbackHolder();
+    if ((pressureData == NULL) || (holder == NULL)) {
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSPressureData = JSPressureData::createJSObject(holder->ptr->getContext(), pressureData);
+    JSValueProtect(holder->ptr->getContext(), holder->mJSPressureData);
+    bGIdleRet = g_idle_add(callPressureSuccessCallback, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+
+}
+
+void PressureSensor::removeCallback(JSContextRef globalCtx)
+{
+    LOGD("enter");
+
+    mPressureCallbackMap.erase(globalCtx);
+    mPressureStartMap.erase(globalCtx);
+
+    LOGD("end %p : [ %d , %d ]",globalCtx ,mPressureCallbackMap.size(), mPressureStartMap.size());
+}
+
+// UltravioletSensor
+UltravioletSensor* UltravioletSensor::getInstance(){
+    static UltravioletSensor instance;
+    return &instance;
+}
+
+UltravioletSensor::UltravioletSensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    mBStart = false;
+    mBSupported = false;
+
+    sensor_is_supported(SENSOR_ULTRAVIOLET, &mBSupported);
+    if(mBSupported == false){
+        LOGE("not supported");
+        return;
+    }
+
+    ret = sensor_get_default_sensor(SENSOR_ULTRAVIOLET, &mUltravioletHandle);
+    if (ret != SENSOR_ERROR_NONE){
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+
+    ret = sensor_create_listener(mUltravioletHandle, &mUltravioletListener);
+    if (ret != SENSOR_ERROR_NONE){
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+}
+
+UltravioletSensor::~UltravioletSensor()
+{
+    int ret = SENSOR_ERROR_NONE;
+    LOGD("enter");
+
+    if(mBSupported == false){
+        LOGE("not supported error");
+        return;
+    }
+
+    ret = sensor_destroy_listener(mUltravioletListener);
+    if (ret != SENSOR_ERROR_NONE){
+        LOGE("ret : %d", ret);
+        SensorUtil::throwSensorException(ret,"");
+    }
+}
+
+bool UltravioletSensor::isSupported()
+{
+    return mBSupported;
+}
+
+void UltravioletSensor::sensor_ultraviolet_callback(sensor_h sensor, sensor_event_s *event, void *user_data)
+{
+    float index = event->values[0];
+    LOGD("enter %f", index);
+    UltravioletSensor* ultravioletSensor = (UltravioletSensor*)user_data;
+    ultravioletSensor->broadcast_ultraviolet(index);
+
+}
+
+gboolean UltravioletSensor::callUltravioletStartSuccessCallback(void* data)
+{
+    LOGD("enter");
+    UltravioletSuccessCallbackHolder* holder = static_cast<UltravioletSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback();
+    delete holder;
+    return false;
+}
+
+gboolean UltravioletSensor::callUltravioletSuccessCallback(void* data)
+{
+    LOGD("enter");
+    UltravioletSuccessCallbackHolder* holder = static_cast<UltravioletSuccessCallbackHolder*>(data);
+    holder->ptr->callSuccessCallback(holder->mJSUltravioletData);
+    delete holder;
+    return false;
+}
+
+void UltravioletSensor::broadcast_ultraviolet(float ultraviolet)
+{
+    bool started = false;
+    guint bGIdleRet = 0;
+    UltravioletData* ultravioletData = NULL;
+    UltravioletSuccessCallbackHolder* holder = NULL;
+    std::map<JSContextRef, UltravioletSuccessCallbackPtr>::iterator iter;
+    int total = mUltravioletCallbackMap.size();
+
+    if(total <= 0){
+        return;
+    }
+
+    for(iter = mUltravioletCallbackMap.begin() ; iter != mUltravioletCallbackMap.end() ; ++iter){
+        started = false;
+        started = mUltravioletStartMap[iter->second->getContext()];
+        if(true == started){
+            ultravioletData = new UltravioletData((double)ultraviolet);
+            holder = new UltravioletSuccessCallbackHolder();
+            if((ultravioletData == NULL) || (holder == NULL)){
+                return;
+            }
+
+            holder->ptr = iter->second;
+            holder->mJSUltravioletData = JSUltravioletData::createJSObject(holder->ptr->getContext(), ultravioletData);
+            JSValueProtect(holder->ptr->getContext(), holder->mJSUltravioletData);
+
+            bGIdleRet = g_idle_add(callUltravioletSuccessCallback, holder);
+            if (!bGIdleRet) {
+                LOGE("g_idle_add fails");
+            }
+        }
+    }
+}
+
+void UltravioletSensor::start(UltravioletSuccessCallbackPtr callback)
+{
+    int ret = 0;
+    guint bGIdleRet = 0;
+    UltravioletSuccessCallbackHolder* holder = NULL;
+    int mapTotal = mUltravioletStartMap.size();
+
+    LOGD("enter");
+
+    if(mapTotal <= 0){
+        ret = sensor_listener_start(mUltravioletListener);
+        if (ret != SENSOR_ERROR_NONE){
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+        mBStart = true;
+    }
+
+    mUltravioletStartMap[callback->getContext()] = true;
+
+    holder = new UltravioletSuccessCallbackHolder();
+    if(holder == NULL){
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSUltravioletData = NULL;
+    bGIdleRet = g_idle_add(callUltravioletStartSuccessCallback, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+}
+
+void UltravioletSensor::stop(JSContextRef globalCtx)
+{
+    LOGD("enter ");
+
+    int ret = 0;
+    int mapTotal = 0;
+
+    mUltravioletStartMap.erase(globalCtx);
+    mapTotal = mUltravioletStartMap.size();
+
+    if(mapTotal <= 0){
+        ret = sensor_listener_stop(mUltravioletListener);
+        if (ret != SENSOR_ERROR_NONE){
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+        mBStart = false;
+    }
+
+}
+
+void UltravioletSensor::setChangeListener(UltravioletSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    int mapTotal = mUltravioletCallbackMap.size();
+    std::map<JSContextRef, UltravioletSuccessCallbackPtr>::iterator iter;
+
+    iter = mUltravioletCallbackMap.find(callback->getContext());
+    if(iter != mUltravioletCallbackMap.end()){
+        mUltravioletCallbackMap.erase(callback->getContext());
+        LOGD("prev callback erase");
+    }
+    mUltravioletCallbackMap[callback->getContext()] = callback;
+
+    if(mapTotal <= 0){
+        ret = sensor_listener_set_event_cb(mUltravioletListener, 100, sensor_ultraviolet_callback, this);
+        if (ret != SENSOR_ERROR_NONE){
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+}
+
+void UltravioletSensor::unsetChangeListener(JSContextRef globalCtx)
+{
+    int total = 0, ret = 0;
+    total = mUltravioletCallbackMap.size();
+    mUltravioletCallbackMap.erase(globalCtx);
+
+    if(total == 1){
+        ret = sensor_listener_unset_event_cb(mUltravioletListener);
+        if (ret != SENSOR_ERROR_NONE){
+            LOGE("ret : %d", ret);
+            SensorUtil::throwSensorException(ret,"");
+        }
+    }
+}
+
+void UltravioletSensor::getSensorData(UltravioletSuccessCallbackPtr callback)
+{
+    LOGD("enter");
+    int ret = 0;
+    bool started = false;
+    float ultraviolet = 0.0;
+    guint bGIdleRet = 0;
+    UltravioletData* ultravioletData = NULL;
+    UltravioletSuccessCallbackHolder* holder = NULL;
+    sensor_event_s sensorEvent;
+
+    started = mUltravioletStartMap[callback->getContext()];
+    if(false == started){
+        mUltravioletStartMap.erase(callback->getContext());
+
+        LOGE("Not yet start");
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, "service not available");
+        callback->callErrorCallback(error);
+        return;
+    }
+
+    ret = sensor_listener_read_data(mUltravioletListener, &sensorEvent);
+    if (ret != SENSOR_ERROR_NONE){
+        LOGE("ret %d , %s", ret, SensorUtil::getSensorErrorMessage(ret).c_str());
+        JSValueRef error = JSWebAPIErrorFactory::makeErrorObject(callback->getContext(), JSWebAPIErrorFactory::SERVICE_NOT_AVAILABLE_ERROR, SensorUtil::getSensorErrorMessage(ret).c_str());
+        callback->callErrorCallback(error);
+        return;
+    }
+    ultraviolet = sensorEvent.values[0];
+
+    ultravioletData = new UltravioletData((double)ultraviolet);
+    holder = new UltravioletSuccessCallbackHolder();
+    if((ultravioletData == NULL) || (holder == NULL)){
+        return;
+    }
+
+    holder->ptr = callback;
+    holder->mJSUltravioletData = JSUltravioletData::createJSObject(holder->ptr->getContext(), ultravioletData);
+    JSValueProtect(callback->getContext(), holder->mJSUltravioletData);
+    bGIdleRet = g_idle_add(callUltravioletSuccessCallback, holder);
+    if (!bGIdleRet) {
+        LOGE("g_idle_add fails");
+    }
+}
+
+void UltravioletSensor::removeCallback(JSContextRef globalCtx)
+{
+    LOGD("enter");
+
+    mUltravioletCallbackMap.erase(globalCtx);
+    mUltravioletStartMap.erase(globalCtx);
+
+    LOGD("end %p [ %d , %d ] ",globalCtx ,mUltravioletCallbackMap.size(), mUltravioletStartMap.size());
+}
+
+} // Sensor
+} // DeviceAPI
diff --git a/src/Sensor/SensorService.h b/src/Sensor/SensorService.h
new file mode 100755 (executable)
index 0000000..ee89061
--- /dev/null
@@ -0,0 +1,268 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SENSOR_SERVICE_H__
+#define __TIZEN_SENSOR_SERVICE_H__
+
+#include <map>
+#include <list>
+#include <glib.h>
+#include <CallbackUserData.h>
+#include <memory>
+#include <sensor.h>
+
+#include "SensorUtil.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sensor {
+
+class SensorService
+{
+    public:
+        SensorService();
+        virtual ~SensorService();
+        JSValueRef getAvailableSensor(JSContextRef context);
+        static SensorService* getInstance();
+
+    private:
+};
+
+class ProximitySuccessCallback : public Common::CallbackUserData
+{
+    public:
+        ProximitySuccessCallback(JSContextRef globalCtx);
+        virtual ~ProximitySuccessCallback();
+
+    private:
+};
+
+
+class LightSuccessCallback : public Common::CallbackUserData
+{
+    public:
+        LightSuccessCallback(JSContextRef globalCtx);
+        virtual ~LightSuccessCallback();
+
+    private:
+};
+
+class MagneticSuccessCallback : public Common::CallbackUserData
+{
+    public:
+        MagneticSuccessCallback(JSContextRef globalCtx);
+        virtual ~MagneticSuccessCallback();
+
+    private:
+};
+
+class PressureSuccessCallback : public Common::CallbackUserData
+{
+    public:
+        PressureSuccessCallback(JSContextRef globalCtx);
+        virtual ~PressureSuccessCallback();
+
+    private:
+};
+
+
+class UltravioletSuccessCallback : public Common::CallbackUserData
+{
+    public:
+        UltravioletSuccessCallback(JSContextRef globalCtx);
+        virtual ~UltravioletSuccessCallback();
+
+    private:
+};
+
+typedef std::shared_ptr<ProximitySuccessCallback> ProximitySuccessCallbackPtr;
+typedef std::shared_ptr<LightSuccessCallback> LightSuccessCallbackPtr;
+typedef std::shared_ptr<MagneticSuccessCallback> MagneticSuccessCallbackPtr;
+typedef std::shared_ptr<PressureSuccessCallback> PressureSuccessCallbackPtr;
+typedef std::shared_ptr<UltravioletSuccessCallback> UltravioletSuccessCallbackPtr;
+
+struct ProximitySuccessCallbackHolder {
+    ProximitySuccessCallbackPtr ptr;
+    JSValueRef mJSProximityData;
+};
+
+struct LightSuccessCallbackHolder {
+    LightSuccessCallbackPtr ptr;
+    JSValueRef mJSLightData;
+};
+
+struct MagneticSuccessCallbackHolder {
+    MagneticSuccessCallbackPtr ptr;
+    JSValueRef mJSMagneticData;
+};
+
+struct PressureSuccessCallbackHolder {
+    PressureSuccessCallbackPtr ptr;
+    JSValueRef mJSPressureData;
+};
+
+struct UltravioletSuccessCallbackHolder {
+    UltravioletSuccessCallbackPtr ptr;
+    JSValueRef mJSUltravioletData;
+};
+
+class ProximitySensor
+{
+    public:
+        ProximitySensor();
+        virtual ~ProximitySensor();
+        static ProximitySensor* getInstance();
+        void start(ProximitySuccessCallbackPtr successCB);
+        void stop(JSContextRef globalCtx);
+        void setChangeListener(ProximitySuccessCallbackPtr callback);
+        void unsetChangeListener(JSContextRef globalCtx);
+        void getSensorData(ProximitySuccessCallbackPtr callback);
+        void broadcast_proximity(float proximityLevel);
+        bool isSupported();
+        void removeCallback(JSContextRef globalCtx);
+        static void sensor_proximity_callback(sensor_h sensor, sensor_event_s *event, void *user_data);
+        static gboolean callProximitySuccessCallback(void* data);
+        static gboolean callProximityStartSuccessCB(void* data);
+
+    private:
+        sensor_h mProximityHandle;
+        sensor_listener_h mProximityListener;
+        bool mBStart;
+        bool mBSupported;
+        std::map<JSContextRef, ProximitySuccessCallbackPtr> mProximityCallbackMap;
+        std::map<JSContextRef, bool> mProximityStartMap;
+
+};
+
+class LightSensor
+{
+    public:
+        LightSensor();
+        virtual ~LightSensor();
+        static LightSensor* getInstance();
+        void start(LightSuccessCallbackPtr successCB);
+        void stop(JSContextRef globalCtx);
+        void setChangeListener(LightSuccessCallbackPtr callback);
+        void unsetChangeListener(JSContextRef globalCtx);
+        void getSensorData(LightSuccessCallbackPtr callback);
+        void broadcast_light(float lux);
+        bool isSupported();
+        void removeCallback(JSContextRef globalCtx);
+        static void sensor_light_callback(sensor_h sensor, sensor_event_s *event, void *user_data);
+        static gboolean callLightSuccessCallback(void* data);
+        static gboolean callLightStartSuccessCallback(void* data);
+
+    private:
+        sensor_h mLightHandle;
+        sensor_listener_h mLightListener;
+        bool mBStart;
+        bool mBSupported;
+        std::map<JSContextRef, LightSuccessCallbackPtr> mLightCallbackMap;
+        std::map<JSContextRef, bool> mLightStartMap;
+
+};
+
+class MagneticSensor
+{
+    public:
+        MagneticSensor();
+        virtual ~MagneticSensor();
+        static MagneticSensor* getInstance();
+        void start(MagneticSuccessCallbackPtr successCB);
+        void stop(JSContextRef globalCtx);
+        void setChangeListener(MagneticSuccessCallbackPtr callback);
+        void unsetChangeListener(JSContextRef globalCtx);
+        void getSensorData(MagneticSuccessCallbackPtr callback);
+        void broadcast_magnetic(float x, float y, float z, sensor_data_accuracy_e accuracy);
+        void broadcast_calibaratiion();
+        bool isSupported();
+        void removeCallback(JSContextRef globalCtx);
+        static void sensor_magnetic_callback(sensor_h sensor, sensor_event_s *event, void *user_data);
+        static gboolean callMagneticStartSuccessCallback(void* data);
+        static gboolean callMagneticSuccessCallback(void* data);
+
+    private:
+        sensor_h mMagneticHandle;
+        sensor_listener_h mMagneticListener;
+        bool mBStart;
+        bool mBSupported;
+        std::map<JSContextRef, MagneticSuccessCallbackPtr> mMagneticCallbackMap;
+        std::map<JSContextRef, bool> mMagneticStartMap;
+
+};
+
+class PressureSensor
+{
+    public:
+        PressureSensor();
+        virtual ~PressureSensor();
+        static PressureSensor* getInstance();
+        void start(PressureSuccessCallbackPtr successCB);
+        void stop(JSContextRef globalCtx);
+        void setChangeListener(PressureSuccessCallbackPtr callback);
+        void unsetChangeListener(JSContextRef globalCtx);
+        void getSensorData(PressureSuccessCallbackPtr callback);
+        void broadcast_pressure(float pressure);
+        bool isSupported();
+        void removeCallback(JSContextRef globalCtx);
+        static void sensor_pressure_callback(sensor_h sensor, sensor_event_s *event, void *user_data);
+        static gboolean callPressureStartSuccessCallback(void* data);
+        static gboolean callPressureSuccessCallback(void* data);
+
+    private:
+        sensor_h mPressureHandle;
+        sensor_listener_h mPressureListener;
+        bool mBStart;
+        bool mBSupported;
+        std::map<JSContextRef, PressureSuccessCallbackPtr> mPressureCallbackMap;
+        std::map<JSContextRef, bool> mPressureStartMap;
+
+};
+
+class UltravioletSensor
+{
+    public:
+        UltravioletSensor();
+        virtual ~UltravioletSensor();
+        static UltravioletSensor* getInstance();
+        void start(UltravioletSuccessCallbackPtr successCB);
+        void stop(JSContextRef globalCtx);
+        void setChangeListener(UltravioletSuccessCallbackPtr callback);
+        void unsetChangeListener(JSContextRef globalCtx);
+        void getSensorData(UltravioletSuccessCallbackPtr callback);
+        void broadcast_ultraviolet(float pressure);
+        bool isSupported();
+        void removeCallback(JSContextRef globalCtx);
+        static void sensor_ultraviolet_callback(sensor_h sensor, sensor_event_s *event, void *user_data);
+        static gboolean callUltravioletStartSuccessCallback(void* data);
+        static gboolean callUltravioletSuccessCallback(void* data);
+
+    private:
+        sensor_h mUltravioletHandle;
+        sensor_listener_h mUltravioletListener;
+        bool mBStart;
+        bool mBSupported;
+        std::map<JSContextRef, UltravioletSuccessCallbackPtr> mUltravioletCallbackMap;
+        std::map<JSContextRef, bool> mUltravioletStartMap;
+
+};
+
+} // Sensor
+} // DeviceAPI
+
+#endif // __TIZEN_SENSOR_SERVICE_H__
diff --git a/src/Sensor/SensorUtil.cpp b/src/Sensor/SensorUtil.cpp
new file mode 100755 (executable)
index 0000000..5e4fbe0
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <sstream>
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "SensorUtil.h"
+
+namespace DeviceAPI {
+namespace Sensor {
+
+using namespace DeviceAPI::Common;
+
+void SensorUtil::throwSensorException(const int errorCode,
+                                        const std::string &hint)
+{
+    std::stringstream ss;
+    ss << hint << " : " << getSensorErrorMessage(errorCode);
+    LOGE("%s", ss.str().c_str());
+
+    switch(errorCode) {
+        case SENSOR_ERROR_NOT_SUPPORTED:
+            throw NotSupportedException(ss.str().c_str());
+        default:
+            throw UnknownException(ss.str().c_str());
+    }
+}
+
+std::string SensorUtil::getSensorErrorMessage(const int errorCode)
+{
+    LOGE("Error : %d", errorCode);
+
+    switch(errorCode) {
+        case SENSOR_ERROR_IO_ERROR:
+            return "IO error";
+        case SENSOR_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case SENSOR_ERROR_NOT_SUPPORTED:
+            return "Not supported";
+        case SENSOR_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case SENSOR_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case SENSOR_ERROR_NOT_NEED_CALIBRATION:
+            return "Need calibration";
+        case SENSOR_ERROR_OPERATION_FAILED:
+            return "Operation failed";
+        default:
+            return "Unknown Error";
+    }
+}
+
+} // Sensor
+} // DeviceAPI
diff --git a/src/Sensor/SensorUtil.h b/src/Sensor/SensorUtil.h
new file mode 100755 (executable)
index 0000000..23cd807
--- /dev/null
@@ -0,0 +1,36 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SENSOR_UTIL_H_
+#define __TIZEN_SENSOR_UTIL_H_
+
+#include <string>
+#include <sensor.h>
+
+namespace DeviceAPI {
+namespace Sensor {
+
+class SensorUtil {
+public:
+    static void throwSensorException(const int errorCode, const std::string &hint);
+    static std::string getSensorErrorMessage(const int errorCode);
+};
+
+} // Sensor
+} // DeviceAPI
+
+#endif // __TIZEN_SENSOR_UTIL_H_
\ No newline at end of file
diff --git a/src/Sensor/config.xml b/src/Sensor/config.xml
new file mode 100755 (executable)
index 0000000..3562214
--- /dev/null
@@ -0,0 +1,10 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-sensor.so</library-name>
+    <feature-install-uri>sensor.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/sensor</name>
+    </api-feature>
+</plugin-properties>
diff --git a/src/Sensor/plugin_config.cpp b/src/Sensor/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..1672d03
--- /dev/null
@@ -0,0 +1,43 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Sensor {
+
+static FunctionMapping createSensorFunctions();
+static FunctionMapping SensorFunctions = createSensorFunctions();
+
+DEFINE_FUNCTION_GETTER(Sensor, SensorFunctions);
+
+static FunctionMapping createSensorFunctions()
+{
+    FunctionMapping sensorMapping;
+    return sensorMapping;
+}
+
+} // Sensor
+} // DeviceAPI
diff --git a/src/Sensor/plugin_config.h b/src/Sensor/plugin_config.h
new file mode 100755 (executable)
index 0000000..a540e14
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _SENSOR_PLUGIN_CONFIG_H_
+#define _SENSOR_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Sensor {
+
+// attributes
+#define SENSOR_ATTRIBUTE_SENSOR_TYPE "sensorType"
+
+#define TIZEN_SENSOR_TYPE_LIGHT "LIGHT"
+#define TIZEN_SENSOR_TYPE_PROXIMITY "PROXIMITY"
+#define TIZEN_SENSOR_TYPE_MAGNETIC "MAGNETIC"
+#define TIZEN_SENSOR_TYPE_PRESSURE "PRESSURE"
+#define TIZEN_SENSOR_TYPE_ULTRAVIOLET "ULTRAVIOLET"
+
+#define TIZEN_LIGHT_DATA_LIGHT_LEVEL "lightLevel"
+#define TIZEN_PROXIMITY_DATA_PROXIMITY_LEVEL "proximityState"
+#define TIZEN_PROXIMITY_DATA_MAGNETIC_X "x"
+#define TIZEN_PROXIMITY_DATA_MAGNETIC_Y "y"
+#define TIZEN_PROXIMITY_DATA_MAGNETIC_Z "z"
+#define TIZEN_PROXIMITY_DATA_MAGNETIC_ACCURACY "accuracy"
+#define TIZEN_PRESSURE_DATA_PRESSURE "pressure"
+#define TIZEN_ULTRAVIOLET_DATA_ULTRAVIOLET_LEVEL "ultravioletLevel"
+
+// functions
+#define SENSOR_SERVICE_API_GET_DEFAULT_SENSOR "getDefaultSensor"
+#define SENSOR_SERVICE_API_GET_AVAILABLE_SENSOR "getAvailableSensors"
+
+#define SENSOR_API_START "start"
+#define SENSOR_API_STOP "stop"
+#define SENSOR_API_SET_CHANGE_LISTENER "setChangeListener"
+#define SENSOR_API_UNSET_CHANGE_LISTENER "unsetChangeListener"
+
+#define SENSOR_API_GET_PROXIMITY_SENSOR_DATA "getProximitySensorData"
+#define SENSOR_API_GET_LIGHT_SENSOR_DATA "getLightSensorData"
+#define SENSOR_API_GET_MAGNETIC_SENSOR_DATA "getMagneticSensorData"
+#define SENSOR_API_GET_PRESSURE_SENSOR_DATA "getPressureSensorData"
+#define SENSOR_API_GET_ULTRAVIOLET_SENSOR_DATA "getUltravioletSensorData"
+
+DECLARE_FUNCTION_GETTER(Sensor);
+
+#define SENSOR_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getSensorFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _SENSOR_PLUGIN_CONFIG_H_
diff --git a/src/Sensor/plugin_initializer.cpp b/src/Sensor/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..c55b2e6
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <GlobalContextManager.h>
+#include <Logger.h>
+
+#include "JSSensorService.h"
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sensor {
+
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Sensor] on_widget_start_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Sensor] on_widget_stop_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Sensor] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Sensor] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+    LightSensor::getInstance()->removeCallback(static_cast<JSContextRef>(context));
+    ProximitySensor::getInstance()->removeCallback(static_cast<JSContextRef>(context));
+    PressureSensor::getInstance()->removeCallback(static_cast<JSContextRef>(context));
+    MagneticSensor::getInstance()->removeCallback(static_cast<JSContextRef>(context));
+    UltravioletSensor::getInstance()->removeCallback(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "sensorservice",
+        (js_class_template_getter)JSSensorService::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_END
+
+} // Sensor
+} // DeviceAPI
diff --git a/src/Sound/CMakeLists.txt b/src/Sound/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..8d8cc3f
--- /dev/null
@@ -0,0 +1,52 @@
+
+SET(TARGET_NAME ${sound_target})
+SET(DESTINATION_NAME ${sound_dest})
+SET(TARGET_IMPL_NAME ${sound_impl})
+
+PKG_CHECK_MODULES(sound REQUIRED capi-media-sound-manager vconf)
+
+INCLUDE_DIRECTORIES(
+    ${TOP}/Common
+    ${sound_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${timeutil_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSSoundManager.cpp
+    SoundManager.cpp
+    SoundUtil.cpp
+    VolumeChangeCallback.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${timeutil_impl}
+    ${sound_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/sound
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Sound/JSSoundManager.cpp b/src/Sound/JSSoundManager.cpp
new file mode 100755 (executable)
index 0000000..4722b87
--- /dev/null
@@ -0,0 +1,350 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+
+#include "JSSoundManager.h"
+#include "SoundUtil.h"
+#include "VolumeChangeCallback.h"
+
+#include <SecurityExceptions.h>
+
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <ArgumentValidator.h>
+#include <JSStringRefWrapper.h>
+#include <GlobalContextManager.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sound {
+
+
+JSClassDefinition JSSoundManager::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "SoundManager",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSSoundManager::m_function[] = {
+    {
+        SOUND_MANAGER_API_GET_SOUND_MODE,
+        getSoundMode,
+        kJSPropertyAttributeNone
+    },
+    {
+        SOUND_MANAGER_API_SET_SOUND_MODE_LISTENER,
+        setSoundModeChangeListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        SOUND_MANAGER_API_UNSET_SOUND_MODE_LISTENER,
+        unsetSoundModeChangeListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        SOUND_MANAGER_API_SET_VOLUME,
+        setVolume,
+        kJSPropertyAttributeNone
+    },
+    {
+        SOUND_MANAGER_API_GET_VOLUME,
+        getVolume,
+        kJSPropertyAttributeNone
+    },
+    {
+        SOUND_MANAGER_API_SET_VOLUME_CHANGE_LISTENER,
+        setVolumeChangeListener,
+        kJSPropertyAttributeNone
+    },
+    {
+        SOUND_MANAGER_API_UNSET_VOLUME_CHANGE_LISTENER,
+        unsetVolumeChangeListener,
+        kJSPropertyAttributeNone
+    },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSSoundManager::m_jsClassRef = JSClassCreate(JSSoundManager::getClassInfo());
+
+const JSClassRef JSSoundManager::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSSoundManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSSoundManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Enter");
+
+    JSObjectSetPrivate(object, static_cast<void *>(SoundManager::getInstance()));
+}
+
+void JSSoundManager::finalize(JSObjectRef object)
+{
+    LOGD("Enter");
+}
+
+JSValueRef JSSoundManager::getSoundMode(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try {
+        SoundModeType mode = SoundManager::getInstance()->getSoundMode();
+        return JSUtil::toJSValueRef(context, SoundUtil::soundModeToString(mode));
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException
+            err("Unknown Error in SoundManager.getSoundMode().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+JSValueRef JSSoundManager::setSoundModeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef functionObject = validator.toFunction(0, false);
+
+        SoundModeChangeListenerPtr eventListener(new SoundModeChangeListener(GlobalContextManager::getInstance()->getGlobalContext(context), thisObject, functionObject));
+        SoundManager::getInstance()->setSoundModeChangeListener(eventListener);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException
+            err("Unknown Error in SoundManager.setSoundModeChangeListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+JSValueRef JSSoundManager::unsetSoundModeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+   LOGD("enter");
+
+   try {
+        SoundManager::getInstance()->unsetSoundModeChangeListener();
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException
+            err("Unknown Error in SoundManager.unsetSoundModeChangeListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+   return JSValueMakeUndefined(context);
+
+}
+
+
+JSValueRef JSSoundManager::setVolume(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+   LOGD("enter");
+   try {
+        TIZEN_CHECK_ACCESS(context, exception, SoundManager::getInstance(), SOUND_MANAGER_API_SET_VOLUME);
+
+        // Private Object
+        SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // type
+        std::string type = validator.toString(0);
+
+        // volume
+        double volume = validator.toDouble(1);
+
+        // perform
+        priv->setVolume(SoundUtil::stringToSoundType(type), volume);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in SoundManager.setVolume().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSSoundManager::getVolume(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // type
+        std::string type = validator.toString(0);
+
+        // perform
+        double ret = priv->getVolume(SoundUtil::stringToSoundType(type));
+
+        return JSUtil::toJSValueRef(context, ret);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err("Unknown Error in SoundManager.getVolume().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSSoundManager::setVolumeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+
+        // Private Object
+        SoundManager *priv = static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        // callback
+        JSObjectRef successCallback = validator.toFunction(0);
+        VolumeChangeCallback* volumeChangeCallback =
+            new VolumeChangeCallback(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        volumeChangeCallback->setCallback("onsuccess", successCallback);
+
+        // perform
+        priv->setVolumeChangeListener(volumeChangeCallback);
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in SoundManager.setVolumeChangeListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSSoundManager::unsetVolumeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    try {
+        // Private Object
+        SoundManager *priv =
+            static_cast<SoundManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv) {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        // perform
+        priv->unsetVolumeChangeListener();
+
+        return JSValueMakeUndefined(context);
+    } catch (const BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        DeviceAPI::Common::UnknownException err(
+            "Unknown Error in SoundManager.unsetVolumeChangeListener().");
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+} // Sound
+} // DeviceAPI
diff --git a/src/Sound/JSSoundManager.h b/src/Sound/JSSoundManager.h
new file mode 100755 (executable)
index 0000000..fc99cc1
--- /dev/null
@@ -0,0 +1,122 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_SOUND_MANAGER_H__
+#define __TIZEN_JS_SOUND_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "SoundManager.h"
+
+namespace DeviceAPI {
+namespace Sound {
+
+class JSSoundManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+            JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getSoundMode(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setSoundModeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetSoundModeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+
+    static JSValueRef setVolume(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getVolume(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef setVolumeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetVolumeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // Sound
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/Sound/SoundManager.cpp b/src/Sound/SoundManager.cpp
new file mode 100755 (executable)
index 0000000..1baf103
--- /dev/null
@@ -0,0 +1,511 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SoundManager.h"
+#include "SoundUtil.h"
+
+#include <cmath>
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include <memory>
+
+namespace DeviceAPI {
+namespace Sound {
+
+std::string logSoundModeError(int err)
+{
+    std::string msg = "";
+    switch (err) {
+        case VCONF_OK:
+            msg = "succeeded";
+            break;
+        case VCONF_ERROR:
+            msg = "VCONF_ERROR";
+            break;
+        case VCONF_ERROR_WRONG_PREFIX:
+            msg = "VCONF_ERROR_WRONG_PREFIX";
+            break;
+        case VCONF_ERROR_WRONG_TYPE:
+            msg = "VCONF_ERROR_WRONG_TYPE";
+            break;
+        case VCONF_ERROR_WRONG_VALUE:
+            msg = "VCONF_ERROR_WRONG_VALUE";
+            break;
+        case VCONF_ERROR_NOT_INITIALIZED:
+            msg = "VCONF_ERROR_NOT_INITIALIZED";
+            break;
+        case VCONF_ERROR_NO_MEM:
+            msg = "VCONF_ERROR_NO_MEM";
+            break;
+        case VCONF_ERROR_FILE_PERM:
+            msg = "VCONF_ERROR_FILE_PERM";
+            break;
+        case VCONF_ERROR_FILE_BUSY:
+            msg = "VCONF_ERROR_FILE_BUSY";
+            break;
+        case VCONF_ERROR_FILE_NO_MEM:
+            msg = "VCONF_ERROR_FILE_NO_MEM";
+            break;
+        case VCONF_ERROR_FILE_NO_ENT:
+            msg = "VCONF_ERROR_FILE_NO_ENT";
+            break;
+        case VCONF_ERROR_FILE_OPEN:
+            msg = "VCONF_ERROR_FILE_OPEN";
+            break;
+        case VCONF_ERROR_FILE_FREAD:
+            msg = "VCONF_ERROR_FILE_FREAD";
+            break;
+        case VCONF_ERROR_FILE_FGETS:
+            msg = "VCONF_ERROR_FILE_FGETS";
+            break;
+        case VCONF_ERROR_FILE_WRITE:
+            msg = "VCONF_ERROR_FILE_WRITE";
+            break;
+        case VCONF_ERROR_FILE_SYNC:
+            msg = "VCONF_ERROR_FILE_SYNC";
+            break;
+        case VCONF_ERROR_FILE_CLOSE:
+            msg = "VCONF_ERROR_FILE_CLOSE";
+            break;
+        case VCONF_ERROR_FILE_ACCESS:
+            msg = "VCONF_ERROR_FILE_ACCESS";
+            break;
+        case VCONF_ERROR_FILE_CHMOD:
+            msg = "VCONF_ERROR_FILE_CHMOD";
+            break;
+        case VCONF_ERROR_FILE_LOCK:
+            msg = "VCONF_ERROR_FILE_LOCK";
+            break;
+        case VCONF_ERROR_FILE_REMOVE:
+            msg = "VCONF_ERROR_FILE_REMOVE";
+            break;
+        case VCONF_ERROR_FILE_SEEK:
+            msg = "VCONF_ERROR_FILE_SEEK";
+            break;
+        case VCONF_ERROR_FILE_TRUNCATE:
+            msg = "VCONF_ERROR_FILE_TRUNCATE";
+            break;
+        default:
+            msg = "Unknown error";
+    }
+
+    return msg;
+}
+
+
+SoundModeType getCurrentSoundMode()
+{
+    SoundModeType soundModeType = SOUND_MODE_TYPE_SOUND;
+
+    int ret = 0;
+
+    int isEnableSound = 0;
+    int isEnableVibrate = 0;
+
+    ret = vconf_get_bool(VCONFKEY_SETAPPL_SOUND_STATUS_BOOL, &isEnableSound);
+    if(VCONF_OK != ret )
+    {
+        LOGE("Unknown error : %s", logSoundModeError(ret).c_str());
+        throw UnknownException(("Unknown error : "+logSoundModeError(ret)).c_str());
+    }
+
+    ret = vconf_get_bool(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, &isEnableVibrate);
+    if(VCONF_OK != ret )
+    {
+        LOGE("Unknown error : %s", logSoundModeError(ret).c_str());
+        throw UnknownException(("Unknown error : "+logSoundModeError(ret)).c_str());
+    }
+
+    if(isEnableSound)
+    {
+        if(isEnableVibrate)
+        {
+            LOGE("Wrong state (sound && vibration)");
+            throw UnknownException("Platform has wrong state.");
+        }
+        else
+        {
+            soundModeType = SOUND_MODE_TYPE_SOUND;
+        }
+    }
+    else
+    {
+        if(isEnableVibrate)
+        {
+            soundModeType = SOUND_MODE_TYPE_VIBRATE;
+        }
+        else
+        {
+            soundModeType = SOUND_MODE_TYPE_MUTE;
+        }
+    }
+
+    return soundModeType;
+}
+
+static void onVibrationVconfChangedCb(keynode_t* key, void* user_data)
+{
+    LOGD("enter");
+    SoundModeType soundModeType = SOUND_MODE_TYPE_SOUND;
+    try
+    {
+        soundModeType = getCurrentSoundMode();
+        SoundManager::getInstance()->onChangeSoundMode(soundModeType);
+        return;
+    }catch(const BasePlatformException& ex){
+        LOGE("Unknown error");
+        return;
+    }catch (...) {
+        LOGE("Unknown error");
+        return;
+    }
+
+}
+
+
+
+
+static double __getRoundedValueFromUserInput(double value)
+{
+    return (double)(round(value*10)/10.f);
+}
+
+static double __getRoundedValueFromSystemVolum(int maxSystemVolume, int currentSystemVolume)
+{
+    double tmp = currentSystemVolume * (1/(double)maxSystemVolume);
+    return (double)(round(tmp*10)/10.f);
+}
+
+
+
+SoundManager::SoundManager():
+    SecurityAccessor(),
+    m_eventListener(NULL),
+    m_currentSoundMode(SOUND_MODE_TYPE_SOUND),
+    m_listener(SoundModeChangeListenerPtr(NULL)),
+    m_listeningPlatformEvent(false)
+{
+    LOGD("Enter");
+
+#ifdef PROFILE_WEARABLE
+    sound_type_e types[] = {
+        SOUND_TYPE_SYSTEM, SOUND_TYPE_NOTIFICATION, SOUND_TYPE_ALARM,
+        SOUND_TYPE_MEDIA, SOUND_TYPE_RINGTONE
+    };
+#else
+    sound_type_e types[] = {
+       SOUND_TYPE_SYSTEM, SOUND_TYPE_NOTIFICATION, SOUND_TYPE_ALARM,
+       SOUND_TYPE_MEDIA, SOUND_TYPE_VOICE, SOUND_TYPE_RINGTONE
+    };
+#endif
+    try
+    {
+        int total = sizeof(types) / sizeof(sound_type_e);
+        for (int i = 0 ; i < total ; i++) {
+            int max = 100;
+            int ret = sound_manager_get_max_volume(types[i], &max);
+            if (ret != SOUND_MANAGER_ERROR_NONE) {
+                LOGE("ret : %d",ret);
+                SoundUtil::throwSoundException(ret, "sound_manager_get_max_volume()");
+            }
+            LOGD("maxVolume: %d - %d", types[i], max);
+
+            std::pair<sound_type_e, int> row(types[i], max);
+            m_maxVolumeMap.insert(row);
+        }
+
+        m_currentSoundMode = getCurrentSoundMode();
+    }
+    catch(const BasePlatformException& ex)
+    {
+        LOGE("Error on getCurrentSoundMode");
+        return;
+    }
+
+}
+
+
+SoundManager::~SoundManager()
+{
+    if(m_listeningPlatformEvent)
+    {
+        int ret = 0;
+        LOGD("::vconf_ignore_key_changed");
+
+        ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, onVibrationVconfChangedCb);
+        if(VCONF_OK != ret )
+        {
+            LOGE("Unknown error : %s", logSoundModeError(ret).c_str());
+        }
+    }
+
+}
+
+SoundManager* SoundManager::getInstance()
+{
+    static SoundManager manager;
+    return &manager;
+}
+
+void SoundManager::setVolume(sound_type_e type, double volume)
+{
+    LOGD("Enter");
+
+    if (volume > 1 || volume < 0) {
+        LOGE("Volume should be the value between 0 and 1.");
+        throw InvalidValuesException("Volume should be the value between 0 and 1.");
+    }
+
+    auto it = m_maxVolumeMap.find(type);
+    if (it == m_maxVolumeMap.end()) {
+        LOGE("Failed to find maxVolume of type: %d", type);
+        throw UnknownException("Failed to find maxVolume");
+    }
+
+    int maxVolume = it->second;
+    double tmp = __getRoundedValueFromUserInput(volume);
+    int value = round(tmp * maxVolume);
+    int ret = sound_manager_set_volume(type, value);
+    if (ret != SOUND_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d",ret);
+        SoundUtil::throwSoundException(ret, "sound_manager_set_volume()");
+    }
+    else {
+        LOGD("sound_manager_set_volume completed. received(%f), set(%d)", volume, value);
+    }
+}
+
+double SoundManager::getVolume(sound_type_e type)
+{
+    auto it = m_maxVolumeMap.find(type);
+    if (it == m_maxVolumeMap.end()) {
+        LOGE("Failed to find maxVolume of type: %d", type);
+        throw UnknownException("Failed to find maxVolume");
+    }
+
+    int maxVolume = it->second;
+    int currentVolume = 0;
+    int ret = sound_manager_get_volume(type, &currentVolume);
+    if (ret != SOUND_MANAGER_ERROR_NONE) {
+        LOGE("ret : %d",ret);
+        SoundUtil::throwSoundException(ret, "sound_manager_get_volume()");
+    }
+    else {
+        double rounded_d = __getRoundedValueFromSystemVolum(maxVolume, currentVolume);
+        LOGD("sound_manager_get_volume - type[%d]: current:%d = rounded:%lf", type, currentVolume, rounded_d);
+        return rounded_d;
+    }
+}
+
+void SoundManager::setVolumeChangeListener(VolumeChangeCallback *callback)
+{
+    LOGD("Enter");
+
+    if (m_eventListener) {
+        delete m_eventListener;
+        m_eventListener = NULL;
+    } else {
+        int ret = sound_manager_set_volume_changed_cb(volumeChangeCallback,
+            NULL);
+        if (ret != SOUND_MANAGER_ERROR_NONE) {
+            LOGE("ret : %d",ret);
+            SoundUtil::throwSoundException(ret, "sound_manager_set_volume_changed_cb()");
+        }
+    }
+    if (callback)
+        m_eventListener = callback;
+    else
+        LOGE("null callback");
+}
+
+void SoundManager::unsetVolumeChangeListener()
+{
+    LOGD("Enter");
+
+    if (m_eventListener) {
+        delete m_eventListener;
+        m_eventListener = NULL;
+#ifdef PROFILE_WEARABLE
+        sound_manager_unset_volume_changed_cb();
+#else
+        int ret = sound_manager_unset_volume_changed_cb();
+        if (ret != SOUND_MANAGER_ERROR_NONE) {
+            LOGE("ret : %d",ret);
+            SoundUtil::throwSoundException(ret, "sound_manager_unset_volume_changed_cb()");
+        }
+#endif
+    }
+    else
+    {
+        LOGD("No issue if no listener registered");
+    }
+}
+
+void SoundManager::volumeChangeCallback(sound_type_e type,
+    unsigned int value, void *userData)
+{
+    LOGD("Enter %d, %d", type, value);
+
+    getInstance()->broadcastEvent(type, value);
+}
+
+void SoundManager::broadcastEvent(sound_type_e type, unsigned int value)
+{
+    try {
+        VolumeChangeCallback *cb = m_eventListener;
+        if (cb)
+        {
+            auto it = m_maxVolumeMap.find(type);
+            if (it == m_maxVolumeMap.end()) {
+                LOGE("Failed to find maxVolume of type: %d", type);
+                throw UnknownException("Failed to find maxVolume");
+            }
+
+            int maxVolume = it->second;
+            double rounded_d = __getRoundedValueFromSystemVolum(maxVolume, value);
+            LOGD("sound_manager_get_volume - type[%d]: current:%d = rounded:%lf", type, value, rounded_d);
+
+            cb->setType(type);
+            cb->setVolume(rounded_d);
+
+            if (!g_idle_add(VolumeChangeCallback::complete, cb)) {
+                LOGE("g_idle_addtion failed");
+                throw UnknownException("g_idle addition failed");
+            }
+        }
+        else
+            LOGE("Something strange happened");
+    } catch (BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("Something strange happened");
+    }
+}
+
+
+SoundModeType SoundManager::getSoundMode()
+{
+    LOGD("enter");
+    return getCurrentSoundMode();
+}
+
+void SoundManager::setSoundModeChangeListener(SoundModeChangeListenerPtr listener)
+{
+    LOGD("enter");
+    m_listener = listener;
+
+    if(!m_listeningPlatformEvent)
+    {
+        int ret = vconf_notify_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL,onVibrationVconfChangedCb, static_cast<void*>(this));
+        if(VCONF_OK != ret )
+        {
+            LOGE("Unknown error : %s", logSoundModeError(ret).c_str());
+            throw UnknownException("Platform failed to register callback.");
+        }
+
+        m_listeningPlatformEvent = true;
+    }
+    LOGD("end");
+}
+
+void SoundManager::unsetSoundModeChangeListener()
+{
+    LOGD("enter");
+
+    m_listener = NULL;
+
+    if(m_listeningPlatformEvent)
+    {
+        LOGD("enter");
+        int ret = vconf_ignore_key_changed(VCONFKEY_SETAPPL_VIBRATION_STATUS_BOOL, onVibrationVconfChangedCb);
+        if(VCONF_OK != ret )
+        {
+            LOGE("Unknown error : %s", logSoundModeError(ret).c_str());
+            throw UnknownException("Platform failed to unregister callback.");
+
+        }
+
+        m_listeningPlatformEvent = false;
+    }
+}
+
+void SoundManager::onChangeSoundMode(SoundModeType mode)
+{
+
+    if(!m_listeningPlatformEvent)
+    {
+        LOGE("event is not registered");
+        return;
+    }
+
+    if(m_listener == NULL)
+    {
+        LOGE("event listener is not registered");
+        return;
+    }
+
+    if(m_currentSoundMode == mode)
+    {
+        LOGD("sound mode is same as before");
+        return;
+    }
+
+    m_currentSoundMode = mode;
+    m_listener->onChangeSoundMode(mode);
+}
+
+SoundModeChangeListener::SoundModeChangeListener(JSContextRef context, JSObjectRef thisObject, JSObjectRef function) :
+        m_context(context),
+        m_thisObject(thisObject),
+        m_function(function)
+{
+    JSValueProtect(m_context, m_function);
+}
+
+SoundModeChangeListener::~SoundModeChangeListener()
+{
+    JSValueUnprotect(m_context, m_function);
+}
+
+void SoundModeChangeListener::onChangeSoundMode(SoundModeType mode)
+{
+    JSValueRef jsValues[1];
+
+    std::string modeStr = SoundUtil::soundModeToString(mode);
+
+    JSStringRefWrapper jsModeStrWrapper(modeStr);
+    jsValues[0] = JSValueMakeString(m_context, jsModeStrWrapper.get());
+
+    LOGD("Calling user callback %s", modeStr.c_str());
+
+    JSValueRef exception = NULL;
+    JSObjectCallAsFunction(m_context, m_function, m_thisObject, 1, jsValues, &exception);
+
+    if(exception != NULL)
+    {
+        LOGD("User callback threw exception");
+    }
+}
+
+
+} // Sound
+} // DeviceAPI
diff --git a/src/Sound/SoundManager.h b/src/Sound/SoundManager.h
new file mode 100755 (executable)
index 0000000..f9f743c
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SOUND_MANAGER_H__
+#define __TIZEN_SOUND_MANAGER_H__
+
+#include <SecurityAccessor.h>
+#include <sound_manager.h>
+
+#include <vconf.h>
+#include <vconf-keys.h>
+
+
+#include <JSStringRefWrapper.h>
+
+#include "SoundTypes.h"
+#include "VolumeChangeCallback.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sound {
+
+class SoundModeChangeListener
+{
+public:
+    // context MUST be a global context.
+    // function MUST be a function object. There is no validation check when invoking.
+    SoundModeChangeListener(JSContextRef context, JSObjectRef thisObject, JSObjectRef function);
+    virtual ~SoundModeChangeListener();
+
+    virtual void onChangeSoundMode(SoundModeType mode);
+
+private:
+    JSContextRef m_context;
+    JSObjectRef m_thisObject;
+    JSObjectRef m_function;
+};
+
+typedef std::shared_ptr<SoundModeChangeListener> SoundModeChangeListenerPtr;
+
+
+class SoundManager : public Common::SecurityAccessor{
+public:
+    static SoundManager* getInstance();
+
+    void setVolume(sound_type_e type, double volume);
+
+    double getVolume(sound_type_e type);
+
+    void setVolumeChangeListener(VolumeChangeCallback *callback);
+
+    void unsetVolumeChangeListener();
+
+    SoundModeType getSoundMode();
+
+    void setSoundModeChangeListener(SoundModeChangeListenerPtr listener);
+
+    void unsetSoundModeChangeListener();
+
+    void onChangeSoundMode(SoundModeType mode);
+
+private:
+    SoundManager();
+    virtual ~SoundManager();
+
+    SoundManager(SoundManager const&) = delete;
+    SoundManager& operator=(SoundManager const&) = delete;
+
+    static void volumeChangeCallback(sound_type_e type, unsigned int value, void *userData);
+    void broadcastEvent(sound_type_e type, unsigned int value);
+
+    VolumeChangeCallback *m_eventListener;
+
+    std::map<sound_type_e, int> m_maxVolumeMap;
+    std::map<int, int> m_userToSystemValueMap;
+
+    //Sound Mode
+    SoundModeType m_currentSoundMode;
+    SoundModeChangeListenerPtr m_listener;
+    bool m_listeningPlatformEvent;
+
+};
+
+} // Sound
+} // DeviceAPI
+
+#endif // __TIZEN_SOUND_MANAGER_H__
diff --git a/src/Sound/SoundTypes.h b/src/Sound/SoundTypes.h
new file mode 100755 (executable)
index 0000000..297fda1
--- /dev/null
@@ -0,0 +1,44 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _SOUND_TYPES_H_
+#define _SOUND_TYPES_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace DeviceAPI {
+namespace Sound {
+
+// enum SoundType
+#define TIZEN_SOUND_TYPE_SYSTEM "SYSTEM"
+#define TIZEN_SOUND_TYPE_NOTIFICATION "NOTIFICATION"
+#define TIZEN_SOUND_TYPE_ALARM "ALARM"
+#define TIZEN_SOUND_TYPE_MEDIA "MEDIA"
+#define TIZEN_SOUND_TYPE_VOICE "VOICE"
+
+// enum MobileSoundType
+#define TIZEN_MOBILE_SOUND_TYPE_RINGTONE "RINGTONE"
+
+// typedef SoundSoundType
+typedef union SoundSoundType;
+
+} // Sound
+} // DeviceAPI
+
+#endif // _SOUND_TYPES_H_
diff --git a/src/Sound/SoundUtil.cpp b/src/Sound/SoundUtil.cpp
new file mode 100755 (executable)
index 0000000..29efb14
--- /dev/null
@@ -0,0 +1,139 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SoundUtil.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include <sstream>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sound {
+
+std::string SoundUtil::soundTypeToString(sound_type_e sound_type)
+{
+    switch (sound_type) {
+        case SOUND_TYPE_SYSTEM:
+            return SYSTEM;
+        case SOUND_TYPE_NOTIFICATION:
+            return NOTIFICATION;
+        case SOUND_TYPE_ALARM:
+            return ALARM;
+        case SOUND_TYPE_MEDIA:
+            return MEDIA;
+#ifndef PROFILE_WEARABLE
+        case SOUND_TYPE_VOICE:
+            return VOICE;
+#endif
+        case SOUND_TYPE_RINGTONE:
+            return RINGTONE;
+        default:
+            LOGE("Invalid SoundSoundType : %d", sound_type);
+            throw TypeMismatchException("Invalid SoundSoundType");
+    }
+}
+
+sound_type_e SoundUtil::stringToSoundType(std::string sound_type_str)
+{
+    if (sound_type_str == SYSTEM) {
+        return SOUND_TYPE_SYSTEM;
+    } else if (sound_type_str == NOTIFICATION) {
+        return SOUND_TYPE_NOTIFICATION;
+    } else if (sound_type_str == ALARM) {
+        return SOUND_TYPE_ALARM;
+    } else if (sound_type_str == MEDIA) {
+        return SOUND_TYPE_MEDIA;
+#ifndef PROFILE_WEARABLE
+    } else if (sound_type_str == VOICE) {
+        return SOUND_TYPE_VOICE;
+#endif
+    } else if (sound_type_str == RINGTONE) {
+        return SOUND_TYPE_RINGTONE;
+    } else {
+        LOGE("Invalid SoundSoundType : %s", sound_type_str.c_str());
+        throw TypeMismatchException("Invalid SoundSoundType");
+    }
+}
+
+std::string SoundUtil::soundModeToString(SoundModeType sound_mode)
+{
+    switch (sound_mode) {
+        case SOUND_MODE_TYPE_SOUND:
+            return SOUND;
+        case SOUND_MODE_TYPE_VIBRATE:
+            return VIBRATE;
+        case SOUND_MODE_TYPE_MUTE:
+            return MUTE;
+        default:
+            LOGE("Invalid SoundMode: %d", sound_mode);
+            throw TypeMismatchException("Invalid SoundMode");
+    }
+}
+
+SoundModeType SoundUtil::stringToSoundMode(std::string sound_mode_str)
+{
+    if (sound_mode_str == SOUND) {
+        return SOUND_MODE_TYPE_SOUND;
+    } else if (sound_mode_str == VIBRATE) {
+        return SOUND_MODE_TYPE_VIBRATE;
+    } else if (sound_mode_str == MUTE) {
+        return SOUND_MODE_TYPE_MUTE;
+    } else {
+        LOGE("Invalid SoundMode: %s", sound_mode_str.c_str());
+        throw TypeMismatchException("Invalid SoundMode");
+    }
+}
+
+std::string& SoundUtil::getSoundErrorMessage(const int errorCode){
+    switch(errorCode) {
+        case SOUND_MANAGER_ERROR_OUT_OF_MEMORY:
+            return errOutOfMemory;
+        case SOUND_MANAGER_ERROR_INVALID_PARAMETER:
+            return errInvalidParameter;
+        case SOUND_MANAGER_ERROR_INVALID_OPERATION:
+            return errInvalidOperation;
+#ifndef PROFILE_WEARABLE
+        case SOUND_MANAGER_ERROR_PERMISSION_DENIED:
+            return errPermissionDenied;
+        case SOUND_MANAGER_ERROR_NOT_SUPPORTED:
+            return errNotSupported;
+        case SOUND_MANAGER_ERROR_NO_DATA:
+            return errNoData ;
+#endif
+        case SOUND_MANAGER_ERROR_NO_PLAYING_SOUND:
+            return errNoPlayingSound ;
+        case SOUND_MANAGER_ERROR_INTERNAL:
+            return errInternal;
+        case SOUND_MANAGER_ERROR_POLICY:
+            return errPolicy;
+        default:
+            return errUnknown;
+    }
+}
+
+std::string SoundUtil::getSoundLogMessage(const int errorCode, const std::string &hint){
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getSoundErrorMessage(errorCode) << ", " << errorCode;
+    return std::string(ss.str());
+}
+
+
+} // Sound
+} // DeviceAPI
diff --git a/src/Sound/SoundUtil.h b/src/Sound/SoundUtil.h
new file mode 100755 (executable)
index 0000000..31f4a13
--- /dev/null
@@ -0,0 +1,86 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SOUND_UTIL_H__
+#define __TIZEN_SOUND_UTIL_H__
+
+#include <string>
+
+#include <sound_manager.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Sound {
+
+namespace {
+const std::string SYSTEM = "SYSTEM";
+const std::string NOTIFICATION = "NOTIFICATION";
+const std::string ALARM = "ALARM";
+const std::string MEDIA = "MEDIA";
+const std::string VOICE = "VOICE";
+const std::string RINGTONE = "RINGTONE";
+
+const std::string SOUND = "SOUND";
+const std::string VIBRATE = "VIBRATE";
+const std::string MUTE = "MUTE";
+
+static std::string errOutOfMemory = "Out of memory";
+static std::string errInvalidParameter = "Invalid parameter";
+static std::string errInvalidOperation = "Invalid Operation";
+static std::string errPermissionDenied = "Permission denied";
+static std::string errNotSupported = "Not supported";
+static std::string errNoData = "No data";
+static std::string errNoPlayingSound = "No playing sound";
+static std::string errInternal = "Internal Error";
+static std::string errPolicy = "Policy Error";
+static std::string errUnknown = "Unknown error";
+
+}
+
+enum SoundModeType
+{
+    SOUND_MODE_TYPE_SOUND,
+    SOUND_MODE_TYPE_VIBRATE,
+    SOUND_MODE_TYPE_MUTE
+};
+
+class SoundUtil
+{
+public:
+    static std::string soundTypeToString(sound_type_e sound_type);
+    static sound_type_e stringToSoundType(std::string sound_type_str);
+
+    static std::string soundModeToString(SoundModeType sound_mode);
+    static SoundModeType stringToSoundMode(std::string sound_mode_str);
+
+    template <class T = DeviceAPI::Common::UnknownException>
+    static void throwSoundException(const int errorCode, const std::string& hint) {
+        std::string message = SoundUtil::getSoundLogMessage(errorCode, hint);
+        LOGE("%s", message.c_str());
+        throw T(message.c_str());
+    }
+    static std::string& getSoundErrorMessage(const int errorCode);
+    static std::string getSoundLogMessage(const int errorCode, const std::string& hint);
+
+private:
+};
+
+} // Sound
+} // DeviceAPI
+
+#endif // __TIZEN_SOUND_UTIL_H__
diff --git a/src/Sound/VolumeChangeCallback.cpp b/src/Sound/VolumeChangeCallback.cpp
new file mode 100644 (file)
index 0000000..7a4f31c
--- /dev/null
@@ -0,0 +1,99 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "VolumeChangeCallback.h"
+
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sound {
+
+VolumeChangeCallback::VolumeChangeCallback(JSContextRef global_ctx):
+    MultiCallbackUserData(global_ctx)
+{
+}
+
+VolumeChangeCallback::~VolumeChangeCallback()
+{
+}
+
+
+void VolumeChangeCallback::onSuccess()
+{
+    LOGD("Enter");
+
+    JSContextRef context = getContext();
+    JSValueRef type = JSUtil::toJSValueRef(context, SoundUtil::soundTypeToString(m_type));
+    JSValueRef volume = JSUtil::toJSValueRef(context, m_volume);
+
+    JSValueRef args[2];
+    args[0] = type;
+    args[1] = volume;
+
+    invokeCallback("onsuccess", 2, args);
+}
+
+gboolean VolumeChangeCallback::complete(void *data)
+{
+    LOGD("Enter");
+
+    VolumeChangeCallback *cb = static_cast<VolumeChangeCallback *>(data);
+
+    try {
+        JSContextRef context = cb->getContext();
+        if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+            LOGE("context was closed");
+            throw UnknownException("context was closed");
+        }
+
+        cb->onSuccess();
+    } catch (BasePlatformException &err) {
+        LOGE("%s: %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("Something strange happened");
+    }
+
+    return false;
+}
+
+sound_type_e VolumeChangeCallback::getType()
+{
+    return m_type;
+}
+
+void VolumeChangeCallback::setType(sound_type_e type)
+{
+    m_type = type;
+}
+
+double VolumeChangeCallback::getVolume()
+{
+    return m_volume;
+}
+
+void VolumeChangeCallback::setVolume(double volume)
+{
+    m_volume = volume;
+}
+
+} // Sound
+} // DeviceAPI
diff --git a/src/Sound/VolumeChangeCallback.h b/src/Sound/VolumeChangeCallback.h
new file mode 100755 (executable)
index 0000000..00239fa
--- /dev/null
@@ -0,0 +1,58 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SOUND_VOLUME_CHANGE_CALLBACK_H__
+#define __TIZEN_SOUND_VOLUME_CHANGE_CALLBACK_H__
+
+#include <string>
+#include <glib.h>
+
+#include <JavaScriptCore/JavaScript.h>
+#include <MultiCallbackUserData.h>
+#include <JSWebAPIError.h>
+
+#include "SoundUtil.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sound {
+
+class VolumeChangeCallback: public MultiCallbackUserData
+{
+public:
+    VolumeChangeCallback(JSContextRef global_ctx);
+    virtual ~VolumeChangeCallback();
+
+    void onSuccess();
+
+    static gboolean complete(void *data);
+
+    sound_type_e getType();
+    void setType(sound_type_e type);
+    double getVolume();
+    void setVolume(double volume);
+
+private:
+    sound_type_e m_type;
+    double m_volume;
+};
+
+} // Sound
+} // DeviceAPI
+
+#endif // __TIZEN_SOUND_VOLUME_CHANGE_CALLBACK_H__
diff --git a/src/Sound/config.xml b/src/Sound/config.xml
new file mode 100644 (file)
index 0000000..8fc2c80
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-sound.so</library-name>
+    <feature-install-uri>sound.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/volume.set</name>
+        <device-capability>volume.set</device-capability>
+    </api-feature>
+</plugin-properties>
diff --git a/src/Sound/plugin_config.cpp b/src/Sound/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..73396dd
--- /dev/null
@@ -0,0 +1,74 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "plugin_config.h"
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#define SOUND_FEATURE_API_VOLUME_SET "http://tizen.org/privilege/volume.set"
+
+#define SOUND_DEVICE_CAP_VOLUME_SET "volume.set"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Sound {
+
+static FunctionMapping createSoundFunctions();
+static FunctionMapping SoundFunctions = createSoundFunctions();
+
+DEFINE_FUNCTION_GETTER(Sound, SoundFunctions);
+
+static FunctionMapping createSoundFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_SOUND_VOLUME_SET, SOUND_DEVICE_CAP_VOLUME_SET);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_SOUND_VOLUME_SET);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_SOUND_VOLUME_SET, DEVICE_CAP_SOUND_VOLUME_SET);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_SOUND_VOLUME_SET, SOUND_FEATURE_API_VOLUME_SET);
+
+    ACE_CREATE_FEATURE_LIST(SOUND_FEATURES_VOLUME_SET);
+    ACE_ADD_API_FEATURE(SOUND_FEATURES_VOLUME_SET, FEATURE_SOUND_VOLUME_SET);
+
+    // SoundManager.setVolume
+    AceFunction soundManagerSetVolumeFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_SOUND_MANAGER_SET_VOLUME,
+        SOUND_MANAGER_API_SET_VOLUME,
+        SOUND_FEATURES_VOLUME_SET,
+        DEVICE_LIST_SOUND_VOLUME_SET);
+
+    FunctionMapping soundMapping;
+
+    soundMapping.insert(std::make_pair(
+        SOUND_MANAGER_API_SET_VOLUME,
+        soundManagerSetVolumeFunc));
+
+    return soundMapping;
+}
+
+} // Sound
+} // DeviceAPI
diff --git a/src/Sound/plugin_config.h b/src/Sound/plugin_config.h
new file mode 100755 (executable)
index 0000000..1766391
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _SOUND_PLUGIN_CONFIG_H_
+#define _SOUND_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Sound {
+
+// attributes
+
+// functions
+#define SOUND_MANAGER_API_GET_SOUND_MODE "getSoundMode"
+#define SOUND_MANAGER_API_SET_VOLUME "setVolume"
+#define SOUND_MANAGER_API_GET_VOLUME "getVolume"
+#define SOUND_MANAGER_API_SET_VOLUME_CHANGE_LISTENER "setVolumeChangeListener"
+#define SOUND_MANAGER_API_UNSET_VOLUME_CHANGE_LISTENER "unsetVolumeChangeListener"
+#define SOUND_MANAGER_API_SET_SOUND_MODE_LISTENER "setSoundModeChangeListener"
+#define SOUND_MANAGER_API_UNSET_SOUND_MODE_LISTENER "unsetSoundModeChangeListener"
+
+DECLARE_FUNCTION_GETTER(Sound);
+
+#define SOUND_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getSoundFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _SOUND_PLUGIN_CONFIG_H_
diff --git a/src/Sound/plugin_initializer.cpp b/src/Sound/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..1ad3f58
--- /dev/null
@@ -0,0 +1,107 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/plugin_initializer_def.h>
+
+#include "JSSoundManager.h"
+#include "plugin_config.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Sound {
+
+AceSecurityStatus soundAceCheckAccessFunction(const char* functionName)
+{
+    return SOUND_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerSoundSetter,
+        SecurityAccessor,
+        gSecurityAccessor);
+
+class_definition_options_t ClassOptions =
+{
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerSoundSetter,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\Sound] on_widget_start_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, soundAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\Sound] on_widget_stop_callback (%d)", widgetId);
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    } catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\Sound] on_frame_load_callback (%p)", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\Sound] on_frame_unload_callback (%p)", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "sound",
+        (js_class_template_getter)JSSoundManager::getClassRef,
+        &ClassOptions)
+PLUGIN_CLASS_MAP_END
+
+} // Sound
+} // DeviceAPI
diff --git a/src/SystemSetting/CMakeLists.txt b/src/SystemSetting/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..169f141
--- /dev/null
@@ -0,0 +1,56 @@
+SET(TARGET_NAME ${systemsetting_target})
+SET(DESTINATION_NAME ${systemsetting_dest})
+SET(TARGET_IMPL_NAME ${systemsetting_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_systemsetting REQUIRED capi-system-system-settings)
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${TOP}/Tizen
+    ${TOP}/Filesystem
+    ${platform_pkgs_systemsetting_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${filesystem_dest}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    SystemSetting.cpp
+    ISystemSetting.cpp
+    SystemSettingFactory.cpp
+    JSSystemSetting.cpp
+    SystemSettingResponseDispatcher.cpp
+    ConverterSystemSetting.cpp
+    SystemSettingAsyncCallbackManager.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${tizen_impl}
+    ${filesystem_impl}
+    ${platform_pkgs_systemsetting_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/systemsetting
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/SystemSetting/ConverterSystemSetting.cpp b/src/SystemSetting/ConverterSystemSetting.cpp
new file mode 100755 (executable)
index 0000000..a73aa70
--- /dev/null
@@ -0,0 +1,122 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/Exception.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/JSDOMExceptionFactory.h>
+#include "ConverterSystemSetting.h"
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+#include <Logger.h>
+//#include "JSMessageAttachment.h"
+//#include "JSConversation.h"
+//#include "JSMessageFolder.h"
+
+using namespace std;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+ConverterSystemSetting::ConverterSystemSetting(JSContextRef context) :
+    Converter(context)
+{
+}
+
+ConverterSystemSetting::~ConverterSystemSetting()
+{
+}
+
+SettingType ConverterSystemSetting::toSettingType(JSValueRef arg)
+{
+    LOGD("Enter");
+    return toSettingType(toJSObjectRef(arg));
+}
+
+SettingType ConverterSystemSetting::toSettingType(JSObjectRef arg)
+{
+    // convert JSvalue to message type enum
+    std::string strSettingType = toString(arg);
+    LOGD("Setting Type : %s", strSettingType.c_str());
+
+    if (strSettingType.compare("HOME_SCREEN") == 0)
+    {
+        return HOME_SCREEN;
+    }
+    else if (strSettingType.compare("LOCK_SCREEN") == 0)
+    {
+        return LOCK_SCREEN;
+    }
+    else if (strSettingType.compare("INCOMING_CALL") == 0)
+    {
+        return INCOMMING_CALL;
+    }
+    else if (strSettingType.compare("NOTIFICATION_EMAIL") == 0)
+    {
+        return NOTIFICATION_EMAIL;
+    }
+    else
+    {
+        ThrowMsg(WrtDeviceApis::Commons::ConversionException, "Setting type not supported");
+    }
+}
+
+/*
+std::string ConverterMessage::toMessageType(long msgtype)
+{
+    LOGD("Messasge Type : %ld", msgtype);
+
+    switch (msgtype)
+    {
+        case Api::Messaging::SMS:
+            return "messaging.sms";
+        case Api::Messaging::MMS:
+            return "messaging.mms";
+        case Api::Messaging::EMAIL:
+            return "messaging.email";
+        default :
+            ThrowMsg(WrtDeviceApis::Commons::ConversionException, "message type not supported");
+    }
+}
+
+std::string ConverterMessage::toMessageStatusType(long msgstatus)
+{
+    LOGD("Messasge Status : %ld", msgstatus);
+
+    switch (msgstatus)
+    {
+        case Api::Messaging::MESSAGE_STATUS_SENT:
+            return "SENT";
+        case Api::Messaging::MESSAGE_STATUS_SENDING:
+            return "SENDING";
+        case Api::Messaging::MESSAGE_STATUS_FAILED:
+            return "FAILED";
+        case Api::Messaging::MESSAGE_STATUS_DRAFT:
+            return "DRAFT";
+        case Api::Messaging::MESSAGE_STATUS_CREATED:
+        case Api::Messaging::MESSAGE_STATUS_LOADED:
+            return "";
+        default :
+            ThrowMsg(WrtDeviceApis::Commons::ConversionException, "message status not supported");
+    }
+}
+*/
+
+}
+}
diff --git a/src/SystemSetting/ConverterSystemSetting.h b/src/SystemSetting/ConverterSystemSetting.h
new file mode 100755 (executable)
index 0000000..0a8d3ad
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/Converter.h>
+#include "ISystemSettingType.h"
+
+#ifndef CONVERTEDSYSTEMSETTING_H
+#define CONVERTEDSYSTEMSETTING_H
+
+namespace DeviceAPI {
+namespace SystemSetting {
+class ConverterSystemSetting : public WrtDeviceApis::CommonsJavaScript::Converter
+{
+public:
+    using WrtDeviceApis::CommonsJavaScript::Converter::toJSValueRef;
+    explicit ConverterSystemSetting(JSContextRef context);
+    virtual ~ConverterSystemSetting();
+    SettingType toSettingType(JSValueRef arg);
+    SettingType toSettingType(JSObjectRef arg);
+    //std::string toMessageStatusType(long msgstatus);
+};
+
+typedef WrtDeviceApis::CommonsJavaScript::ConverterFactory<ConverterSystemSetting> ConverterSystemSettingFactory;
+}
+}
+
+#endif
diff --git a/src/SystemSetting/EventGetSetting.h b/src/SystemSetting/EventGetSetting.h
new file mode 100755 (executable)
index 0000000..da83814
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_SYSTEMSETTING_GET_SETTING_EVENT_H_
+#define WRTPLUGINS_API_SYSTEMSETTING_GET_SETTING_EVENT_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+
+#include "ISystemSettingType.h"
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+class EventGetSetting : public WrtDeviceApis::Commons::IEvent<EventGetSetting>
+{
+public:
+    void setSettingValue(const std::string &value)
+    {
+        m_settingValue = value;
+    }
+
+    std::string getSettingValue() const
+    {
+        return m_settingValue;
+    }
+
+    // void setSettingType(const std::string &value)
+    void setSettingType(SettingType value)
+    {
+        m_settingType = value;
+    }
+
+    // std::string getSettingType() const
+    SettingType getSettingType() const
+    {
+        return m_settingType;
+    }
+
+    EventGetSetting()
+    {
+    }
+
+    ~EventGetSetting()
+    {
+    }
+
+private:
+    std::string m_settingValue;
+    // std::string m_settingType;
+    // USE TO CONVERTER
+    SettingType m_settingType;
+    // int m_settingType;
+
+};
+
+typedef std::shared_ptr<EventGetSetting> EventGetSettingPtr;
+
+}
+}
+#endif
diff --git a/src/SystemSetting/EventSetRingtone.h b/src/SystemSetting/EventSetRingtone.h
new file mode 100755 (executable)
index 0000000..60235f1
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_SYSTEMSETTING_SET_RINGTONE_EVENT_H_
+#define WRTPLUGINS_API_SYSTEMSETTING_SET_RINGTONE_EVENT_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+class EventSetRingtone : public WrtDeviceApis::Commons::IEvent<EventSetRingtone>
+{
+public:
+    void setRingtoneURI(const std::string &value)
+    {
+        m_ringtoneUri = value;
+    }
+
+    std::string getRingtoneURI() const
+    {
+        return m_ringtoneUri;
+    }
+
+    void setRingtoneType(const std::string &value)
+    {
+        m_ringtoneType = value;
+    }
+
+    std::string getRingtoneType() const
+    {
+        return m_ringtoneType;
+    }
+
+    EventSetRingtone()
+    {
+    }
+
+    ~EventSetRingtone()
+    {
+    }
+
+private:
+    std::string m_ringtoneUri;
+    std::string m_ringtoneType;
+};
+
+typedef std::shared_ptr<EventSetRingtone> EventSetRingtonePtr;
+
+}
+}
+#endif
diff --git a/src/SystemSetting/EventSetSetting.h b/src/SystemSetting/EventSetSetting.h
new file mode 100755 (executable)
index 0000000..9c57fb0
--- /dev/null
@@ -0,0 +1,69 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_SYSTEMSETTING_SET_SETTING_EVENT_H_
+#define WRTPLUGINS_API_SYSTEMSETTING_SET_SETTING_EVENT_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+
+#include "ISystemSettingType.h"
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+class EventSetSetting : public WrtDeviceApis::Commons::IEvent<EventSetSetting>
+{
+public:
+    void setSettingValue(const std::string &value)
+    {
+        m_settingValue = value;
+    }
+
+    std::string getSettingValue() const
+    {
+        return m_settingValue;
+    }
+
+    void setSettingType(SettingType value)
+    {
+        m_settingType = value;
+    }
+
+    SettingType getSettingType() const
+    {
+        return m_settingType;
+    }
+
+    EventSetSetting()
+    {
+    }
+
+    ~EventSetSetting()
+    {
+    }
+
+private:
+    std::string m_settingValue;
+    SettingType m_settingType;
+};
+
+typedef std::shared_ptr<EventSetSetting> EventSetSettingPtr;
+
+}
+}
+#endif
diff --git a/src/SystemSetting/EventSetWallpaper.h b/src/SystemSetting/EventSetWallpaper.h
new file mode 100755 (executable)
index 0000000..2339dbc
--- /dev/null
@@ -0,0 +1,67 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_SYSTEMSETTING_SET_WALLPAPER_EVENT_H_
+#define WRTPLUGINS_API_SYSTEMSETTING_SET_WALLPAPER_EVENT_H_
+
+#include <Commons/IEvent.h>
+#include <memory>
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+class EventSetWallpaper : public WrtDeviceApis::Commons::IEvent<EventSetWallpaper>
+{
+public:
+    void setWallpaperURI(const std::string &value)
+    {
+        m_wallpaperUri = value;
+    }
+
+    std::string getWallpaperURI() const
+    {
+        return m_wallpaperUri;
+    }
+
+    void setWallpaperType(const std::string &value)
+    {
+        m_wallpaperType = value;
+    }
+
+    std::string getWallpaperType() const
+    {
+        return m_wallpaperType;
+    }
+
+    EventSetWallpaper()
+    {
+    }
+
+    ~EventSetWallpaper()
+    {
+    }
+
+private:
+    std::string m_wallpaperUri;
+    std::string m_wallpaperType;
+};
+
+typedef std::shared_ptr<EventSetWallpaper> EventSetWallpaperPtr;
+
+}
+}
+#endif
diff --git a/src/SystemSetting/ISystemSetting.cpp b/src/SystemSetting/ISystemSetting.cpp
new file mode 100755 (executable)
index 0000000..b4e9f03
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "ISystemSetting.h"
+#include "EventSetWallpaper.h"
+#include "EventSetRingtone.h"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+ISystemSetting::ISystemSetting() :
+    EventRequestReceiver< EventSetWallpaper >(ThreadEnum::NULL_THREAD),
+    EventRequestReceiver< EventSetRingtone >(ThreadEnum::NULL_THREAD),
+    EventRequestReceiver< EventSetSetting >(ThreadEnum::NULL_THREAD),
+    EventRequestReceiver< EventGetSetting >(ThreadEnum::NULL_THREAD)
+{
+}
+
+ISystemSetting::~ISystemSetting()
+{
+}
+
+}
+}
diff --git a/src/SystemSetting/ISystemSetting.h b/src/SystemSetting/ISystemSetting.h
new file mode 100755 (executable)
index 0000000..c1b9127
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_ISYSTEMSETTING_H_
+#define WRTPLUGINS_API_ISYSTEMSETTING_H_
+
+#include <memory>
+#include <Commons/ThreadPool.h>
+#include "EventSetWallpaper.h"
+#include "EventSetRingtone.h"
+#include "EventSetSetting.h"
+#include "EventGetSetting.h"
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+class EventSetWallpaper;
+class EventSetRingtone;
+class EventSetSetting;
+class EventGetSetting;
+
+typedef std::shared_ptr<EventSetWallpaper> EventSetWallpaperPtr;
+typedef std::shared_ptr<EventSetRingtone> EventSetRingtonePtr;
+typedef std::shared_ptr<EventSetSetting> EventSetSettingPtr;
+typedef std::shared_ptr<EventGetSetting> EventGetSettingPtr;
+
+class ISystemSetting :
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventSetWallpaper>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventSetRingtone>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventSetSetting>,
+    public WrtDeviceApis::Commons::EventRequestReceiver<EventGetSetting>
+{
+public:
+    virtual ~ISystemSetting();
+    ISystemSetting();
+
+    virtual void setWallpaper(const EventSetWallpaperPtr &event) = 0;
+    virtual void setRingtone(const EventSetRingtonePtr &event) = 0;
+    virtual void setProperty(const EventSetSettingPtr &event) = 0;
+    virtual void getProperty(const EventGetSettingPtr &event) = 0;
+    virtual std::string getProperty(const SettingType settingType) = 0;
+
+protected:
+    virtual void OnRequestReceived(const EventSetWallpaperPtr &event) = 0;
+    virtual void OnRequestReceived(const EventSetRingtonePtr &event) = 0;
+    virtual void OnRequestReceived(const EventSetSettingPtr &event) = 0;
+    virtual void OnRequestReceived(const EventGetSettingPtr &event) = 0;
+
+};
+
+typedef std::shared_ptr<ISystemSetting> ISystemSettingPtr;
+
+}
+}
+
+#endif
diff --git a/src/SystemSetting/ISystemSettingType.h b/src/SystemSetting/ISystemSettingType.h
new file mode 100755 (executable)
index 0000000..e3dea40
--- /dev/null
@@ -0,0 +1,40 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef ISYSTEMSETTINGTYPES_H
+#define ISYSTEMSETTINGTYPES_H
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+//#define NAME_SMS_TYPE "SMS"
+#define NAME_HOME_SCREEN_TYPE "HOME_SCREEN"
+#define NAME_LOCK_SCREEN_TYPE "LOCK_SCREEN"
+#define NAME_INCOMMING_CALL_TYPE "INCOMING_CALL"
+#define NAME_INCOMMING_EMAIL_TYPE "NOTIFICATION_EMAIL"
+
+enum SettingType
+{
+    HOME_SCREEN = 0,
+    LOCK_SCREEN,
+    INCOMMING_CALL,
+    NOTIFICATION_EMAIL
+};
+
+}
+}
+#endif
diff --git a/src/SystemSetting/JSSystemSetting.cpp b/src/SystemSetting/JSSystemSetting.cpp
new file mode 100755 (executable)
index 0000000..81fac3e
--- /dev/null
@@ -0,0 +1,335 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <CommonsJavaScript/JSUtils.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <CommonsJavaScript/Converter.h>
+#include "SystemSettingFactory.h"
+#include "ISystemSetting.h"
+#include "EventSetWallpaper.h"
+#include "EventSetRingtone.h"
+#include "EventSetSetting.h"
+#include "EventGetSetting.h"
+#include "SystemSettingFactory.h"
+
+#include <JSWebAPIErrorFactory.h>
+#include <TimeTracer.h>
+#include "JSSystemSetting.h"
+#include "SystemSettingResponseDispatcher.h"
+
+#include "ConverterSystemSetting.h"
+#include "SystemSettingAsyncCallbackManager.h"
+
+//#include <JSFile.h>
+//#include <EventGetNodeData.h>
+#include <FilesystemUtils.h>
+#include "plugin_config_impl.h"
+#include <Logger.h>
+
+using namespace std;
+
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+using WrtDeviceApis::Commons::UnknownException;
+
+JSClassDefinition JSSystemSetting::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    "systemsetting",
+    NULL,
+    NULL,
+    m_function,
+    initialize,
+    finalize,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL
+};
+
+JSStaticFunction JSSystemSetting::m_function[] = {
+//    { "setWallpaper", JSSystemSetting::setWallpaper, kJSPropertyAttributeNone },
+//    { "setRingtone", JSSystemSetting::setRingtone, kJSPropertyAttributeNone },
+    { "setProperty", JSSystemSetting::setProperty, kJSPropertyAttributeNone },
+    { "getProperty", JSSystemSetting::getProperty, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+const JSClassRef JSSystemSetting::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSSystemSetting::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemSetting::m_jsClassRef = JSClassCreate(JSSystemSetting::getClassInfo());
+
+void JSSystemSetting::initialize(JSContextRef context, JSObjectRef object)
+{
+    JSSystemSettingPriv* priv = static_cast<JSSystemSettingPriv*>(JSObjectGetPrivate(object));
+    ISystemSettingPtr SystemSettings(SystemSettingFactory::getInstance().getSystemSetting());
+
+    if (priv != NULL)
+    {
+        LOGD("JSSystemSetting::initialized already");
+        return;
+    }
+
+    Try {
+        priv = new JSSystemSettingPriv(context, SystemSettings);
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            LOGE("Object can't store private data.");
+            delete priv;
+        }
+    } Catch (UnsupportedException) {
+        LOGE("UnsupportedException: %s", _rethrown_exception.GetMessage().c_str());
+    } Catch (UnknownException) {
+        LOGE("UnknownExceptionException: %s", _rethrown_exception.GetMessage().c_str());
+    } Catch (PlatformException) {
+        LOGE("PlatformExceptionException: %s", _rethrown_exception.GetMessage().c_str());
+    } Catch (WrtDeviceApis::Commons::Exception) {
+        LOGE("Exception: %s", _rethrown_exception.GetMessage().c_str());
+    }
+
+    LOGD("JSSystemSetting::initialize");
+}
+
+void JSSystemSetting::finalize(JSObjectRef object)
+{
+    LOGD("enter");
+    JSSystemSettingPriv* priv = static_cast<JSSystemSettingPriv*>(JSObjectGetPrivate(object));
+
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+}
+
+JSValueRef JSSystemSetting::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+
+    SettingType settingType;
+    std::string settingValue;
+
+    JSSystemSettingPriv *priv = static_cast<JSSystemSettingPriv*>(JSObjectGetPrivate(thisObject));
+    ConverterSystemSettingFactory::ConverterType converter =
+            ConverterSystemSettingFactory::getConverter(context);
+    Validator check(context, exception);
+
+    if (!priv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Wrong Object");
+    }
+    if (argumentCount < 3) {
+        LOGD("Incorrect number of arguments");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
+    }
+    if (!check.isCallback(arguments[2])) {
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
+    }
+
+    TIZEN_CHECK_ACCESS(context, exception, priv, SYSTEMSETTING_FUNCTION_API_SET_PROPERTY);
+
+    JSValueRef onSuccessForCbm = NULL, onErrorForCbm = NULL;
+    onSuccessForCbm = arguments[2];
+    if (argumentCount > 3) {
+        if (check.isCallback(arguments[3])) {
+            onErrorForCbm = arguments[3];
+        } else if (!JSValueIsNull(context, arguments[3])) {
+            return JSWebAPIErrorFactory::postException(context, exception,
+                        JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
+        }
+    }
+
+    JSCallbackManagerPtr callbackManager(JSCallbackManager::createObject(priv->getContext(),
+            onSuccessForCbm, onErrorForCbm, true, true));
+    callbackManager->setObject(thisObject);
+
+    std::string strSettingType;
+    Try {
+        strSettingType = converter->toString(arguments[0]);
+        TIME_TRACER_ITEM_BEGIN(strSettingType.c_str(), 0);
+
+        settingType = converter->toSettingType(arguments[0]);
+        settingValue = converter->toString(arguments[1]);
+        LOGD("settingValue = %s", settingValue.c_str());
+
+        ISystemSettingPtr SystemSettings(priv->getObject());
+        EventSetSettingPtr dplEvent(new EventSetSetting());
+        dplEvent->setSettingType(settingType);
+        dplEvent->setSettingValue(settingValue);
+        dplEvent->setPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        dplEvent->setForAsynchronousCall(&SystemSettingResponseDispatcher::getInstance());
+
+        SystemSettings->setProperty(dplEvent);
+        SystemSettingAsyncCallbackManagerSingleton::Instance().registerCallbackManager(
+                callbackManager, priv->getContext());
+    }
+
+    Catch(WrtDeviceApis::Commons::ConversionException) {
+        LOGD("Exception");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
+    }
+
+    Catch(WrtDeviceApis::Commons::InvalidArgumentException) {
+        LOGD("Exception");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "invalid value error");
+    }
+
+    Catch(WrtDeviceApis::Commons::PlatformException) {
+        LOGD("Exception");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform error");
+    }
+
+    Catch(WrtDeviceApis::Commons::Exception) {
+        LOGD("Exception");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    LOGD("end");
+    TIME_TRACER_ITEM_END(strSettingType.c_str(), 0);
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemSetting::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("enter");
+    JSSystemSettingPriv *priv = static_cast<JSSystemSettingPriv*>(JSObjectGetPrivate(thisObject));
+
+    ConverterSystemSettingFactory::ConverterType converter =
+            ConverterSystemSettingFactory::getConverter(context);
+
+    Validator check(context, exception);
+
+    if (!priv) {
+        LOGE("private object is null");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Wrong Object");
+    }
+
+    if (argumentCount < 2) {
+        LOGD("Incorrect number of arguments");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
+    }
+    if (!check.isCallback(arguments[1])) {
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
+    }
+
+/*
+    AceSecurityStatus status = SYSTEMSETTING_CHECK_ACCESS(SYSTEMSETTING_FUNCTION_API_GET_PROPERTY);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+*/
+
+    JSValueRef onSuccessForCbm = NULL, onErrorForCbm = NULL;
+    onSuccessForCbm = arguments[1];
+    if (argumentCount > 2) {
+        if (check.isCallback(arguments[2])) {
+            onErrorForCbm = arguments[2];
+        } else if (!JSValueIsNull(context, arguments[2])) {
+            return JSWebAPIErrorFactory::postException(context, exception,
+                        JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
+        }
+    }
+
+    JSCallbackManagerPtr callbackManager(JSCallbackManager::createObject(priv->getContext(),
+            onSuccessForCbm, onErrorForCbm, true, true));
+    callbackManager->setObject(thisObject);
+
+    std::string strGettingType;
+    Try {
+        strGettingType = converter->toString(arguments[0]);
+        TIME_TRACER_ITEM_BEGIN(strGettingType.c_str(), 0);
+        SettingType settingType = converter->toSettingType(arguments[0]);
+
+        ISystemSettingPtr SystemSettings(priv->getObject());
+        EventGetSettingPtr dplEvent(new EventGetSetting());
+        dplEvent->setSettingType(settingType);
+        dplEvent->setPrivateData(std::static_pointer_cast<IEventPrivateData>(callbackManager));
+        dplEvent->setForAsynchronousCall(&SystemSettingResponseDispatcher::getInstance());
+
+        SystemSettings->getProperty(dplEvent);
+        SystemSettingAsyncCallbackManagerSingleton::Instance().registerCallbackManager(
+                callbackManager, priv->getContext());
+    }
+
+    Catch(WrtDeviceApis::Commons::ConversionException) {
+        LOGD("Exception");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Type mismatch error");
+    }
+
+    Catch(WrtDeviceApis::Commons::InvalidArgumentException) {
+        LOGD("Exception");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "invalid value error");
+    }
+
+    Catch(WrtDeviceApis::Commons::PlatformException) {
+        LOGD("Exception");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "platform error");
+    }
+
+    Catch(WrtDeviceApis::Commons::Exception) {
+        LOGD("Exception");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+    }
+
+    LOGD("end");
+    TIME_TRACER_ITEM_BEGIN(strGettingType.c_str(), 0);
+    return JSValueMakeUndefined(context);
+}
+
+}
+}
diff --git a/src/SystemSetting/JSSystemSetting.h b/src/SystemSetting/JSSystemSetting.h
new file mode 100755 (executable)
index 0000000..38ba15b
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_TIZEN1_0_JS_SYSTEMSETTING_H_
+#define WRTPLUGINS_TIZEN1_0_JS_SYSTEMSETTING_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <Security.h>
+#include "ISystemSetting.h"
+
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+typedef PrivateObject<ISystemSettingPtr, NoOwnership> JSSystemSettingPrivObject;
+
+class JSSystemSettingPriv :
+    public JSSystemSettingPrivObject,
+    public DeviceAPI::Common::SecurityAccessor
+{
+public:
+    JSSystemSettingPriv(JSContextRef context, ISystemSettingPtr systemSetting) :
+        JSSystemSettingPrivObject(context, systemSetting),
+        DeviceAPI::Common::SecurityAccessor()
+    {
+    }
+
+    virtual ~JSSystemSettingPriv()
+    {
+    }
+};
+
+class JSSystemSetting
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+private:
+    static void initialize(JSContextRef context, JSObjectRef object);
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef setProperty(JSContextRef context, JSObjectRef object, JSObjectRef thisObject,
+            size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+    static JSValueRef getProperty(JSContextRef context, JSObjectRef object, JSObjectRef thisObject,
+            size_t argumentCount, const JSValueRef arguments[], JSValueRef* exception);
+
+    static JSClassDefinition m_classInfo;
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+}
+}
+
+#endif
diff --git a/src/SystemSetting/SystemSetting.cpp b/src/SystemSetting/SystemSetting.cpp
new file mode 100755 (executable)
index 0000000..b2781a4
--- /dev/null
@@ -0,0 +1,304 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/Exception.h>
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "SystemSetting.h"
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <system_settings.h>
+
+using namespace WrtDeviceApis::CommonsJavaScript;
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+namespace {
+static const std::string ERR_SYSTEM_SETTINGS_INVALID_PARAMETER = "Invalid parameter";
+static const std::string ERR_SYSTEM_SETTINGS_OUT_OF_MEMORY = "Out of memory";
+static const std::string ERR_SYSTEM_SETTINGS_IO_ERROR = "Internal I/O error";
+static const std::string ERR_SYSTEM_SETTINGS_PERMISSION_DENIED = "Permission denied";
+static const std::string ERR_SYSTEM_SETTINGS_UNKNOWN = "Unknown error";
+}
+
+const std::string& getSystemSettingsErrorMessage(int errorCode)
+{
+    switch (errorCode) {
+        case SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER:
+            return ERR_SYSTEM_SETTINGS_INVALID_PARAMETER;
+        case SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY:
+            return ERR_SYSTEM_SETTINGS_OUT_OF_MEMORY;
+        case SYSTEM_SETTINGS_ERROR_IO_ERROR:
+            return ERR_SYSTEM_SETTINGS_IO_ERROR;
+        case SYSTEM_SETTINGS_ERROR_PERMISSION_DENIED:
+            return ERR_SYSTEM_SETTINGS_PERMISSION_DENIED;
+        default:
+            return ERR_SYSTEM_SETTINGS_UNKNOWN;
+    }
+}
+
+std::string SystemSetting::getSystemSettingsLogMessage(const int errorCode, const std::string &hint)
+{
+    std::stringstream ss;
+    ss << "Failed " << hint << " : " << getSystemSettingsErrorMessage(errorCode) << ", " << errorCode;
+    return ss.str();
+}
+
+SystemSetting::SystemSetting()
+{
+}
+
+SystemSetting::~SystemSetting()
+{
+}
+
+void SystemSetting::setWallpaper(const EventSetWallpaperPtr &event)
+{
+    LOGD("enter");
+    EventRequestReceiver<EventSetWallpaper>::PostRequest(event);
+}
+
+void SystemSetting::setRingtone(const EventSetRingtonePtr &event)
+{
+    LOGD("enter");
+    EventRequestReceiver<EventSetRingtone>::PostRequest(event);
+}
+
+void SystemSetting::setProperty(const EventSetSettingPtr &event)
+{
+    LOGD("enter");
+    EventRequestReceiver<EventSetSetting>::PostRequest(event);
+}
+
+void SystemSetting::getProperty(const EventGetSettingPtr &event)
+{
+    LOGD("enter");
+    EventRequestReceiver<EventGetSetting>::PostRequest(event);
+}
+
+std::string SystemSetting::getProperty(const SettingType settingType)
+{
+    LOGD("enter");
+    int ret = SYSTEM_SETTINGS_ERROR_NONE;
+
+    char *value = NULL;
+    std::string gettingValue;
+
+    if (settingType == HOME_SCREEN)
+    {
+        LOGD("home screen");
+        ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, &value);
+        LOGD("result : %d value: %s", ret, value);
+    }
+    else if (settingType == LOCK_SCREEN)
+    {
+        LOGD("lock screen");
+        ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_LOCK_SCREEN, &value);
+        LOGD("result : %d value: %s", ret, value);
+    }else if (settingType == INCOMMING_CALL)
+    {
+        LOGD("call");
+        ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, &value);
+        LOGD("result : %d value: %s", ret, value);
+    }
+    else if (settingType == NOTIFICATION_EMAIL)
+    {
+        LOGD("email");
+        ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_EMAIL_ALERT_RINGTONE, &value);
+        LOGD("result : %d value: %s", ret, value);
+    }
+
+    if (ret == SYSTEM_SETTINGS_ERROR_NONE)
+    {
+        LOGD("success");
+        gettingValue = value;
+        return value;
+    }
+    else
+    {
+        LOGE("err : %d", ret);
+        throwSystemSettingsException(ret, "system_settings_get_value_string()");
+    }
+}
+
+void SystemSetting::OnRequestReceived(const EventSetWallpaperPtr &event)
+{
+    LOGD("enter");
+    int ret = SYSTEM_SETTINGS_ERROR_NONE;
+
+    std::string wallpaperUri = event->getWallpaperURI();
+    std::string wallpaperType = event->getWallpaperType();
+
+    if (strcmp(wallpaperType.c_str(), "HOME_SCREEN") == 0)
+    {
+        LOGD("home screen : %s", wallpaperUri.c_str());
+        ret = system_settings_set_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, wallpaperUri.c_str());
+    }
+    else if (strcmp(wallpaperType.c_str(), "LOCK_SCREEN") == 0)
+    {
+        LOGD("lock screen : %s", wallpaperUri.c_str());
+        ret = system_settings_set_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_LOCK_SCREEN, wallpaperUri.c_str());
+    }
+
+    if (ret == SYSTEM_SETTINGS_ERROR_NONE)
+    {
+        LOGD("success");
+        event->setExceptionCode(ExceptionCodes::None);
+    }
+    else
+    {
+        LOGW("%s", getSystemSettingsLogMessage(ret, "system_settings_set_value_string()").c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+    LOGD("end");
+}
+
+void SystemSetting::OnRequestReceived(const EventSetRingtonePtr &event)
+{
+    LOGD("enter");
+    int ret = SYSTEM_SETTINGS_ERROR_NONE;
+
+    std::string ringtoneUri = event->getRingtoneURI();
+    std::string ringtoneType = event->getRingtoneType();
+
+    if (strcmp(ringtoneType.c_str(), "INCOMING_CALL") == 0)
+    {
+        LOGD("call  : %s", ringtoneUri.c_str());
+        ret = system_settings_set_value_string(SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, ringtoneUri.c_str());
+    }
+    else if (strcmp(ringtoneType.c_str(), "NOTIFICATION_EMAIL") == 0)
+    {
+        // TODO need manage-api
+        LOGD("email  : %s", ringtoneUri.c_str());
+        ret = system_settings_set_value_string(SYSTEM_SETTINGS_KEY_EMAIL_ALERT_RINGTONE, ringtoneUri.c_str());
+    }
+
+    if (ret == SYSTEM_SETTINGS_ERROR_NONE)
+    {
+        LOGD("success");
+        event->setExceptionCode(ExceptionCodes::None);
+    }
+    else
+    {
+        LOGW("%s", getSystemSettingsLogMessage(ret, "system_settings_set_value_string()").c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+    LOGD("end");
+}
+
+void SystemSetting::OnRequestReceived(const EventSetSettingPtr &event)
+{
+    LOGD("enter");
+    int ret = SYSTEM_SETTINGS_ERROR_NONE;
+
+    std::string settingValue = event->getSettingValue();
+    SettingType settingType = event->getSettingType();
+
+    if (settingType == HOME_SCREEN)
+    {
+        LOGD("home screen : %s", settingValue.c_str());
+        ret = system_settings_set_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, settingValue.c_str());
+        LOGD("result : %d", ret);
+    }
+    else if (settingType == LOCK_SCREEN)
+    {
+        LOGD("lock screen : %s", settingValue.c_str());
+        ret = system_settings_set_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_LOCK_SCREEN, settingValue.c_str());
+        LOGD("result : %d", ret);
+    }else if (settingType == INCOMMING_CALL)
+    {
+        LOGD("call  : %s", settingValue.c_str());
+        ret = system_settings_set_value_string(SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, settingValue.c_str());
+        LOGD("result : %d", ret);
+    }
+    else if (settingType == NOTIFICATION_EMAIL)
+    {
+        LOGD("email  : %s", settingValue.c_str());
+        ret = system_settings_set_value_string(SYSTEM_SETTINGS_KEY_EMAIL_ALERT_RINGTONE, settingValue.c_str());
+        LOGD("result : %d", ret);
+    }
+
+    if (ret == SYSTEM_SETTINGS_ERROR_NONE)
+    {
+        LOGD("success");
+        event->setExceptionCode(ExceptionCodes::None);
+    }
+    else
+    {
+        LOGW("%s", getSystemSettingsLogMessage(ret, "system_settings_set_value_string()").c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+    LOGD("end");
+}
+
+void SystemSetting::OnRequestReceived(const EventGetSettingPtr &event)
+{
+    LOGD("enter");
+    int ret = SYSTEM_SETTINGS_ERROR_NONE;
+
+    std::string settingValue;
+    SettingType settingType = event->getSettingType();
+    char *value = NULL;
+
+    if (settingType == HOME_SCREEN)
+    {
+        LOGD("home screen");
+        ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_HOME_SCREEN, &value);
+        LOGD("result : %d", ret);
+    }
+    else if (settingType == LOCK_SCREEN)
+    {
+        LOGD("lock screen");
+        ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_WALLPAPER_LOCK_SCREEN, &value);
+        LOGD("result : %d", ret);
+    }else if (settingType == INCOMMING_CALL)
+    {
+        LOGD("call");
+        ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_INCOMING_CALL_RINGTONE, &value);
+        LOGD("result : %d", ret);
+    }
+    else if (settingType == NOTIFICATION_EMAIL)
+    {
+        LOGD("email");
+        ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_EMAIL_ALERT_RINGTONE, &value);
+        LOGD("result : %d", ret);
+    }
+
+    if (ret == SYSTEM_SETTINGS_ERROR_NONE)
+    {
+        LOGD("success");
+        event->setExceptionCode(ExceptionCodes::None);
+        settingValue = value;
+        event->setSettingValue(settingValue);
+    }
+    else
+    {
+        LOGW("%s", getSystemSettingsLogMessage(ret, "system_settings_get_value_string()").c_str());
+        event->setExceptionCode(ExceptionCodes::PlatformException);
+    }
+
+    if (value) {
+        free(value);
+    }
+    LOGD("end");
+}
+
+}
+}
diff --git a/src/SystemSetting/SystemSetting.h b/src/SystemSetting/SystemSetting.h
new file mode 100755 (executable)
index 0000000..44b3155
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_PLATFORM_SYSTEMSETTING_H_
+#define WRTPLUGINS_PLATFORM_SYSTEMSETTING_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <string>
+#include <memory>
+#include <dpl/noncopyable.h>
+#include "SystemSettingFactory.h"
+#include "ISystemSetting.h"
+#include "EventSetWallpaper.h"
+#include "EventSetRingtone.h"
+#include "EventSetSetting.h"
+#include "EventGetSetting.h"
+#include <CommonsJavaScript/Converter.h>
+
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+class SystemSetting : public ISystemSetting
+{
+    friend class SystemSettingFactory;
+    friend class EventSetWallpaper;
+    friend class EventSetRingtone;
+    friend class EventSetSetting;
+    friend class EventGetSetting;
+
+public:
+    SystemSetting();
+    virtual ~SystemSetting();
+    virtual void setWallpaper(const EventSetWallpaperPtr &event);
+    virtual void setRingtone(const EventSetRingtonePtr &event);
+    virtual void setProperty(const EventSetSettingPtr &event);
+    virtual void getProperty(const EventGetSettingPtr &event);
+    virtual std::string getProperty(const SettingType settingType);
+
+protected:
+    virtual void OnRequestReceived(const EventSetWallpaperPtr &event);
+    virtual void OnRequestReceived(const EventSetRingtonePtr &event);
+    virtual void OnRequestReceived(const EventSetSettingPtr &event);
+    virtual void OnRequestReceived(const EventGetSettingPtr &event);
+
+private:
+    std::string getSystemSettingsLogMessage(const int errorCode, const std::string &hint);
+
+    template <class T = WrtDeviceApis::Commons::PlatformException>
+    void throwSystemSettingsException(const int errorCode, const std::string &hint)
+    {
+        std::string log = getSystemSettingsLogMessage(errorCode, hint);
+        LOGE("%s", log.c_str());
+        ThrowMsg (T, log);
+    }
+
+    std::string m_domainName;
+};
+
+}
+}
+#endif
diff --git a/src/SystemSetting/SystemSettingAsyncCallbackManager.cpp b/src/SystemSetting/SystemSettingAsyncCallbackManager.cpp
new file mode 100755 (executable)
index 0000000..048fcd8
--- /dev/null
@@ -0,0 +1,33 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        SystemSettingAsyncCallbackManager.cpp
+ * @version     0.1
+ * @brief
+ */
+
+#include "SystemSettingAsyncCallbackManager.h"
+#include <dpl/singleton_impl.h>
+
+IMPLEMENT_SINGLETON(DeviceAPI::SystemSetting::SystemSettingAsyncCallbackManager)
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+} // Tizen1_0
+} // TizenApis
diff --git a/src/SystemSetting/SystemSettingAsyncCallbackManager.h b/src/SystemSetting/SystemSettingAsyncCallbackManager.h
new file mode 100755 (executable)
index 0000000..792c40b
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        SystemSettingAsyncCallbackManager.h
+ * @version     0.1
+ * @brief
+ */
+
+#ifndef _TIZEN_SYSTEMSETTING_ASYNC_CALLBACK_MANAGER_H_
+#define _TIZEN_SYSTEMSETTING_ASYNC_CALLBACK_MANAGER_H_
+
+#include <dpl/singleton.h>
+#include <AsyncCallbackManager.h>
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+class SystemSettingAsyncCallbackManager : public DeviceAPI::Common::AsyncCallbackManager
+{
+public:
+    SystemSettingAsyncCallbackManager()
+    {
+    }
+
+    virtual ~SystemSettingAsyncCallbackManager()
+    {
+    }
+
+    friend class DPL::Singleton<SystemSettingAsyncCallbackManager>;
+};
+
+typedef DPL::Singleton<SystemSettingAsyncCallbackManager> SystemSettingAsyncCallbackManagerSingleton;
+
+} // Tizen1_0
+} // TizenApis
+
+#endif
diff --git a/src/SystemSetting/SystemSettingFactory.cpp b/src/SystemSetting/SystemSettingFactory.cpp
new file mode 100755 (executable)
index 0000000..9670305
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SystemSetting.h"
+#include "SystemSettingFactory.h"
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+ISystemSettingPtr SystemSettingFactory::getSystemSetting()
+{
+    static ISystemSettingPtr result(new SystemSetting());
+    return result;
+}
+
+SystemSettingFactory& SystemSettingFactory::getInstance()
+{
+    static SystemSettingFactory theInstance;
+    return theInstance;
+}
+
+SystemSettingFactory::SystemSettingFactory()
+{
+}
+
+}
+}
diff --git a/src/SystemSetting/SystemSettingFactory.h b/src/SystemSetting/SystemSettingFactory.h
new file mode 100755 (executable)
index 0000000..4d9b7b3
--- /dev/null
@@ -0,0 +1,41 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef WRTPLUGINS_API_SYSTEMSETTING_FACTORY_H_
+#define WRTPLUGINS_API_SYSTEMSETTING_FACTORY_H_
+
+#include <dpl/noncopyable.h>
+#include "ISystemSetting.h"
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+class SystemSettingFactory : DPL::Noncopyable
+{
+public:
+    ISystemSettingPtr getSystemSetting();
+    static SystemSettingFactory& getInstance();
+
+protected:
+    SystemSettingFactory();
+};
+
+}
+}
+
+#endif
+
diff --git a/src/SystemSetting/SystemSettingResponseDispatcher.cpp b/src/SystemSetting/SystemSettingResponseDispatcher.cpp
new file mode 100755 (executable)
index 0000000..8f12de2
--- /dev/null
@@ -0,0 +1,265 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SystemSettingResponseDispatcher.h"
+#include <CommonsJavaScript/JSCallbackManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <FilesystemUtils.h>
+#include "SystemSettingAsyncCallbackManager.h"
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+SystemSettingResponseDispatcher& SystemSettingResponseDispatcher::getInstance()
+{
+    static SystemSettingResponseDispatcher instance;
+    return instance;
+}
+
+SystemSettingResponseDispatcher::SystemSettingResponseDispatcher() :
+    SystemSettingSetWallpaperEventAnswerReceiverRequest(ThreadEnum::NULL_THREAD),
+    SystemSettingSetRingtoneEventAnswerReceiverRequest(ThreadEnum::NULL_THREAD),
+    SystemSettingSetSettingEventAnswerReceiverRequest(ThreadEnum::NULL_THREAD),
+    SystemSettingGetSettingEventAnswerReceiverRequest(ThreadEnum::NULL_THREAD)
+{
+}
+
+SystemSettingResponseDispatcher::~SystemSettingResponseDispatcher()
+{
+}
+
+void SystemSettingResponseDispatcher::OnAnswerReceived(const EventSetWallpaperPtr &event)
+{
+    LOGD("entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager>(event->getPrivateData());
+
+    if (!callbackManager) {
+        LOGE("No listener callback!");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+    JSValueRef error = NULL;
+
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+            break;
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::NOT_FOUND_ERROR, "record not found");
+            break;
+        case ExceptionCodes::InvalidArgumentException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "DomainName is not set");
+            break;
+        case ExceptionCodes::ConversionException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong argument");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+            break;
+        }
+        LOGD("callOnError");
+        callbackManager->callOnError(error);
+        return;
+    }
+    LOGD("callOnSuccess");
+    callbackManager->callOnSuccess();
+}
+
+void SystemSettingResponseDispatcher::OnAnswerReceived(const EventSetRingtonePtr &event)
+{
+    LOGD("entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager >(event->getPrivateData());
+
+    if (!callbackManager) {
+        LOGE("No listener callback!");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+    JSValueRef error = NULL;
+
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+            break;
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::NOT_FOUND_ERROR, "record not found");
+            break;
+        case ExceptionCodes::InvalidArgumentException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "DomainName is not set");
+            break;
+        case ExceptionCodes::ConversionException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong argument");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        return;
+    }
+    callbackManager->callOnSuccess();
+}
+
+void SystemSettingResponseDispatcher::OnAnswerReceived(const EventSetSettingPtr &event)
+{
+    LOGD("entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager >(event->getPrivateData());
+
+    if (!callbackManager) {
+        LOGE("No listener callback!");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+    JSValueRef error = NULL;
+
+    SystemSettingAsyncCallbackManagerSingleton::Instance().unregisterCallbackManager(callbackManager);
+    if (callbackManager->getOnSuccess() == NULL && callbackManager->getOnError() == NULL)
+    {
+        LOGD("Callback was not registered or context has been already expired.");
+        return;
+    }
+
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+            break;
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::NOT_FOUND_ERROR, "record not found");
+            break;
+        case ExceptionCodes::InvalidArgumentException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "DomainName is not set");
+            break;
+        case ExceptionCodes::ConversionException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong argument");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        return;
+    }
+    callbackManager->callOnSuccess();
+}
+
+void SystemSettingResponseDispatcher::OnAnswerReceived(const EventGetSettingPtr &event)
+{
+    LOGD("entered");
+    JSCallbackManagerPtr callbackManager =
+            std::static_pointer_cast<JSCallbackManager >(event->getPrivateData());
+
+    if (!callbackManager) {
+        LOGE("No listener callback!");
+        return;
+    }
+
+    JSContextRef gContext = callbackManager->getContext();
+    JSValueRef error = NULL;
+
+    SystemSettingAsyncCallbackManagerSingleton::Instance().unregisterCallbackManager(callbackManager);
+    if (callbackManager->getOnSuccess() == NULL && callbackManager->getOnError() == NULL)
+    {
+        LOGD("Callback was not registered or context has been already expired.");
+        return;
+    }
+
+    Converter converter(gContext);
+
+    if (ExceptionCodes::None != event->getExceptionCode())
+    {
+        switch (event->getExceptionCode())
+        {
+        case ExceptionCodes::PlatformException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "Internal error");
+            break;
+        case ExceptionCodes::NotFoundException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::NOT_FOUND_ERROR, "record not found");
+            break;
+        case ExceptionCodes::InvalidArgumentException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::INVALID_VALUES_ERROR, "DomainName is not set");
+            break;
+        case ExceptionCodes::ConversionException:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::TYPE_MISMATCH_ERROR, "Wrong argument");
+            break;
+        default:
+            error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                        JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+            break;
+        }
+
+        callbackManager->callOnError(error);
+        return;
+    }
+    LOGD("gettingValue : %s", event->getSettingValue().c_str());
+
+    std::string settingPath = event->getSettingValue();
+    LOGD("RealSettingPath : %s", settingPath.c_str());
+
+    if (settingPath.size() == 0)
+    {
+        error = JSWebAPIErrorFactory::makeErrorObject(gContext,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "Unknown error");
+        callbackManager->callOnError(error);
+        return;
+    }
+
+    callbackManager->callOnSuccess(converter.toJSValueRef(settingPath));
+}
+
+}
+}
diff --git a/src/SystemSetting/SystemSettingResponseDispatcher.h b/src/SystemSetting/SystemSettingResponseDispatcher.h
new file mode 100755 (executable)
index 0000000..6687e40
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _SYSTEMSETTING_RESPONSE_DISPATCHER_H_
+#define _SYSTEMSETTING_RESPONSE_DISPATCHER_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include <Commons/EventReceiver.h>
+#include <Commons/EventListener.h>
+#include "EventSetWallpaper.h"
+#include "EventSetRingtone.h"
+#include "EventSetSetting.h"
+#include "EventGetSetting.h"
+
+#include <CommonsJavaScript/Converter.h>
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<SystemSetting::EventSetWallpaper>
+SystemSettingSetWallpaperEventAnswerReceiverRequest;
+
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<SystemSetting::EventSetRingtone>
+SystemSettingSetRingtoneEventAnswerReceiverRequest;
+
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<SystemSetting::EventSetSetting>
+SystemSettingSetSettingEventAnswerReceiverRequest;
+
+typedef WrtDeviceApis::Commons::EventAnswerReceiver<SystemSetting::EventGetSetting>
+SystemSettingGetSettingEventAnswerReceiverRequest;
+
+class SystemSettingResponseDispatcher :
+    public SystemSettingSetWallpaperEventAnswerReceiverRequest,
+    public SystemSettingSetRingtoneEventAnswerReceiverRequest,
+    public SystemSettingSetSettingEventAnswerReceiverRequest,
+    public SystemSettingGetSettingEventAnswerReceiverRequest
+{
+public:
+    static SystemSettingResponseDispatcher& getInstance();
+
+private:
+    SystemSettingResponseDispatcher();
+    virtual ~SystemSettingResponseDispatcher();
+
+protected:
+    void OnAnswerReceived(const SystemSetting::EventSetWallpaperPtr &event);
+    void OnAnswerReceived(const SystemSetting::EventSetRingtonePtr &event);
+    void OnAnswerReceived(const SystemSetting::EventSetSettingPtr &event);
+    void OnAnswerReceived(const SystemSetting::EventGetSettingPtr &event);
+
+};
+
+}
+}
+
+#endif
diff --git a/src/SystemSetting/config.xml b/src/SystemSetting/config.xml
new file mode 100755 (executable)
index 0000000..4d57a81
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-systemsetting.so</library-name>
+    <feature-install-uri>systemsetting.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/setting</name>
+        <device-capability>setting</device-capability>
+    </api-feature>
+</plugin-properties>
+
diff --git a/src/SystemSetting/plugin_config.cpp b/src/SystemSetting/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..377a7da
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <map>
+#include <utility>
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include "plugin_config.h"
+#include "plugin_config_impl.h"
+
+#define SYSTEMSETTING_FEATURE_API "http://tizen.org/privilege/setting"
+//#define SYSTEMSETTING_FEATURE_API_READ "http://tizen.org/privilege/setting.read"
+//#define SYSTEMSETTING_FEATURE_API_WRITE "http://tizen.org/privilege/setting.write"
+
+#define SYSTEMSETTING_DEVICE_CAP "setting"
+//#define SYSTEMSETTING_DEVICE_CAP_READ "setting"
+//#define SYSTEMSETTING_DEVICE_CAP_WRITE "setting"
+
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+static WrtDeviceApis::Commons::FunctionMapping createSystemSettingFunctions();
+
+static WrtDeviceApis::Commons::FunctionMapping SystemSettingFunctions =
+    createSystemSettingFunctions();
+
+DEFINE_FUNCTION_GETTER(SystemSetting, SystemSettingFunctions);
+
+static WrtDeviceApis::Commons::FunctionMapping createSystemSettingFunctions()
+{
+    using namespace WrtDeviceApis::Commons;
+
+    /**
+     * Device capabilities
+     */
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_SYSTEMSETTING, SYSTEMSETTING_DEVICE_CAP);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_SYSTEMSETTING);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_SYSTEMSETTING, DEVICE_CAP_SYSTEMSETTING);
+
+    /**
+     * Api Features
+     */
+
+    ACE_CREATE_FEATURE(FEATURE_SYSTEMSETTING, SYSTEMSETTING_FEATURE_API);
+
+    ACE_CREATE_FEATURE_LIST(SYSTEMSETTING_FEATURES_SYSTEMSETTING);
+    ACE_ADD_API_FEATURE(SYSTEMSETTING_FEATURES_SYSTEMSETTING, FEATURE_SYSTEMSETTING);
+
+    /**
+    * Functions
+    */
+
+    FunctionMapping SystemSettingFunctions;
+
+    /**  Read  **/
+    AceFunction getPropertyFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_GET_PROPERTY,
+            SYSTEMSETTING_FUNCTION_API_GET_PROPERTY,
+            SYSTEMSETTING_FEATURES_SYSTEMSETTING,
+            DEVICE_LIST_SYSTEMSETTING);
+
+    SystemSettingFunctions.insert( std::make_pair(
+            SYSTEMSETTING_FUNCTION_API_GET_PROPERTY,
+            getPropertyFunc));
+
+    /**  Write  **/
+    AceFunction setPropertyFunc = ACE_CREATE_FUNCTION(
+            FUNCTION_SET_PROPERTY,
+            SYSTEMSETTING_FUNCTION_API_SET_PROPERTY,
+            SYSTEMSETTING_FEATURES_SYSTEMSETTING,
+            DEVICE_LIST_SYSTEMSETTING);
+
+    SystemSettingFunctions.insert( std::make_pair(
+            SYSTEMSETTING_FUNCTION_API_SET_PROPERTY,
+            setPropertyFunc));
+
+    return SystemSettingFunctions;
+}
+}
+}
+
+#undef SYSTEMSETTING_FEATURE_API
+#undef SYSTEMSETTING_DEVICE_CAP
+
diff --git a/src/SystemSetting/plugin_config.h b/src/SystemSetting/plugin_config.h
new file mode 100755 (executable)
index 0000000..ad74a50
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _SYSTEMSETTING_PLUGIN_CONFIG_H_
+#define _SYSTEMSETTING_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+DECLARE_FUNCTION_GETTER(SystemSetting);
+
+#define SYSTEMSETTING_CHECK_ACCESS(functionName)               \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >(             \
+                                            getSystemSettingFunctionData,     \
+                                            functionName)
+}
+}
+
+#endif
diff --git a/src/SystemSetting/plugin_config_impl.h b/src/SystemSetting/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..66720dc
--- /dev/null
@@ -0,0 +1,24 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _SYSTEMSETTING_PLUGIN_CONFIG_IMPL_H_
+#define _SYSTEMSETTING_PLUGIN_CONFIG_IMPL_H_
+
+#define SYSTEMSETTING_FUNCTION_API_SET_PROPERTY "setProperty"
+#define SYSTEMSETTING_FUNCTION_API_GET_PROPERTY "getProperty"
+
+#endif
diff --git a/src/SystemSetting/plugin_initializer.cpp b/src/SystemSetting/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..e6b1bf3
--- /dev/null
@@ -0,0 +1,116 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <TimeTracer.h>
+#include <Security.h>
+#include "JSSystemSetting.h"
+#include "SystemSettingAsyncCallbackManager.h"
+#include "plugin_config.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace SystemSetting {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+#define WRT_JS_EXTENSION_OBJECT_TIZEN "tizen"
+
+AceSecurityStatus systemsettingAceCheckAccessFunction(const char* functionName)
+{
+    return SYSTEMSETTING_CHECK_ACCESS(functionName);
+}
+
+DEFINE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+
+DEFINE_SECURITY_ACCESSOR_SETTER(AceCheckerSystemSettingSetter,
+                                JSSystemSettingPriv,
+                                gSecurityAccessor);
+
+class_definition_options_t ClassOptions =
+{
+    JS_CLASS,
+    NONE,
+    ALWAYS_NOTICE,
+    IGNORED,
+    AceCheckerSystemSettingSetter,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\SystemSetting ] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    Try
+    {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LOGE("WrtAccess initialization failed");
+    }
+    INITAILIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor, systemsettingAceCheckAccessFunction);
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\SystemSetting ] on_widget_stop_callback (%d)", widgetId);
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE,"SystemSetting");
+    TIME_TRACER_RELEASE();
+    Try
+    {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    }
+    Catch(Commons::Exception)
+    {
+        LOGE("WrtAccess deinitialization failed");
+    }
+    FINALIZE_GLOBAL_SECURITY_ACCESSOR(gSecurityAccessor);
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\SystemSetting] on_frame_load_callback (%p)", context);
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\SystemSetting] on_frame_unload_callback (%p)", context);
+
+    DeviceAPI::SystemSetting::SystemSettingAsyncCallbackManagerSingleton::Instance().unregisterContext(static_cast<JSContextRef>(context));
+}
+
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(
+        WRT_JS_EXTENSION_OBJECT_TIZEN,
+        "systemsetting",
+        (js_class_template_getter)DeviceAPI::SystemSetting::JSSystemSetting::getClassRef,
+        &ClassOptions)
+PLUGIN_CLASS_MAP_END
+
+} // SystemSetting
+} // DeviceAPI
diff --git a/src/Systeminfo/CMakeLists.txt b/src/Systeminfo/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..15d316b
--- /dev/null
@@ -0,0 +1,125 @@
+SET(TARGET_NAME ${systeminfo_target})
+SET(DESTINATION_NAME ${systeminfo_dest})
+SET(TARGET_IMPL_NAME ${systeminfo_impl})
+
+SET(PLATFORM_PKGS_FOR_SYSTEMINFO
+    capi-system-info
+    capi-system-runtime-info
+    capi-network-connection
+    capi-system-device
+    capi-system-system-settings
+    sensor
+)
+
+IF(ENABLE_OPTIONAL_BT)
+SET(PLATFORM_PKGS_FOR_SYSTEMINFO
+    ${PLATFORM_PKGS_FOR_SYSTEMINFO}
+    capi-network-bluetooth
+)
+ENDIF(ENABLE_OPTIONAL_BT)
+
+IF(ENABLE_OPTIONAL_WI_FI)
+SET(PLATFORM_PKGS_FOR_SYSTEMINFO
+    ${PLATFORM_PKGS_FOR_SYSTEMINFO}
+    capi-network-wifi
+)
+ENDIF(ENABLE_OPTIONAL_WI_FI)
+
+IF(ENABLE_OPTIONAL_TELEPHONY)
+SET(PLATFORM_PKGS_FOR_SYSTEMINFO
+    ${PLATFORM_PKGS_FOR_SYSTEMINFO}
+    tapi
+)
+ENDIF(ENABLE_OPTIONAL_TELEPHONY)
+
+PKG_CHECK_MODULES(platform_pkgs_systeminfo REQUIRED
+    ${PLATFORM_PKGS_FOR_SYSTEMINFO}
+)
+
+ADD_DEFINITIONS("-fvisibility=hidden")
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_systeminfo_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSSystemInfoDeviceCapability.cpp
+    SystemInfoDeviceCapability.cpp
+    JSSystemInfoProperty.cpp
+    SystemInfoProperty.cpp
+    JSSystemInfoBattery.cpp
+    SystemInfoBattery.cpp
+    JSSystemInfoLocale.cpp
+    SystemInfoLocale.cpp
+    JSSystemInfoStorage.cpp
+    SystemInfoStorage.cpp
+    JSSystemInfoStorageUnit.cpp
+    SystemInfoStorageUnit.cpp
+    JSSystemInfoDisplay.cpp
+    SystemInfoDisplay.cpp
+    JSSystemInfoDeviceOrientation.cpp
+    SystemInfoDeviceOrientation.cpp
+    JSSystemInfo.cpp
+    SystemInfo.cpp
+    JSSystemInfoCpu.cpp
+    SystemInfoCpu.cpp
+    JSSystemInfoBuild.cpp
+    SystemInfoBuild.cpp
+    JSSystemInfoPeripheral.cpp
+    SystemInfoPeripheral.cpp
+    SystemInfoPropertySuccessCallbackData.cpp
+    JSSystemInfoNetwork.cpp
+    SystemInfoNetwork.cpp
+    JSSystemInfoMemory.cpp
+    SystemInfoMemory.cpp
+    SystemInfoUtil.cpp
+)
+
+IF(ENABLE_OPTIONAL_WI_FI)
+SET(SRCS_IMPL
+    ${SRCS_IMPL}
+    JSSystemInfoWifiNetwork.cpp
+    SystemInfoWifiNetwork.cpp
+)
+ENDIF(ENABLE_OPTIONAL_WI_FI)
+
+IF(ENABLE_OPTIONAL_TELEPHONY)
+SET(SRCS_IMPL
+    ${SRCS_IMPL}
+    JSSystemInfoCellularNetwork.cpp
+    SystemInfoCellularNetwork.cpp
+    JSSystemInfoSIM.cpp
+    SystemInfoSIM.cpp
+)
+ENDIF(ENABLE_OPTIONAL_TELEPHONY)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${platform_pkgs_systeminfo_LIBRARIES}
+)
+
+SET(SRCS
+    plugin_config.cpp
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/systeminfo
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Systeminfo/JSSystemInfo.cpp b/src/Systeminfo/JSSystemInfo.cpp
new file mode 100755 (executable)
index 0000000..970bed6
--- /dev/null
@@ -0,0 +1,941 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfo.h"
+#include "SystemInfo.h"
+#include "SystemInfoPropertySuccessCallbackData.h"
+#include "JSSystemInfoDeviceCapability.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <GlobalContextManager.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+#include "plugin_config.h"
+#include "SysteminfoDeviceCapabilityKeys.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO = "SystemInfo";
+
+const char* SYSTEMINFO_GET_TOTAL_MEMORY = "getTotalMemory";
+const char* SYSTEMINFO_GET_AVAILABLE_MEMORY = "getAvailableMemory";
+
+const char* SYSTEMINFO_GET_CAPABILITIES = "getCapabilities";
+const char* SYSTEMINFO_GET_CAPABILITY = "getCapability";
+const char* SYSTEMINFO_GET_COUNT = "getCount";
+const char* SYSTEMINFO_GET_PROPERTYVALUE = "getPropertyValue";
+const char* SYSTEMINFO_GET_PROPERTYVALUEARRAY = "getPropertyValueArray";
+const char* SYSTEMINFO_ADD_LISTENER = "addPropertyValueChangeListener";
+const char* SYSTEMINFO_ADD_LISTENER_ARRAY = "addPropertyValueArrayChangeListener";
+const char* SYSTEMINFO_REMOVE_LISTENER = "removePropertyValueChangeListener";
+
+const char* SYSTEMINFO_OPTION_TIMEOUT = "timeout";
+const char* SYSTEMINFO_OPTION_HIGHTHRESHOLD = "highThreshold";
+const char* SYSTEMINFO_OPTION_LOWTHRESHOLD = "lowThreshold";
+}
+
+JSClassDefinition JSSystemInfo::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO, //class name
+        NULL, // parent class
+        NULL, //m_property,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticFunction JSSystemInfo::m_function[] = {
+        { SYSTEMINFO_GET_TOTAL_MEMORY, getTotalMemory, kJSPropertyAttributeNone },
+        { SYSTEMINFO_GET_AVAILABLE_MEMORY, getAvailableMemory, kJSPropertyAttributeNone },
+        { SYSTEMINFO_GET_CAPABILITIES, getCapabilities, kJSPropertyAttributeNone },
+        { SYSTEMINFO_GET_CAPABILITY, getCapability, kJSPropertyAttributeNone },
+        { SYSTEMINFO_GET_COUNT, getCount, kJSPropertyAttributeNone },
+        { SYSTEMINFO_GET_PROPERTYVALUE, getPropertyValue, kJSPropertyAttributeNone },
+        { SYSTEMINFO_GET_PROPERTYVALUEARRAY, getPropertyValueArray, kJSPropertyAttributeNone },
+        { SYSTEMINFO_ADD_LISTENER, addPropertyValueChangeListener, kJSPropertyAttributeNone },
+        { SYSTEMINFO_ADD_LISTENER_ARRAY, addPropertyValueArrayChangeListener, kJSPropertyAttributeNone },
+        { SYSTEMINFO_REMOVE_LISTENER, removePropertyValueChangeListener, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfo::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfo::m_jsClassRef = JSClassCreate(JSSystemInfo::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfo::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSSystemInfo::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfo::getInstance();
+}
+
+void JSSystemInfo::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+JSValueRef JSSystemInfo::getTotalMemory(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        long long totalMemory = SystemInfo::getInstance().getTotalMemory();
+
+        return JSUtil::toJSValueRef(context, totalMemory);
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getTotalMemory fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "getTotalMemory fails");
+    }
+}
+
+JSValueRef JSSystemInfo::getAvailableMemory(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        long long availableMemory = SystemInfo::getInstance().getAvailableMemory();
+
+        return JSUtil::toJSValueRef(context, availableMemory);
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getAvailableMemory fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "getAvailableMemory fails");
+    }
+}
+
+JSValueRef JSSystemInfo::getCapabilities(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    //SystemInfoDeviceCapability getCapabilities();
+    try {
+        return JSSystemInfoDeviceCapability::makeJSObject(context,
+                SystemInfo::getInstance().getCapabilities());
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getCapabilities fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "getCapabilities fails");
+    }
+}
+
+JSValueRef JSSystemInfo::getCapability(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    //SystemInfoDeviceCapability getCapability();
+    try {
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        SystemInfoDeviceCapabilityPtr deviceCapability = SystemInfo::getInstance().getCapabilities();
+        std::string key = validator.toString(0);
+        LOGD("capability key (%s)", key.c_str());
+
+        /*API feature*/
+        if (key == TIZEN_FEATURE_ACCOUNT) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isAccount());
+        } else if (key == TIZEN_FEATURE_ARCHIVE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isArchive());
+        } else if (key == TIZEN_FEATURE_BADGE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBadge());
+        } else if (key == TIZEN_FEATURE_BOOKMARK) {
+               return JSUtil::toJSValueRef(context, deviceCapability->isBookmark());
+        } else if (key == TIZEN_FEATURE_CALENDAR) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isCalendar());
+        } else if (key == TIZEN_FEATURE_CONTACT) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isContact());
+        } else if (key == TIZEN_FEATURE_DATACONTROL) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isDataControl());
+        } else if (key == TIZEN_FEATURE_DATASYNC) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isDataSync());
+        } else if (key == TIZEN_FEATURE_DOWNLOAD) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isDownload());
+        } else if (key == TIZEN_FEATURE_EXIF) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isExif ());
+        } else if (key == TIZEN_FEATURE_SYSTEMSETTING) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isSystemSetting());
+        } else if (key == TIZEN_FEATURE_SYSTEMSETTING_HOME_SCREEN) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isSystemSettingHomeScreen());
+        } else if (key == TIZEN_FEATURE_SYSTEMSETTING_LOCK_SCREEN) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isSystemSettingLockScreen());
+        } else if (key == TIZEN_FEATURE_SYSTEMSETTING_INCOMING_CALL) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isSystemSettingIncomingCall());
+        } else if (key == TIZEN_FEATURE_SYSTEMSETTING_NOTIFICATION_EMAIL) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isSystemSettingNotificationEmail());
+        } else if (key == TIZEN_FEATURE_WEBSETTING) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isWebSetting());
+        } else if (key == TIZEN_FEATURE_EMAIL) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isMessagingEmail());
+        } else if (key == TIZEN_FEATURE_TELEPHONY) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isTelephony());
+        } else if (key == TIZEN_FEATURE_TELEPHONY_MMS) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isTelephonyMMS());
+        } else if (key == TIZEN_FEATURE_NOTIFICATION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isNotification());
+        }
+
+        /*Battery feature*/
+        else if (key == TIZEN_FEATURE_BATTERY) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBattery()); //TODO
+        }
+
+        /*Camera feature*/
+        else if (key == TIZEN_FEATURE_CAMERA) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isCamera());
+        } else if (key == TIZEN_FEATURE_CAMERABACK) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isCameraBack());
+        } else if (key == TIZEN_FEATURE_CAMERABACKFLASH) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isCameraBackFlash());
+        } else if (key == TIZEN_FEATURE_CAMERAFRONT) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isCameraFront());
+        } else if (key == TIZEN_FEATURE_CAMERAFRONTFLASH) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isCameraFrontFlash());
+        }
+
+        /*Database feature*/
+        else if (key == TIZEN_FEATURE_DATA_ENCRYPTION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isDataEncryption());
+        }
+
+        /*FM radio featuer*/
+        else if (key == TIZEN_FEATURE_FMRADIO) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isFmRadio());
+        }
+        /*Graphics feature*/
+        else if (key == TIZEN_FEATURE_GRAPHICS_ACCELERATION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isGraphicsAcceleration());
+        }
+
+        /*LED feature*/
+        else if (key == TIZEN_FEATURE_LED) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isLed());
+        }
+
+        /*input feature*/
+        else if (key == TIZEN_FEATURE_INPUTKEYBOARD) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isInputKeyboard());
+        } else if (key == TIZEN_FEATURE_INPUTKEYBOARD_LAYOUT) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getInputKeyboardLayout());
+        }
+
+        /*Location feature*/
+        else if (key == TIZEN_FEATURE_LOCATION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isLocation());
+        } else if (key == TIZEN_FEATURE_LOCATIONGPS) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isLocationGps());
+        } else if (key == TIZEN_FEATURE_LOCATIONWPS) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isLocationWps());
+        } else if (key == TIZEN_FEATURE_LOCATIONBATCH) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isLocationBatch());
+        }
+
+        /*Multimedia transcoder*/
+        else if (key == TIZEN_FEATURE_MULTIMEDIA_TRANSCODER) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isMultimediaTranscoder());
+        }
+
+        /*Microphone feature*/
+        else if (key == TIZEN_FEATURE_MICROPHONE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isMicrophone());
+        }
+
+        /*Multi-point touch feature*/
+        else if (key == TIZEN_FEATURE_MULTITOUCH_PINCH_ZOOM) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isMultiTouchPinchZoon());
+        } else if (key == TIZEN_FEATURE_MULTITOUCHCOUNT) {
+            return JSUtil::toJSValueRef(context, static_cast<unsigned long>(deviceCapability->getMultiTouchCount()));
+        }
+
+        /*Network faeture*/
+        else if (key == TIZEN_FEATURE_BLUETOOTH_ALWAYS_ON) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBluetoothAlwaysOn());
+        } else if (key == TIZEN_FEATURE_BLUETOOTH) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBluetooth());
+        } else if (key == TIZEN_FEATURE_BLUETOOTH_AUDIO_CALL) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBluetoothAudioCall());
+        } else if (key == TIZEN_FEATURE_BLUETOOTH_AUDIO_MEDIA) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBluetoothAudioMedia());
+        } else if (key == TIZEN_FEATURE_BLUETOOTH_HEALTH) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBluetootHealth());
+        } else if (key == TIZEN_FEATURE_BLUETOOTH_HID) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBluetootHID());
+        } else if (key == TIZEN_FEATURE_BLUETOOTH_LE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBluetootLE());
+        } else if (key == TIZEN_FEATURE_BLUETOOTH_OPP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBluetootOPP());
+        } else if (key == TIZEN_FEATURE_NFC) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isNfc());
+        } else if (key == TIZEN_FEATURE_NFC_CARD_EMULATION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isNfcEmulation());
+        } else if (key == TIZEN_FEATURE_NFC_RESERVED_PUSH) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isNfcReservedPush());
+        } else if (key == TIZEN_FEATURE_PUSH) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isPush());
+        } else if (key == TIZEN_FEATURE_SECURE_ELEMENT) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isSecureElement());
+        } else if (key == TIZEN_FEATURE_WIFI) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isWifi());
+        } else if (key == TIZEN_FEATURE_WIFIDIRECT) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isWifiDirect());
+        }
+
+        /*openGL ES feature*/
+        else if (key == TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getOpenglesTextureFormat());
+        } else if (key == TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_3DC) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isOpenglesTextureFormat3DC());
+        } else if (key == TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_ATC) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isOpenglesTextureFormatATC());
+        } else if (key == TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_ETC) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isOpenglesTextureFormatETC());
+        } else if (key == TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_PTC) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isOpenglesTextureFormatPTC());
+        } else if (key == TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_PVRTC) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isOpenglesTextureFormatPVRTC());
+        } else if (key == TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_UTC) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isOpenglesTextureFormatUTC());
+        } else if (key == TIZEN_FEATURE_OPENGLES) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isOpengles());
+        } else if (key == TIZEN_FEATURE_OPENGLESVERSION1_1) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isOpenglesVersion11());
+        } else if (key == TIZEN_FEATURE_OPENGLESVERSION2_0) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isOpenglesVersion20());
+        }
+
+        /*platform feature*/
+        else if (key == TIZEN_FEATURE_CORE_API_VERSION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isCoreAPIVersion());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_CPU_ARCH) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreCpuArch());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_CPU_ARCH_ARMV7) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreCpuArchArmv7());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_CPU_ARCH_ARMV6) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreCpuArchArmv6());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_CPU_ARCH_X86) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreCpuArchX86());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_CPU_FREQUENCY) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatformCoreCpuFrequency());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreFpuArch());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_SSE2) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreFpuArchSSE2());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_SSE3) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreFpuArchSSE3());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_SSSE3) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreFpuArchSSSE3());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_VFPV2) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreFpuArchVFPV2());
+        } else if (key == TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_VFPV3) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatfomCoreFpuArchVFPV3());
+        } else if (key == TIZEN_FEATURE_NATIVE_API_VERSION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getNativeApiVersion());
+        } else if (key == TIZEN_FEATURE_NATIVE_OSP_COMPATIBLE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isNativeOspCompatible());
+        } else if (key == TIZEN_FEATURE_PLATFORM_VERSION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatformVersion());
+        } else if (key == TIZEN_FEATURE_PLATFORM_WEB_API_VERSION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getWebApiVersion());
+        } else if (key == TIZEN_FETURE_PLATFORM_VERSION_NAME) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatformVersionName());
+        }
+
+        /*profile feature*/
+        else if (key == TIZEN_FEATURE_PROFILE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getProfile());
+        }
+
+        /*Screen feature*/
+        else if (key == TIZEN_FEATURE_AUTO_ROTATION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isAutoRotation());
+        } else if (key == TIZEN_FEATURE_SCREEN) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreen());
+        } else if (key == TIZEN_FEATURE_SCREEN_BPP) {
+            return JSUtil::toJSValueRef(context, static_cast<unsigned long>(deviceCapability->getScreenBpp()));
+        } else if (key == TIZEN_FEATURE_SCREEN_COORDINATE_SYSTEM_SIZE_LARGE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenCoordinateSystemSizeLarge());
+        } else if (key == TIZEN_FEATURE_SCREEN_COORDINATE_SYSTEM_SIZE_NORMAL) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenCoordinateSystemSizeNormal());
+        } else if (key == TIZEN_FEATURE_SCREEN_DPI) {
+            return JSUtil::toJSValueRef(context, static_cast<unsigned long>(deviceCapability->getScreenDpi()));
+        } else if (key == TIZEN_FEATURE_SCREEN_HEIGHT) {
+            return JSUtil::toJSValueRef(context, static_cast<unsigned long>(deviceCapability->getScreenHeight()));
+        } else if (key == TIZEN_FEATURE_SCREEN_OUTPUT_HDMI) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenOutputHdmi());
+        } else if (key == TIZEN_FEATURE_SCREEN_OUTPUT_RCA) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenOutputRca());
+        } else if (key == TIZEN_FEATURE_SCREEN_SIZE_ALL) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSizeAll());
+        } else if (key == TIZEN_FEATURE_SCREEN_SIZE_LARGE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSizeLarge());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_NORMAL) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSizeNormal());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_240_400) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSize240_400());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_320_320) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSize320_320());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_320_480) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSize320_480());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_360_480) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSize360_480());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_480_800) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSize480_800());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_540_960) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSize540_960());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_600_1024) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSize600_1024());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_720_1280) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSize720_1280());
+        } else if (key == TIZEN_FEATURE_SCREENSIZE_1080_1920) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isScreenSize1080_1920());
+        } else if (key == TIZEN_FEATURE_SCREEN_WIDTH) {
+            return JSUtil::toJSValueRef(context, static_cast<unsigned long>(deviceCapability->getScreenWidth()));
+        }
+
+        /*Sencor faeture*/
+        else if (key == TIZEN_FEATURE_ACCELEROMETER) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isAccelerometer());
+        } else if (key == TIZEN_FEATURE_ACCELEROMETER_WAKEUP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isAccelerometerWakeup());
+        } else if (key == TIZEN_FEATURE_ACTIVITY_RECOGNITION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isActivityRecognition());
+        } else if (key == TIZEN_FEATURE_BAROMETER) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBarometer());
+        } else if (key == TIZEN_FEATURE_BAROMETER_WAKEUP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isBarometerWakeup());
+        } else if (key == TIZEN_FEATURE_GESTURE_RECOGNITION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isGestureRecognition());
+        } else if (key == TIZEN_FEATURE_GRAVITY) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isGravity());
+        } else if (key == TIZEN_FEATURE_GYROSCOPE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isGyroscope());
+        } else if (key == TIZEN_FEATURE_GYROSCOPE_WAKEUP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isGyroscopeWakeup());
+        } else if (key == TIZEN_FEATURE_HRM) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isHrm());
+        } else if (key == TIZEN_FEATURE_HUMIDITY) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isHumidity());
+        } else if (key == TIZEN_FEATURE_LINEAR_ACCELERATION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isLinearAcceleration());
+        } else if (key == TIZEN_FEATURE_MAGNETOMETER) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isMagnetometer());
+        } else if (key == TIZEN_FEATURE_MAGNETOMETER_WAKEUP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isMagnetometerWakeup());
+        } else if (key == TIZEN_FEATURE_PEDOMETER) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isPedometer());
+        } else if (key == TIZEN_FEATURE_PHOTOMETER) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isPhotometer());
+        } else if (key == TIZEN_FEATURE_PHOTOMETER_WAKEUP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isPhotometerWakeup());
+        } else if (key == TIZEN_FEATURE_PROXIMITY) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isProximity());
+        } else if (key == TIZEN_FEATURE_PROXIMITY_WAKEUP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isProximityWakeup());
+        } else if (key == TIZEN_FEATURE_ROTATION_VECTOR) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isRotationVector());
+        } else if (key == TIZEN_FEATURE_TEMPERATURE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isTemperature());
+        } else if (key == TIZEN_FEATURE_TILTMETER) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isTiltmeter());
+        } else if (key == TIZEN_FEATURE_TILTMETER_WAKEUP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isTiltmeterWakeup());
+        } else if (key == TIZEN_FEATURE_ULTRAVIOLET) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isUltraviolet());
+        } else if (key == TIZEN_FEATURE_WRIST_UP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isWristUp());
+        } else if (key == TIZEN_FEATURE_HUMAN_ACTIVITY_MONITOR) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isHumanActivityMonitor());
+        }
+
+        /*Shell feature*/
+        else if (key == TIZEN_FEATURE_SHELL_APP_WIDGET) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isShellAppWidget());
+        }
+
+        /*Sip feature*/
+        else if (key == TIZEN_FEATURE_SIPVOIP) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isSipVoip());
+        }
+
+        /*Speech feature*/
+        else if (key == TIZEN_FEATURE_SPEECH_RECOGNITION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isSpeechRecognition());
+        } else if (key == TIZEN_FEATURE_SPEECH_SYNTHESIS) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isSpeechSynthesis());
+        }
+
+        /*USB feature*/
+        else if (key == TIZEN_FEATURE_USBACCESSORY) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isUsbAccessory());
+        } else if (key == TIZEN_FEATURE_USBHOST) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isUsbHost());
+        }
+
+        /*Web service*/
+        else if (key == TIZEN_FEATURE_WEB_SERVICE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isWebService());
+        }
+
+        /*Vision feature*/
+        else if (key == TIZEN_FEATURE_VISION_FACE_RECOGNITION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isVisionFaceRecognition());
+        } else if (key == TIZEN_FEATURE_VISION_IMAGE_RECOGNITION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isVisionImageRecognition());
+        } else if (key == TIZEN_FEATURE_VISION_QRCODE_GENERATION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isVisionQrcodeGeneration());
+        } else if (key == TIZEN_FEATURE_VISION_QRCODE_RECOGNITION) {
+            return JSUtil::toJSValueRef(context, deviceCapability->isVisionQrcodeRecognition());
+        }
+
+        /*build information*/
+        else if (key == TIZEN_SYSTEM_BUILD_DATE) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getBuildDate());
+        } else if (key == TIZEN_SYSTEM_BUILD_STRING) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getBuildString());
+        } else if (key == TIZEN_SYSTEM_BUILD_TIME) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getBuildTime());
+        } else if (key == TIZEN_SYSTEM_BUILD_MANUFACTURER) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getBuildManafacture());
+        }
+
+        /*duid*/
+        else if (key == TIZEN_SYSTEM_TIZEN_ID) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getDuid());
+        }
+
+        /*model name*/
+        else if (key == TIZEN_SYSTEM_MODEL_NAME) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getModelName());
+        }
+
+        /*platform*/
+        else if (key == TIZEN_SYSTEM_PLATFORM_NAME) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatformName());
+        } else if (key == TIZEN_SYSTEM_PLATFORM_COMMUNICATION_PROCESSOR) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatformCommunicationProcessor());
+        } else if (key == TIZEN_SYSTEM_PLATFORM_PROCESSOR) {
+            return JSUtil::toJSValueRef(context, deviceCapability->getPlatformProcessor());
+        } else {
+            std::string errorMessage = "Unsupported key : ";
+            errorMessage.append(key.c_str());
+            LOGE("%s", errorMessage.c_str());
+            throw NotSupportedException(errorMessage.c_str());
+        }
+
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getCapabilities fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "getCapabilities fails");
+    }
+}
+
+JSValueRef JSSystemInfo::getCount(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        ArgumentValidator validator(context, argument_count, arguments);
+        std::string property = validator.toString(0);
+        SystemInfoPropertyId propertyId = SystemInfoProperty::stringToPropertyId(property);
+        long count = SystemInfo::getInstance().getCount(propertyId);
+        return JSUtil::toJSValueRef(context, count);
+
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getCount fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "getCount fails");
+    }
+}
+
+JSValueRef JSSystemInfo::getPropertyValue(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    //void getPropertyValue(SystemInfoPropertyId property,
+    //        SystemInfoPropertySuccessCallback successCallback,
+    //        optional ErrorCallback? errorCallback);
+    try {
+        ArgumentValidator validator(context, argument_count, arguments);
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        std::string property_id = validator.toString(0);
+
+        PropertyCallbackDataPtr callback(new(std::nothrow) PropertyCallbackData(g_ctx));
+        if (!callback) {
+            LOGE("Failed to allocate memory");
+            throw UnknownException("Failed to allocate memory");
+        }
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setArrayCallback(false);
+
+        SystemInfoPropertyId propertyId = SystemInfoProperty::stringToPropertyId(property_id);
+        callback->setPropertyId(propertyId);
+
+        LOGD("Entered");
+        SystemInfo::getInstance().getPropertyValue(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getPropertyValue fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "getPropertyValue fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfo::getPropertyValueArray(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    try {
+        ArgumentValidator validator(context, argument_count, arguments);
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        std::string property_id = validator.toString(0);
+
+        PropertyCallbackDataPtr callback(new(std::nothrow) PropertyCallbackData(g_ctx));
+        if (!callback) {
+            LOGE("Failed to allocate memory");
+            throw UnknownException("Failed to allocate memory");
+        }
+        callback->setSuccessCallback(validator.toFunction(1));
+        callback->setErrorCallback(validator.toFunction(2, true));
+        callback->setArrayCallback(true);
+
+        callback->setPropertyId(SystemInfoProperty::stringToPropertyId(property_id));
+
+        SystemInfo::getInstance().getPropertyValue(callback);
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("getPropertyValue fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "getPropertyValue fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfo::addPropertyValueChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    //unsigned long addPropertyValueChangeListener(SystemInfoPropertyId property,
+    //        SystemInfoPropertySuccessCallback successCallback,
+    //        optional SystemInfoOptions? options);
+    try {
+        ArgumentValidator validator(context, argument_count, arguments);
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        PropertyCallbackDataPtr callback(new(std::nothrow) PropertyCallbackData(g_ctx));
+        if (!callback) {
+            LOGE("Failed to allocate memory");
+            throw UnknownException("Failed to allocate memory");
+        }
+
+        std::string property_id = validator.toString(0);
+        callback->setSuccessCallback(validator.toFunction(1));
+
+        SystemInfoOptions options;
+        double highThreshold = 0;
+        double lowThreshold = 0;
+        JSObjectRef options_obj = validator.toObject(2, true);
+
+        callback->setErrorCallback(validator.toFunction(3, true));
+
+        callback->setArrayCallback(false);
+
+        SystemInfoPropertyId property = SystemInfoProperty::stringToPropertyId(property_id);
+        callback->setPropertyId(property);
+
+        if (NULL != options_obj) {
+            JSObjectRef js_timeout = getOptionFromObj(context,
+                    options_obj, SYSTEMINFO_OPTION_TIMEOUT);
+            if (NULL != js_timeout) {
+                options.timeout = JSUtil::JSValueToULong(context,
+                        js_timeout);
+            }
+
+            JSObjectRef js_high_threshold = getOptionFromObj(context,
+                    options_obj, SYSTEMINFO_OPTION_HIGHTHRESHOLD);
+            if (NULL != js_high_threshold) {
+                highThreshold = JSUtil::JSValueToDouble(context,
+                        js_high_threshold);
+            }
+
+            JSObjectRef js_low_threshold = getOptionFromObj(context,
+                    options_obj, SYSTEMINFO_OPTION_LOWTHRESHOLD);
+            if (NULL != js_low_threshold) {
+                lowThreshold = JSUtil::JSValueToDouble(context,
+                        js_low_threshold);
+            }
+
+            options.high_threshold = highThreshold;
+            options.low_threshold = lowThreshold;
+            callback->setOptions(options);
+        }
+
+        unsigned long listener_id =
+                SystemInfo::getInstance().addPropertyValueChangeListener(callback);
+
+        return JSUtil::toJSValueRef(context, listener_id);
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("addPropertyValueChangeListener fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "addPropertyValueChangeListener fails");
+    }
+}
+
+JSValueRef JSSystemInfo::addPropertyValueArrayChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    SET_TIME_TRACER_ITEM(0);
+    LOGD("Entered");
+
+    //unsigned long addPropertyValueChangeListener(SystemInfoPropertyId property,
+    //        SystemInfoPropertySuccessCallback successCallback,
+    //        optional SystemInfoOptions? options);
+    try {
+        ArgumentValidator validator(context, argument_count, arguments);
+        JSContextRef g_ctx =
+                GlobalContextManager::getInstance()->getGlobalContext(context);
+
+        PropertyCallbackDataPtr callback(new(std::nothrow) PropertyCallbackData(g_ctx));
+        if (!callback) {
+            LOGE("Failed to allocate memory");
+            throw UnknownException("Failed to allocate memory");
+        }
+
+        std::string property_id = validator.toString(0);
+        callback->setSuccessCallback(validator.toFunction(1));
+
+        SystemInfoOptions options;
+        double highThreshold = 0;
+        double lowThreshold = 0;
+        JSObjectRef options_obj = validator.toObject(2, true);
+
+        callback->setErrorCallback(validator.toFunction(3, true));
+
+        callback->setPropertyId(SystemInfoProperty::stringToPropertyId(property_id));
+        callback->setArrayCallback(true);
+
+        if (NULL != options_obj) {
+            JSObjectRef js_timeout = getOptionFromObj(context,
+                    options_obj, SYSTEMINFO_OPTION_TIMEOUT);
+            if (NULL != js_timeout) {
+                options.timeout = JSUtil::JSValueToULong(context,
+                        js_timeout);
+            }
+
+            JSObjectRef js_high_threshold = getOptionFromObj(context,
+                    options_obj, SYSTEMINFO_OPTION_HIGHTHRESHOLD);
+            if (NULL != js_high_threshold) {
+                highThreshold = JSUtil::JSValueToDouble(context,
+                        js_high_threshold);
+            }
+
+            JSObjectRef js_low_threshold = getOptionFromObj(context,
+                    options_obj, SYSTEMINFO_OPTION_LOWTHRESHOLD);
+            if (NULL != js_low_threshold) {
+                lowThreshold = JSUtil::JSValueToDouble(context,
+                        js_low_threshold);
+            }
+
+            options.high_threshold = highThreshold;
+            options.low_threshold = lowThreshold;
+            callback->setOptions(options);
+        }
+
+        unsigned long listener_id =
+                SystemInfo::getInstance().addPropertyValueChangeListener(callback);
+
+        return JSUtil::toJSValueRef(context, listener_id);
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("addPropertyValueChangeListener fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "addPropertyValueChangeListener fails");
+    }
+}
+
+JSValueRef JSSystemInfo::removePropertyValueChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef this_object,
+        size_t argument_count,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    //void removePropertyValueChangeListener(unsigned long listenerId);
+    try {
+        ArgumentValidator validator(context, argument_count, arguments);
+
+        unsigned long listener_id = validator.toULong(0);
+        LOGD("Removing listener ID: %u", listener_id);
+
+        SystemInfo::getInstance().removePropertyValueChangeListener(context, listener_id);
+    } catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    } catch (...) {
+        LOGE("removePropertyValueChangeListener fails");
+        return JSWebAPIErrorFactory::postException(context, exception,
+                JSWebAPIErrorFactory::UNKNOWN_ERROR,
+                "removePropertyValueChangeListener fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+
+JSObjectRef JSSystemInfo::getOptionFromObj(JSContextRef context,
+        JSObjectRef obj,
+        const char* name)
+{
+    JSObjectRef option_obj = NULL;
+    JSStringRef property_name = JSStringCreateWithUTF8CString(name);
+    bool has = JSObjectHasProperty(context, obj, property_name);
+    JSStringRelease(property_name);
+    if (has) {
+        JSValueRef value = JSUtil::getProperty(context, obj, name);
+        option_obj = JSUtil::JSValueToObject(context, value);
+    }
+    return option_obj;
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfo.h b/src/Systeminfo/JSSystemInfo.h
new file mode 100755 (executable)
index 0000000..ae3f70f
--- /dev/null
@@ -0,0 +1,164 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfo {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Returns available memory of the device.
+     */
+    static JSValueRef getTotalMemory (JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Returns total memory of the device.
+     */
+    static JSValueRef getAvailableMemory (JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Retrieves the capabilities of the device.
+     */
+    static JSValueRef getCapabilities(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Retrieves the capabilities of the device.
+     */
+    static JSValueRef getCapability(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Retrieves the number of system property.
+     */
+    static JSValueRef getCount(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Retrieves the current state of a given system property.
+     */
+    static JSValueRef getPropertyValue(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Retrieves List of the current state of a given system property.
+     */
+    static JSValueRef getPropertyValueArray(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Allows tracking the change of one or several system properties.
+     */
+    static JSValueRef addPropertyValueChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Allows tracking the change of one or several system properties.
+     */
+    static JSValueRef addPropertyValueArrayChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    /**
+     * Unsubscribes notifications for property changes.
+     */
+    static JSValueRef removePropertyValueChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef this_object,
+            size_t argument_count,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSObjectRef getOptionFromObj(JSContextRef context,
+            JSObjectRef obj,
+            const char* name);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_H__
diff --git a/src/Systeminfo/JSSystemInfoBattery.cpp b/src/Systeminfo/JSSystemInfoBattery.cpp
new file mode 100755 (executable)
index 0000000..9792d36
--- /dev/null
@@ -0,0 +1,212 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoBattery.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+struct SystemInfoBatteryHolder {
+    SystemInfoBatteryPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_BATTERY = "SystemInfoBattery";
+
+const char* SYSTEMINFO_BATTERY_LEVEL = "level";
+const char* SYSTEMINFO_BATTERY_IS_CHARGING = "isCharging";
+}
+
+JSClassDefinition JSSystemInfoBattery::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_BATTERY, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoBattery::m_property[] = {
+        { SYSTEMINFO_BATTERY_LEVEL, getLevel, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_BATTERY_IS_CHARGING, getIsCharging, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoBattery::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoBattery::m_jsClassRef =
+        JSClassCreate(JSSystemInfoBattery::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoBattery::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoBatteryPtr JSSystemInfoBattery::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoBatteryHolder* priv =
+            static_cast<SystemInfoBatteryHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoBattery::setPrivateObject(JSObjectRef object,
+        SystemInfoBatteryPtr native)
+{
+    SystemInfoBatteryHolder* priv =
+            static_cast<SystemInfoBatteryHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoBattery::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoBattery given");
+        throw UnknownException("NULL pointer to SystemInfoBattery given");
+    }
+
+    SystemInfoBatteryPtr battery = std::dynamic_pointer_cast<SystemInfoBattery>(
+            native);
+
+    if (!battery) {
+        LOGE("Invalid pointer to SystemInfoBattery given");
+        throw UnknownException("Invalid pointer to SystemInfoBattery given");
+    }
+
+    SystemInfoBatteryHolder* priv = new(std::nothrow) SystemInfoBatteryHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = battery;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoBattery::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoBattery::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoBatteryHolder* priv =
+            static_cast<SystemInfoBatteryHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoBattery::getLevel(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoBatteryPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getLevel());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getLevel fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoBattery::getIsCharging(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoBatteryPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->isCharging());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getIsCharging fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoBattery.h b/src/Systeminfo/JSSystemInfoBattery.h
new file mode 100755 (executable)
index 0000000..e99c147
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_BATTERY_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_BATTERY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoBattery.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoBattery {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoBatteryPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoBatteryPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getLevel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getIsCharging(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_BATTERY_H__
diff --git a/src/Systeminfo/JSSystemInfoBuild.cpp b/src/Systeminfo/JSSystemInfoBuild.cpp
new file mode 100755 (executable)
index 0000000..c840cf9
--- /dev/null
@@ -0,0 +1,230 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Export.h>
+#include <JSUtil.h>
+#include <Logger.h>
+#include "JSSystemInfoBuild.h"
+#include "JSSystemInfoProperty.h"
+#include "PlatformException.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+struct SystemInfoBuildHolder {
+    SystemInfoBuildPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_BUILD = "SystemInfoBuild";
+const char* SYSTEMINFO_MODEL = "model";
+const char* SYSTEMINFO_MANUFACTURER = "manufacturer";
+const char* SYSTEMINFO_BUILDVERSION = "buildVersion";
+}
+
+JSClassDefinition JSSystemInfoBuild::m_classInfo = {
+    0, // current (and only) version is 0
+    kJSClassAttributeNone, //attributes
+    SYSTEMINFO_SYSTEMINFO_BUILD, //class name
+    JSSystemInfoProperty::getClassRef(), // parent class
+    m_property,
+    NULL, //m_function,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //deleteProperty,
+    NULL, //getPropertyNames,
+    NULL, //function,
+    NULL, //constructor,
+    NULL, //hasInstance,
+    NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoBuild::m_property[] = {
+    { SYSTEMINFO_MODEL, getModel, NULL,
+        kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { SYSTEMINFO_MANUFACTURER, getManufacturer, NULL,
+        kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { SYSTEMINFO_BUILDVERSION, getBuildVersion, NULL,
+        kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoBuild::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoBuild::m_jsClassRef =
+        JSClassCreate(JSSystemInfoBuild::getClassInfo());
+
+SystemInfoBuildPtr JSSystemInfoBuild::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw Common::TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = Common::JSUtil::JSValueToObject(context, value);
+    SystemInfoBuildHolder* priv =
+            static_cast< SystemInfoBuildHolder* >(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw Common::UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw Common::UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+JSClassRef DLL_EXPORT JSSystemInfoBuild::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSSystemInfoBuild::setPrivateObject(JSObjectRef object,
+        SystemInfoBuildPtr native)
+{
+    SystemInfoBuildHolder* priv =
+            static_cast< SystemInfoBuildHolder* >(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw Common::UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoBuild::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    LOGD("Entered");
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoBuild given");
+        throw Common::UnknownException("NULL pointer to SystemInfoBuild given");
+    }
+
+    SystemInfoBuildPtr build = std::dynamic_pointer_cast<SystemInfoBuild>(
+            native);
+
+    if (!build) {
+        LOGE("Invalid pointer to SystemInfoBuild given");
+        throw Common::UnknownException("Invalid pointer to SystemInfoBuild given");
+    }
+
+    SystemInfoBuildHolder* priv = new(std::nothrow) SystemInfoBuildHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw Common::UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = build;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+             static_cast< void* >(priv));
+    return obj;
+}
+
+void JSSystemInfoBuild::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoBuild::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoBuildHolder* priv =
+            static_cast< SystemInfoBuildHolder* >(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoBuild::getModel(JSContextRef context,
+        JSObjectRef object, JSStringRef property_name, JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        SystemInfoBuildPtr priv = getPrivateObject(context, object);
+        return Common::JSUtil::toJSValueRef(context, priv->getModel());
+    }
+    catch (const Common::BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+        err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getModel fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoBuild::getManufacturer(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        SystemInfoBuildPtr priv = getPrivateObject(context, object);
+        return Common::JSUtil::toJSValueRef(context, priv->getManufacturer());
+    }
+    catch (const Common::BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+        err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getManufacturer fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoBuild::getBuildVersion(JSContextRef context,
+    JSObjectRef object,
+    JSStringRef property_name,
+    JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        SystemInfoBuildPtr priv = getPrivateObject(context, object);
+        return Common::JSUtil::toJSValueRef(context, priv->getBuildVersion());
+    }
+    catch (const Common::BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+        err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getBuildVersion fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // namespace SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoBuild.h b/src/Systeminfo/JSSystemInfoBuild.h
new file mode 100755 (executable)
index 0000000..c6d65cf
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_BUILDINFO_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_BUILDINFO_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoBuild.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoBuild
+{
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoBuildPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoBuildPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getModel(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getManufacturer(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getBuildVersion(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // namespace Systeminfo
+} // namespace DeviceAPI
+
+#endif // __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_BUILDINFO_H__
diff --git a/src/Systeminfo/JSSystemInfoCellularNetwork.cpp b/src/Systeminfo/JSSystemInfoCellularNetwork.cpp
new file mode 100755 (executable)
index 0000000..027179f
--- /dev/null
@@ -0,0 +1,440 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoCellularNetwork.h"
+
+#include <SecurityExceptions.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+struct SystemInfoCellularNetworkHolder {
+    SystemInfoCellularNetworkPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_CELLULAR_NETWORK = "SystemInfoCellularNetwork";
+
+const char* SYSTEMINFO_CELLULAR_NETWORK_STATUS = "status";
+const char* SYSTEMINFO_CELLULAR_NETWORK_APN = "apn";
+const char* SYSTEMINFO_CELLULAR_NETWORK_IP_ADDRESS = "ipAddress";
+const char* SYSTEMINFO_CELLULAR_NETWORK_IPV6_ADDRESS = "ipv6Address";
+const char* SYSTEMINFO_CELLULAR_NETWORK_MCC = "mcc";
+const char* SYSTEMINFO_CELLULAR_NETWORK_MNC = "mnc";
+const char* SYSTEMINFO_CELLULAR_NETWORK_CELL_ID = "cellId";
+const char* SYSTEMINFO_CELLULAR_NETWORK_LAC = "lac";
+const char* SYSTEMINFO_CELLULAR_NETWORK_IS_ROAMING = "isRoaming";
+const char* SYSTEMINFO_CELLULAR_NETWORK_IS_FLIGHT_MODE = "isFlightMode";
+const char* SYSTEMINFO_CELLULAR_NETWORK_IMEI = "imei";
+}
+
+JSClassDefinition JSSystemInfoCellularNetwork::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_CELLULAR_NETWORK, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoCellularNetwork::m_property[] = {
+        { SYSTEMINFO_CELLULAR_NETWORK_STATUS, getStatus, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_APN, getApn, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_IP_ADDRESS, getIpAddress, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_IPV6_ADDRESS, getIpv6Address, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_MCC, getMcc, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_MNC,getMnc, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_CELL_ID, getCellId, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_LAC, getLac, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_IS_ROAMING, isRoaming, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_IS_FLIGHT_MODE, isFlightMode, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_CELLULAR_NETWORK_IMEI, getImei, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoCellularNetwork::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoCellularNetwork::m_jsClassRef =
+        JSClassCreate(JSSystemInfoCellularNetwork::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoCellularNetwork::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoCellularNetworkPtr JSSystemInfoCellularNetwork::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoCellularNetworkHolder* priv =
+            static_cast<SystemInfoCellularNetworkHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoCellularNetwork::setPrivateObject(JSObjectRef object,
+        SystemInfoCellularNetworkPtr native)
+{
+    SystemInfoCellularNetworkHolder* priv =
+            static_cast<SystemInfoCellularNetworkHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoCellularNetwork::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoCellularNetwork given");
+        throw UnknownException("NULL pointer to SystemInfoCellularNetwork given");
+    }
+
+    SystemInfoCellularNetworkPtr cellular =
+            std::dynamic_pointer_cast<SystemInfoCellularNetwork>(native);
+
+    if (!cellular) {
+        LOGE("Invalid pointer to SystemInfoCellularNetwork given");
+        throw UnknownException("Invalid pointer to SystemInfoCellularNetwork given");
+    }
+
+    SystemInfoCellularNetworkHolder* priv = new(std::nothrow) SystemInfoCellularNetworkHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = cellular;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoCellularNetwork::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoCellularNetwork::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoCellularNetworkHolder* priv =
+            static_cast<SystemInfoCellularNetworkHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoCellularNetwork::getStatus(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getStatus());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getStatus fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::getApn(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getApn());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getApn fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::getIpAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getIpAddress());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getIpAddress fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::getIpv6Address(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getIpv6Address());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getIpv6Address fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::getMcc(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context,
+                static_cast<unsigned long>(priv->getMcc()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMcc fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::getMnc(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context,
+                static_cast<unsigned long>(priv->getMnc()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMnc fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::getCellId(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context,
+                static_cast<unsigned long>(priv->getCellId()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getCellId fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::getLac(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context,
+                static_cast<unsigned long>(priv->getLac()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getLac fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::isRoaming(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->isRoaming());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("isRoaming fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::isFlightMode(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->isFlightMode());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("isFlightMode fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoCellularNetwork::getImei(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ACE_ACCESS_CHECK(
+            AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                SYSTEMINFO_FUNCTION_API_GET_PROPERTY_PARTNER_VALUE);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+        );
+
+        SystemInfoCellularNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getImei());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getImei fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoCellularNetwork.h b/src/Systeminfo/JSSystemInfoCellularNetwork.h
new file mode 100755 (executable)
index 0000000..a9b2375
--- /dev/null
@@ -0,0 +1,128 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_CELLULAR_NETWORK_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_CELLULAR_NETWORK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoCellularNetwork.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoCellularNetwork {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoCellularNetworkPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoCellularNetworkPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getStatus(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getApn(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getIpAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getIpv6Address(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getMcc(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getMnc(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getCellId(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getLac(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef isRoaming(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef isFlightMode(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getImei(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_CELLULAR_NETWORK_H__
diff --git a/src/Systeminfo/JSSystemInfoCpu.cpp b/src/Systeminfo/JSSystemInfoCpu.cpp
new file mode 100755 (executable)
index 0000000..3913fe5
--- /dev/null
@@ -0,0 +1,181 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoCpu.h"
+#include <Export.h>
+#include <Logger.h>
+#include "PlatformException.h"
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+struct SystemInfoCpuHolder {
+    SystemInfoCpuPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_CPU = "SystemInfoCpu";
+const char* SYSTEMINFO_CPU_LOAD = "load";
+}
+
+JSClassDefinition JSSystemInfoCpu::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_CPU, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoCpu::m_property[] = {
+        { SYSTEMINFO_CPU_LOAD, getLoad, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoCpu::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoCpu::m_jsClassRef =
+        JSClassCreate(JSSystemInfoCpu::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoCpu::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoCpuPtr JSSystemInfoCpu::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw Common::TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = Common::JSUtil::JSValueToObject(context, value);
+    SystemInfoCpuHolder* priv =
+            static_cast<SystemInfoCpuHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw Common::UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw Common::UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoCpu::setPrivateObject(JSObjectRef object,
+        SystemInfoCpuPtr native)
+{
+    SystemInfoCpuHolder* priv =
+            static_cast<SystemInfoCpuHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw Common::UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoCpu::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoCpu given");
+        throw Common::UnknownException("NULL pointer to SystemInfoCpu given");
+    }
+
+    SystemInfoCpuPtr cpu = std::dynamic_pointer_cast<SystemInfoCpu>(
+            native);
+
+    if (!cpu) {
+        LOGE("Invalid pointer to SystemInfoCpu given");
+        throw Common::UnknownException("Invalid pointer to SystemInfoCpu given");
+    }
+
+    SystemInfoCpuHolder* priv = new(std::nothrow) SystemInfoCpuHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw Common::UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = cpu;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoCpu::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoCpu::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoCpuHolder* priv =
+            static_cast<SystemInfoCpuHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoCpu::getLoad(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    try {
+        SystemInfoCpuPtr priv = getPrivateObject(context, object);
+        return Common::JSUtil::toJSValueRef(context, priv->getLoad());
+    }
+    catch (const Common::BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+        err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getLoad fails");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // namespace SystemInfo
+} // namespace DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoCpu.h b/src/Systeminfo/JSSystemInfoCpu.h
new file mode 100755 (executable)
index 0000000..895a209
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_CPU_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_CPU_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoCpu.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoCpu {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoCpuPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoCpuPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getLoad(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_CPU_H__
diff --git a/src/Systeminfo/JSSystemInfoDeviceCapability.cpp b/src/Systeminfo/JSSystemInfoDeviceCapability.cpp
new file mode 100755 (executable)
index 0000000..4ad04be
--- /dev/null
@@ -0,0 +1,681 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoDeviceCapability.h"
+
+#include <SecurityExceptions.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include "plugin_config.h"
+
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+struct SystemInfoDeviceCapabilityHolder {
+    SystemInfoDeviceCapabilityPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_DEVICE_CAPABILITY = "SystemInfoDeviceCapability";
+
+const char* DEVICE_CAPABILITY_BLUETOOTH = "bluetooth";
+const char* DEVICE_CAPABILITY_NFC = "nfc";
+const char* DEVICE_CAPABILITY_NFC_RESERVED_PUSH = "nfcReservedPush";
+const char* DEVICE_CAPABILITY_MULTITOUCHCOUNT = "multiTouchCount";
+const char* DEVICE_CAPABILITY_INPUTKEYBOARD = "inputKeyboard";
+const char* DEVICE_CAPABILITY_INPUTKEYBOARD_LAYOUT = "inputKeyboardLayout";
+const char* DEVICE_CAPABILITY_WIFI = "wifi";
+const char* DEVICE_CAPABILITY_WIFIDIRECT = "wifiDirect";
+const char* DEVICE_CAPABILITY_OPENGLES = "opengles";
+const char* DEVICE_CAPABILITY_OPENGLES_TEXTURE_FORMAT = "openglestextureFormat";
+const char* DEVICE_CAPABILITY_OPENGLESVERSION1_1 = "openglesVersion1_1";
+const char* DEVICE_CAPABILITY_OPENGLESVERSION2_0 = "openglesVersion2_0";
+const char* DEVICE_CAPABILITY_FMRADIO = "fmRadio";
+const char* DEVICE_CAPABILITY_PLATFORMVERSION = "platformVersion";
+const char* DEVICE_CAPABILITY_WEBAPIVERSION = "webApiVersion";
+const char* DEVICE_CAPABILITY_NATIVEAPIVERSION = "nativeApiVersion";
+const char* DEVICE_CAPABILITY_PLATFORMNAME = "platformName";
+const char* DEVICE_CAPABILITY_CAMERA = "camera";
+const char* DEVICE_CAPABILITY_CAMERAFRONT = "cameraFront";
+const char* DEVICE_CAPABILITY_CAMERAFRONTFLASH = "cameraFrontFlash";
+const char* DEVICE_CAPABILITY_CAMERABACK = "cameraBack";
+const char* DEVICE_CAPABILITY_CAMERABACKFLASH = "cameraBackFlash";
+const char* DEVICE_CAPABILITY_LOCATION = "location";
+const char* DEVICE_CAPABILITY_LOCATIONGPS = "locationGps";
+const char* DEVICE_CAPABILITY_LOCATIONWPS = "locationWps";
+const char* DEVICE_CAPABILITY_MICROPHONE = "microphone";
+const char* DEVICE_CAPABILITY_USBHOST = "usbHost";
+const char* DEVICE_CAPABILITY_USBACCESSORY = "usbAccessory";
+const char* DEVICE_CAPABILITY_SCREENOUTPUTRCA = "screenOutputRca";
+const char* DEVICE_CAPABILITY_SCREENOUTPUTHDMI = "screenOutputHdmi";
+const char* DEVICE_CAPABILITY_PLATFORMCORECPUARCH = "platformCoreCpuArch";
+const char* DEVICE_CAPABILITY_PLATFORMCOREFPUARCH = "platformCoreFpuArch";
+const char* DEVICE_CAPABILITY_SIPVOIP = "sipVoip";
+const char* DEVICE_CAPABILITY_DUID = "duid";
+const char* DEVICE_CAPABILITY_SPEECH_RECOGNITION = "speechRecognition";
+const char* DEVICE_CAPABILITY_SPEECH_SYNTHESIS = "speechSynthesis";
+const char* DEVICE_CAPABILITY_ACCELEROMETER = "accelerometer";
+const char* DEVICE_CAPABILITY_ACCELEROMETER_WAKEUP = "accelerometerWakeup";
+const char* DEVICE_CAPABILITY_BAROMETER = "barometer";
+const char* DEVICE_CAPABILITY_BAROMETER_WAKEUP = "barometerWakeup";
+const char* DEVICE_CAPABILITY_GYROSCOPE = "gyroscope";
+const char* DEVICE_CAPABILITY_GYROSCOPE_WAKEUP = "gyroscopeWakeup";
+const char* DEVICE_CAPABILITY_MAGNETOMETER = "magnetometer";
+const char* DEVICE_CAPABILITY_MAGNETOMETER_WAKEUP = "magnetometerWakeup";
+const char* DEVICE_CAPABILITY_PHOTOMETER = "photometer";
+const char* DEVICE_CAPABILITY_PHOTOMETER_WAKEUP = "photometerWakeup";
+const char* DEVICE_CAPABILITY_PROXIMITY = "proximity";
+const char* DEVICE_CAPABILITY_PROXIMITY_WAKEUP = "proximityWakeup";
+const char* DEVICE_CAPABILITY_TILTMETER = "tiltmeter";
+const char* DEVICE_CAPABILITY_TILTMETER_WAKEUP = "tiltmeterWakeup";
+const char* DEVICE_CAPABILITY_DATA_ENCRYPTION = "dataEncryption";
+const char* DEVICE_CAPABILITY_GRAPHICS_ACCELERATION = "graphicsAcceleration";
+const char* DEVICE_CAPABILITY_PUSH = "push";
+const char* DEVICE_CAPABILITY_TELEPHONY = "telephony";
+const char* DEVICE_CAPABILITY_TELEPHONY_MMS = "telephonyMms";
+const char* DEVICE_CAPABILITY_TELEPHONY_SMS = "telephonySms";
+const char* DEVICE_CAPABILITY_SCREENSIZE_NORMAL = "screenSizeNormal";
+const char* DEVICE_CAPABILITY_SCREENSIZE_480_800 = "screenSize480_800";
+const char* DEVICE_CAPABILITY_SCREENSIZE_720_1280 = "screenSize720_1280";
+const char* DEVICE_CAPABILITY_AUTO_ROTATION = "autoRotation";
+const char* DEVICE_CAPABILITY_SHELL_APP_WIDGET = "shellAppWidget";
+const char* DEVICE_CAPABILITY_VISION_IMAGE_RECOGNITION = "visionImageRecognition";
+const char* DEVICE_CAPABILITY_VISION_QRCODE_GENERATION = "visionQrcodeGeneration";
+const char* DEVICE_CAPABILITY_VISION_QRCODE_RECOGNITION = "visionQrcodeRecognition";
+const char* DEVICE_CAPABILITY_VISION_FACE_RECOGNITION = "visionFaceRecognition";
+const char* DEVICE_CAPABILITY_SECURE_ELEMENT = "secureElement";
+const char* DEVICE_CAPABILITY_NATIVE_OSP_COMPATIBLE = "nativeOspCompatible";
+const char* DEVICE_CAPABILITY_PROFILE = "profile";
+}
+
+JSClassDefinition JSSystemInfoDeviceCapability::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_DEVICE_CAPABILITY, //class name
+        NULL, // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        hasProperty,
+        getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoDeviceCapability::m_property[] = {
+    { DEVICE_CAPABILITY_BLUETOOTH, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_NFC, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_NFC_RESERVED_PUSH, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_MULTITOUCHCOUNT, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_INPUTKEYBOARD, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_INPUTKEYBOARD_LAYOUT, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_WIFI, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_WIFIDIRECT, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_OPENGLES, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_OPENGLES_TEXTURE_FORMAT, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_OPENGLESVERSION1_1, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_OPENGLESVERSION2_0, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_FMRADIO, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PLATFORMVERSION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_WEBAPIVERSION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_NATIVEAPIVERSION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PLATFORMNAME, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_CAMERA, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_CAMERAFRONT, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_CAMERAFRONTFLASH, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_CAMERABACK, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_CAMERABACKFLASH, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_LOCATION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_LOCATIONGPS, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_LOCATIONWPS, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_MICROPHONE, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_USBHOST, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_USBACCESSORY, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SCREENOUTPUTRCA, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SCREENOUTPUTHDMI, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PLATFORMCORECPUARCH, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PLATFORMCOREFPUARCH, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SIPVOIP, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_DUID, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SPEECH_RECOGNITION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SPEECH_SYNTHESIS, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_ACCELEROMETER, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_ACCELEROMETER_WAKEUP, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_BAROMETER, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_BAROMETER_WAKEUP, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_GYROSCOPE, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_GYROSCOPE_WAKEUP, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_MAGNETOMETER, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_MAGNETOMETER_WAKEUP, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PHOTOMETER, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PHOTOMETER_WAKEUP, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PROXIMITY, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PROXIMITY_WAKEUP, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_TILTMETER, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_TILTMETER_WAKEUP, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_DATA_ENCRYPTION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_GRAPHICS_ACCELERATION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PUSH, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_TELEPHONY, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_TELEPHONY_MMS, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_TELEPHONY_SMS, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SCREENSIZE_NORMAL, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SCREENSIZE_480_800, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SCREENSIZE_720_1280, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_AUTO_ROTATION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SHELL_APP_WIDGET, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_VISION_IMAGE_RECOGNITION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_VISION_QRCODE_GENERATION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_VISION_QRCODE_RECOGNITION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_VISION_FACE_RECOGNITION, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_SECURE_ELEMENT, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_NATIVE_OSP_COMPATIBLE, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { DEVICE_CAPABILITY_PROFILE, getProperty, NULL,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly  },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoDeviceCapability::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoDeviceCapability::m_jsClassRef =
+        JSClassCreate(JSSystemInfoDeviceCapability::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoDeviceCapability::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoDeviceCapabilityPtr JSSystemInfoDeviceCapability::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoDeviceCapabilityHolder* priv =
+            static_cast<SystemInfoDeviceCapabilityHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoDeviceCapability::setPrivateObject(JSObjectRef object,
+        SystemInfoDeviceCapabilityPtr native)
+{
+    SystemInfoDeviceCapabilityHolder* priv =
+            static_cast<SystemInfoDeviceCapabilityHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoDeviceCapability::makeJSObject(JSContextRef context,
+        SystemInfoDeviceCapabilityPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoDeviceCapability given");
+        throw UnknownException("NULL pointer to SystemInfoDeviceCapability given");
+    }
+
+    SystemInfoDeviceCapabilityHolder* priv = new(std::nothrow) SystemInfoDeviceCapabilityHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoDeviceCapability::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoDeviceCapability::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+bool JSSystemInfoDeviceCapability::hasProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name)
+{
+    JSStaticValue* property = &m_property[0];
+    while (property->name) {
+        if (JSStringIsEqualToUTF8CString(property_name, property->name)) {
+            return true;
+        }
+        ++property;
+    }
+    return false;
+}
+
+JSValueRef JSSystemInfoDeviceCapability::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDeviceCapabilityPtr priv = getPrivateObject(context, object);
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_BLUETOOTH)) {
+            return JSUtil::toJSValueRef(context, priv->isBluetooth());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_NFC)) {
+            return JSUtil::toJSValueRef(context, priv->isNfc());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_NFC_RESERVED_PUSH)) {
+            return JSUtil::toJSValueRef(context, priv->isNfcReservedPush());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_MULTITOUCHCOUNT)) {
+            return JSUtil::toJSValueRef(context,
+                    static_cast<unsigned long>(priv->getMultiTouchCount()));
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_INPUTKEYBOARD)) {
+            return JSUtil::toJSValueRef(context, priv->isInputKeyboard());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_INPUTKEYBOARD_LAYOUT)) {
+            return JSUtil::toJSValueRef(context, priv->isInputKeyboardLayout());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_WIFI)) {
+            return JSUtil::toJSValueRef(context, priv->isWifi());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_WIFIDIRECT)) {
+            return JSUtil::toJSValueRef(context, priv->isWifiDirect());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_OPENGLES)) {
+            return JSUtil::toJSValueRef(context, priv->isOpengles());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_OPENGLES_TEXTURE_FORMAT)) {
+            return JSUtil::toJSValueRef(context, priv->getOpenglesTextureFormat());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_OPENGLESVERSION1_1)) {
+            return JSUtil::toJSValueRef(context, priv->isOpenglesVersion11());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_OPENGLESVERSION2_0)) {
+            return JSUtil::toJSValueRef(context, priv->isOpenglesVersion20());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_FMRADIO)) {
+            return JSUtil::toJSValueRef(context, priv->isFmRadio());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PLATFORMVERSION)) {
+            ACE_ACCESS_CHECK(
+                AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_CAPABILITIES);
+                TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+            );
+            return JSUtil::toJSValueRef(context, priv->getPlatformVersion());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_WEBAPIVERSION)) {
+            ACE_ACCESS_CHECK(
+                AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_CAPABILITIES);
+                TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+            );
+            return JSUtil::toJSValueRef(context, priv->getWebApiVersion());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_NATIVEAPIVERSION)) {
+            ACE_ACCESS_CHECK(
+                AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_CAPABILITIES);
+                TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+            );
+            return JSUtil::toJSValueRef(context, priv->getNativeApiVersion());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PLATFORMNAME)) {
+            return JSUtil::toJSValueRef(context, priv->getPlatformName());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_CAMERA)) {
+            return JSUtil::toJSValueRef(context, priv->isCamera());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_CAMERAFRONT)) {
+            return JSUtil::toJSValueRef(context, priv->isCameraFront());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_CAMERAFRONTFLASH)) {
+            return JSUtil::toJSValueRef(context, priv->isCameraFrontFlash());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_CAMERABACK)) {
+            return JSUtil::toJSValueRef(context, priv->isCameraBack());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_CAMERABACKFLASH)) {
+            return JSUtil::toJSValueRef(context, priv->isCameraBackFlash());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_LOCATION)) {
+            return JSUtil::toJSValueRef(context, priv->isLocation());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_LOCATIONGPS)) {
+            return JSUtil::toJSValueRef(context, priv->isLocationGps());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_LOCATIONWPS)) {
+            return JSUtil::toJSValueRef(context, priv->isLocationWps());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_MICROPHONE)) {
+            return JSUtil::toJSValueRef(context, priv->isMicrophone());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_USBHOST)) {
+            return JSUtil::toJSValueRef(context, priv->isUsbHost());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_USBACCESSORY)) {
+            return JSUtil::toJSValueRef(context, priv->isUsbAccessory());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SCREENOUTPUTRCA)) {
+            return JSUtil::toJSValueRef(context, priv->isScreenOutputRca());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SCREENOUTPUTHDMI)) {
+            return JSUtil::toJSValueRef(context, priv->isScreenOutputHdmi());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PLATFORMCORECPUARCH)) {
+            return JSUtil::toJSValueRef(context, priv->getPlatfomCoreCpuArch());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PLATFORMCOREFPUARCH)) {
+            return JSUtil::toJSValueRef(context, priv->getPlatfomCoreFpuArch());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SIPVOIP)) {
+            return JSUtil::toJSValueRef(context, priv->isSipVoip());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_DUID)) {
+            return JSUtil::toJSValueRef(context, priv->getDuid());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SPEECH_RECOGNITION)) {
+            return JSUtil::toJSValueRef(context, priv->isSpeechRecognition());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SPEECH_SYNTHESIS)) {
+            return JSUtil::toJSValueRef(context, priv->isSpeechSynthesis());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_ACCELEROMETER)) {
+            return JSUtil::toJSValueRef(context, priv->isAccelerometer());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_ACCELEROMETER_WAKEUP)) {
+            return JSUtil::toJSValueRef(context, priv->isAccelerometerWakeup());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_BAROMETER)) {
+            return JSUtil::toJSValueRef(context, priv->isBarometer());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_BAROMETER_WAKEUP)) {
+            return JSUtil::toJSValueRef(context, priv->isBarometerWakeup());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_GYROSCOPE)) {
+            return JSUtil::toJSValueRef(context, priv->isGyroscope());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_GYROSCOPE_WAKEUP)) {
+            return JSUtil::toJSValueRef(context, priv->isGyroscopeWakeup());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_MAGNETOMETER)) {
+            return JSUtil::toJSValueRef(context, priv->isMagnetometer());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_MAGNETOMETER_WAKEUP)) {
+            return JSUtil::toJSValueRef(context, priv->isMagnetometerWakeup());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PHOTOMETER)) {
+            return JSUtil::toJSValueRef(context, priv->isPhotometer());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PHOTOMETER_WAKEUP)) {
+            return JSUtil::toJSValueRef(context, priv->isPhotometerWakeup());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PROXIMITY)) {
+            return JSUtil::toJSValueRef(context, priv->isProximity());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PROXIMITY_WAKEUP)) {
+            return JSUtil::toJSValueRef(context, priv->isProximityWakeup());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_TILTMETER)) {
+            return JSUtil::toJSValueRef(context, priv->isTiltmeter());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_TILTMETER_WAKEUP)) {
+            return JSUtil::toJSValueRef(context, priv->isTiltmeterWakeup());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_DATA_ENCRYPTION)) {
+            return JSUtil::toJSValueRef(context, priv->isDataEncryption());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_GRAPHICS_ACCELERATION)) {
+            return JSUtil::toJSValueRef(context, priv->isGraphicsAcceleration());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PUSH)) {
+            return JSUtil::toJSValueRef(context, priv->isPush());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_TELEPHONY)) {
+            return JSUtil::toJSValueRef(context, priv->isTelephony());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_TELEPHONY_MMS)) {
+            return JSUtil::toJSValueRef(context, priv->isTelephonyMMS());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_TELEPHONY_SMS)) {
+            return JSUtil::toJSValueRef(context, priv->isTelephonySMS());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SCREENSIZE_NORMAL)) {
+            return JSUtil::toJSValueRef(context, priv->isScreenSizeNormal());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SCREENSIZE_480_800)) {
+            return JSUtil::toJSValueRef(context, priv->isScreenSize480_800());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SCREENSIZE_720_1280)) {
+            return JSUtil::toJSValueRef(context, priv->isScreenSize720_1280());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_AUTO_ROTATION)) {
+            return JSUtil::toJSValueRef(context, priv->isAutoRotation());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SHELL_APP_WIDGET)) {
+            return JSUtil::toJSValueRef(context, priv->isShellAppWidget());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_VISION_IMAGE_RECOGNITION)) {
+            return JSUtil::toJSValueRef(context, priv->isVisionImageRecognition());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_VISION_QRCODE_GENERATION)) {
+            return JSUtil::toJSValueRef(context, priv->isVisionQrcodeGeneration());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_VISION_QRCODE_RECOGNITION)) {
+            return JSUtil::toJSValueRef(context, priv->isVisionQrcodeRecognition());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_VISION_FACE_RECOGNITION)) {
+            return JSUtil::toJSValueRef(context, priv->isVisionFaceRecognition());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_SECURE_ELEMENT)) {
+            return JSUtil::toJSValueRef(context, priv->isSecureElement());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_NATIVE_OSP_COMPATIBLE)) {
+            return JSUtil::toJSValueRef(context, priv->isNativeOspCompatible());
+        }
+        if (JSStringIsEqualToUTF8CString(property_name,
+                DEVICE_CAPABILITY_PROFILE)) {
+            return JSUtil::toJSValueRef(context, priv->getProfile());
+        }
+
+        std::string log_msg = "Property not found: " +
+                JSUtil::JSStringToString(context, property_name);
+        LOGW("%s", log_msg.c_str());
+
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getProperty failed");
+    }
+
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoDeviceCapability.h b/src/Systeminfo/JSSystemInfoDeviceCapability.h
new file mode 100755 (executable)
index 0000000..791c66d
--- /dev/null
@@ -0,0 +1,80 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_DEVICE_CAPABILITY_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_DEVICE_CAPABILITY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoDeviceCapability.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoDeviceCapability {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoDeviceCapabilityPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoDeviceCapabilityPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoDeviceCapabilityPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static bool hasProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_DEVICE_CAPABILITY_H__
diff --git a/src/Systeminfo/JSSystemInfoDeviceOrientation.cpp b/src/Systeminfo/JSSystemInfoDeviceOrientation.cpp
new file mode 100755 (executable)
index 0000000..7811e34
--- /dev/null
@@ -0,0 +1,209 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoDeviceOrientation.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+struct SystemInfoDeviceOrientationHolder {
+    SystemInfoDeviceOrientationPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_DEVICE_ORIENTATION = "SystemInfoDeviceOrientation";
+
+const char* SYSTEMINFO_DEVICE_ORIENTATION_STATUS = "status";
+const char* SYSTEMINFO_DEVICE_ORIENTATION_IS_AUTO_ROTATION = "isAutoRotation";
+}
+
+JSClassDefinition JSSystemInfoDeviceOrientation::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_DEVICE_ORIENTATION, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoDeviceOrientation::m_property[] = {
+        { SYSTEMINFO_DEVICE_ORIENTATION_STATUS, getStatus, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_DEVICE_ORIENTATION_IS_AUTO_ROTATION, isAutoRotation, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoDeviceOrientation::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoDeviceOrientation::m_jsClassRef =
+        JSClassCreate(JSSystemInfoDeviceOrientation::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoDeviceOrientation::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoDeviceOrientationPtr JSSystemInfoDeviceOrientation::getPrivateObject(
+        JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoDeviceOrientationHolder* priv =
+            static_cast<SystemInfoDeviceOrientationHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoDeviceOrientation::setPrivateObject(JSObjectRef object,
+        SystemInfoDeviceOrientationPtr native)
+{
+    SystemInfoDeviceOrientationHolder* priv =
+            static_cast<SystemInfoDeviceOrientationHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoDeviceOrientation::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoDeviceOrientation given");
+        throw UnknownException("NULL pointer to SystemInfoDeviceOrientation given");
+    }
+
+    SystemInfoDeviceOrientationPtr orientation =
+            std::dynamic_pointer_cast<SystemInfoDeviceOrientation>(native);
+
+    if (!orientation) {
+        LOGE("Invalid pointer to SystemInfoDeviceOrientation given");
+        throw UnknownException("Invalid pointer to SystemInfoDeviceOrientation given");
+    }
+
+    SystemInfoDeviceOrientationHolder* priv =
+            new(std::nothrow) SystemInfoDeviceOrientationHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = orientation;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoDeviceOrientation::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoDeviceOrientation::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoDeviceOrientationHolder* priv =
+            static_cast<SystemInfoDeviceOrientationHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoDeviceOrientation::getStatus(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDeviceOrientationPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getStatus());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getStatus failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoDeviceOrientation::isAutoRotation(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDeviceOrientationPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->isAutoRotation());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("isAutoRotation failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoDeviceOrientation.h b/src/Systeminfo/JSSystemInfoDeviceOrientation.h
new file mode 100755 (executable)
index 0000000..23a464a
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_DEVICE_ORIENTATION_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_DEVICE_ORIENTATION_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoDeviceOrientation.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoDeviceOrientation {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoDeviceOrientationPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoDeviceOrientationPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getStatus(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef isAutoRotation(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_DEVICE_ORIENTATION_H__
diff --git a/src/Systeminfo/JSSystemInfoDisplay.cpp b/src/Systeminfo/JSSystemInfoDisplay.cpp
new file mode 100755 (executable)
index 0000000..ff7449a
--- /dev/null
@@ -0,0 +1,327 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoDisplay.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+struct SystemInfoDisplayHolder {
+    SystemInfoDisplayPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_DISPLAY = "SystemInfoDisplay";
+
+const char* SYSTEMINFO_DISPLAY_RESOLUTION_WIDTH = "resolutionWidth";
+const char* SYSTEMINFO_DISPLAY_RESOLUTION_HEIGHT = "resolutionHeight";
+const char* SYSTEMINFO_DISPLAY_DOTS_PER_INCH_WIDTH = "dotsPerInchWidth";
+const char* SYSTEMINFO_DISPLAY_DOTS_PER_INCH_HEIGHT = "dotsPerInchHeight";
+const char* SYSTEMINFO_DISPLAY_PHYSICAL_WIDTH = "physicalWidth";
+const char* SYSTEMINFO_DISPLAY_PHYSICAL_HEIGHT = "physicalHeight";
+const char* SYSTEMINFO_DISPLAY_BRIGHTNESS = "brightness";
+}
+
+JSClassDefinition JSSystemInfoDisplay::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_DISPLAY, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoDisplay::m_property[] = {
+        { SYSTEMINFO_DISPLAY_RESOLUTION_WIDTH, getResolutionWidth, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_DISPLAY_RESOLUTION_HEIGHT, getResolutionHeight, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_DISPLAY_DOTS_PER_INCH_WIDTH, getDotsPerInchWidth, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_DISPLAY_DOTS_PER_INCH_HEIGHT, getDotsPerInchHeight, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_DISPLAY_PHYSICAL_WIDTH, getPhysicalWidth, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_DISPLAY_PHYSICAL_HEIGHT, getPhysicalHeight, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_DISPLAY_BRIGHTNESS, getBrightness, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoDisplay::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoDisplay::m_jsClassRef =
+        JSClassCreate(JSSystemInfoDisplay::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoDisplay::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoDisplayPtr JSSystemInfoDisplay::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoDisplayHolder* priv =
+            static_cast<SystemInfoDisplayHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoDisplay::setPrivateObject(JSObjectRef object,
+        SystemInfoDisplayPtr native)
+{
+    SystemInfoDisplayHolder* priv =
+            static_cast<SystemInfoDisplayHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoDisplay::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoDisplay given");
+        throw UnknownException("NULL pointer to SystemInfoDisplay given");
+    }
+
+    SystemInfoDisplayPtr display = std::dynamic_pointer_cast<SystemInfoDisplay>(
+            native);
+
+    if (!display) {
+        LOGE("Invalid pointer to SystemInfoDisplay given");
+        throw UnknownException("Invalid pointer to SystemInfoDisplay given");
+    }
+
+    SystemInfoDisplayHolder* priv = new(std::nothrow) SystemInfoDisplayHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = display;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoDisplay::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoDisplay::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoDisplayHolder* priv =
+            static_cast<SystemInfoDisplayHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoDisplay::getResolutionWidth(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDisplayPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getResolutionWidth());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getResolutionWidth failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoDisplay::getResolutionHeight(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDisplayPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getResolutionHeight());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getResolutionHeight failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoDisplay::getDotsPerInchWidth(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDisplayPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getDotsPerInchWidth());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getDotsPerInchWidth failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoDisplay::getDotsPerInchHeight(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDisplayPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getDotsPerInchHeight());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getDotsPerInchHeight failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoDisplay::getPhysicalWidth(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDisplayPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getPhysicalWidth());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getPhysicalWidth failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoDisplay::getPhysicalHeight(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDisplayPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getPhysicalHeight());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getPhysicalHeight failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoDisplay::getBrightness(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoDisplayPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getBrightness());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getBrightness failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoDisplay.h b/src/Systeminfo/JSSystemInfoDisplay.h
new file mode 100755 (executable)
index 0000000..b7170cb
--- /dev/null
@@ -0,0 +1,107 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_DISPLAY_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_DISPLAY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoDisplay.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoDisplay {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoDisplayPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoDisplayPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getResolutionWidth(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getResolutionHeight(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getDotsPerInchWidth(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getDotsPerInchHeight(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getPhysicalWidth(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getPhysicalHeight(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getBrightness(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_DISPLAY_H__
diff --git a/src/Systeminfo/JSSystemInfoLocale.cpp b/src/Systeminfo/JSSystemInfoLocale.cpp
new file mode 100755 (executable)
index 0000000..33ddc4e
--- /dev/null
@@ -0,0 +1,212 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoLocale.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+struct SystemInfoLocaleHolder {
+    SystemInfoLocalePtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_LOCALE = "SystemInfoLocale";
+
+const char* SYSTEMINFO_LOCALE_LANGUAGE = "language";
+const char* SYSTEMINFO_LOCALE_COUNTRY = "country";
+}
+
+JSClassDefinition JSSystemInfoLocale::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_LOCALE, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoLocale::m_property[] = {
+        { SYSTEMINFO_LOCALE_LANGUAGE, getLanguage, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_LOCALE_COUNTRY, getCountry, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoLocale::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoLocale::m_jsClassRef =
+        JSClassCreate(JSSystemInfoLocale::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoLocale::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoLocalePtr JSSystemInfoLocale::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoLocaleHolder* priv =
+            static_cast<SystemInfoLocaleHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoLocale::setPrivateObject(JSObjectRef object,
+        SystemInfoLocalePtr native)
+{
+    SystemInfoLocaleHolder* priv =
+            static_cast<SystemInfoLocaleHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoLocale::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoLocale given");
+        throw UnknownException("NULL pointer to SystemInfoLocale given");
+    }
+
+    SystemInfoLocalePtr locale = std::dynamic_pointer_cast<SystemInfoLocale>(
+            native);
+
+    if (!locale) {
+        LOGE("Invalid pointer to SystemInfoLocale given");
+        throw UnknownException("Invalid pointer to SystemInfoLocale given");
+    }
+
+    SystemInfoLocaleHolder* priv = new(std::nothrow) SystemInfoLocaleHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = locale;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoLocale::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoLocale::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoLocaleHolder* priv =
+            static_cast<SystemInfoLocaleHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoLocale::getLanguage(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoLocalePtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getLanguage());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getLanguage fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoLocale::getCountry(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoLocalePtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getCountry());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getCountry fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoLocale.h b/src/Systeminfo/JSSystemInfoLocale.h
new file mode 100755 (executable)
index 0000000..4779ac0
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_LOCALE_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_LOCALE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoLocale.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoLocale {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoLocalePtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoLocalePtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getLanguage(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getCountry(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_LOCALE_H__
diff --git a/src/Systeminfo/JSSystemInfoMemory.cpp b/src/Systeminfo/JSSystemInfoMemory.cpp
new file mode 100755 (executable)
index 0000000..d04ab0d
--- /dev/null
@@ -0,0 +1,189 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoMemory.h"
+
+#include <Logger.h>
+#include <TimeTracer.h>
+#include <Export.h>
+#include <JSWebAPIErrorFactory.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+struct SystemInfoMemoryHolder {
+    SystemInfoMemoryPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_MEMORY = "SystemInfoMemory";
+
+const char* SYSTEMINFO_MEMORY_STATE = "status";
+
+}
+
+JSClassDefinition JSSystemInfoMemory::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_MEMORY, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoMemory::m_property[] = {
+        { SYSTEMINFO_MEMORY_STATE, getStatus, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoMemory::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoMemory::m_jsClassRef =
+        JSClassCreate(JSSystemInfoMemory::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoMemory::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoMemoryPtr JSSystemInfoMemory::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoMemoryHolder* priv =
+            static_cast<SystemInfoMemoryHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoMemory::setPrivateObject(JSObjectRef object,
+        SystemInfoMemoryPtr native)
+{
+    SystemInfoMemoryHolder* priv =
+            static_cast<SystemInfoMemoryHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoMemory::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoMemory given");
+        throw UnknownException("NULL pointer to SystemInfoMemory given");
+    }
+
+    SystemInfoMemoryPtr memory = std::dynamic_pointer_cast<SystemInfoMemory>(
+            native);
+
+    if (!memory) {
+        LOGE("Invalid pointer to SystemInfoMemory given");
+        throw UnknownException("Invalid pointer to SystemInfoMemory given");
+    }
+
+    SystemInfoMemoryHolder* priv = new(std::nothrow) SystemInfoMemoryHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = memory;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoMemory::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoMemory::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoMemoryHolder* priv =
+            static_cast<SystemInfoMemoryHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoMemory::getStatus(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoMemoryPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getStatus());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getState fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoMemory.h b/src/Systeminfo/JSSystemInfoMemory.h
new file mode 100755 (executable)
index 0000000..3b81126
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_MEMORY_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_MEMORY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoMemory.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoMemory {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoMemoryPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoMemoryPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getStatus(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_MEMORY_H__
diff --git a/src/Systeminfo/JSSystemInfoNetwork.cpp b/src/Systeminfo/JSSystemInfoNetwork.cpp
new file mode 100755 (executable)
index 0000000..e564bfa
--- /dev/null
@@ -0,0 +1,181 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoNetwork.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+struct SystemInfoNetworkHolder {
+    SystemInfoNetworkPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_NETWORK = "SystemInfoNetwork";
+const char* SYSTEMINFO_NETWORK_TYPE = "networkType";
+}
+
+JSClassDefinition JSSystemInfoNetwork::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_NETWORK, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoNetwork::m_property[] = {
+        { SYSTEMINFO_NETWORK_TYPE, getNetworkType, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoNetwork::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoNetwork::m_jsClassRef =
+        JSClassCreate(JSSystemInfoNetwork::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoNetwork::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoNetworkPtr JSSystemInfoNetwork::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoNetworkHolder* priv =
+            static_cast<SystemInfoNetworkHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoNetwork::setPrivateObject(JSObjectRef object,
+        SystemInfoNetworkPtr native)
+{
+    SystemInfoNetworkHolder* priv =
+            static_cast<SystemInfoNetworkHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoNetwork::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoNetwork given");
+        throw UnknownException("NULL pointer to SystemInfoNetwork given");
+    }
+
+    SystemInfoNetworkPtr network = std::dynamic_pointer_cast<SystemInfoNetwork>(
+            native);
+
+    if (!network) {
+        LOGE("Invalid pointer to SystemInfoNetwork given");
+        throw UnknownException("Invalid pointer to SystemInfoNetwork given");
+    }
+
+    SystemInfoNetworkHolder* priv = new(std::nothrow) SystemInfoNetworkHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = network;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoNetwork::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoNetwork::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoNetworkHolder* priv =
+            static_cast<SystemInfoNetworkHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoNetwork::getNetworkType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoNetworkPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getNetworkTypeString());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getNetworkType failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoNetwork.h b/src/Systeminfo/JSSystemInfoNetwork.h
new file mode 100755 (executable)
index 0000000..48081cf
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_NETWORK_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_NETWORK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoNetwork.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoNetwork {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoNetworkPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoNetworkPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getNetworkType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_NETWORK_H__
diff --git a/src/Systeminfo/JSSystemInfoPeripheral.cpp b/src/Systeminfo/JSSystemInfoPeripheral.cpp
new file mode 100755 (executable)
index 0000000..5383e30
--- /dev/null
@@ -0,0 +1,181 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoPeripheral.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+struct SystemInfoPeripheralHolder {
+    SystemInfoPeripheralPtr ptr;
+};
+
+namespace {
+    const char* SYSTEMINFO_SYSTEMINFO_PERIPHERAL = "SystemInfoPeripheral";
+    const char* SYSTEMINFO_SYSTEMINFO_IS_VIDEO_OUTPUT_ON = "isVideoOutputOn";
+}
+
+JSClassDefinition JSSystemInfoPeripheral::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_PERIPHERAL, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoPeripheral::m_property[] = {
+        { SYSTEMINFO_SYSTEMINFO_IS_VIDEO_OUTPUT_ON, getIsVideoOutputOn, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoPeripheral::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoPeripheral::m_jsClassRef =
+        JSClassCreate(JSSystemInfoPeripheral::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoPeripheral::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoPeripheralPtr JSSystemInfoPeripheral::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw Common::TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = Common::JSUtil::JSValueToObject(context, value);
+    SystemInfoPeripheralHolder* priv =
+            static_cast<SystemInfoPeripheralHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw Common::UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw Common::UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoPeripheral::setPrivateObject(JSObjectRef object,
+        SystemInfoPeripheralPtr native)
+{
+    SystemInfoPeripheralHolder* priv =
+            static_cast<SystemInfoPeripheralHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw Common::UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoPeripheral::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoPeripheral given");
+        throw Common::UnknownException("NULL pointer to SystemInfoPeripheral given");
+    }
+
+    SystemInfoPeripheralPtr peripheral =
+            std::dynamic_pointer_cast<SystemInfoPeripheral>(native);
+
+    if (!peripheral) {
+        LOGE("Invalid pointer to SystemInfoPeripheral given");
+        throw Common::UnknownException("Invalid pointer to SystemInfoPeripheral given");
+    }
+
+    SystemInfoPeripheralHolder* priv = new(std::nothrow) SystemInfoPeripheralHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw Common::UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = peripheral;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoPeripheral::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoPeripheral::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoPeripheralHolder* priv =
+            static_cast<SystemInfoPeripheralHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoPeripheral::getIsVideoOutputOn(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoPeripheralPtr priv = getPrivateObject(context, object);
+
+        return Common::JSUtil::toJSValueRef(context, priv->isVideoOutputOn());
+    }
+    catch (const Common::BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getIsVideoOutputOn fails");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoPeripheral.h b/src/Systeminfo/JSSystemInfoPeripheral.h
new file mode 100755 (executable)
index 0000000..5ec9348
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_PERIPHERAL_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_PERIPHERAL_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoPeripheral.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoPeripheral {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoPeripheralPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoPeripheralPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getIsVideoOutputOn(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_PERIPHERAL_H__
diff --git a/src/Systeminfo/JSSystemInfoProperty.cpp b/src/Systeminfo/JSSystemInfoProperty.cpp
new file mode 100755 (executable)
index 0000000..656f0e2
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+
+#include <Export.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_PROPERTY = "SystemInfoProperty";
+}
+
+JSClassDefinition JSSystemInfoProperty::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_PROPERTY, //class name
+        NULL, // parent class
+        NULL, //m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+const JSClassDefinition* JSSystemInfoProperty::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoProperty::m_jsClassRef =
+        JSClassCreate(JSSystemInfoProperty::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoProperty::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSSystemInfoProperty::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoProperty::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoProperty.h b/src/Systeminfo/JSSystemInfoProperty.h
new file mode 100755 (executable)
index 0000000..5dbb86f
--- /dev/null
@@ -0,0 +1,54 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_PROPERTY_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_PROPERTY_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoProperty {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+};
+
+} // SystemInfo
+} // DeviceAPI
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_PROPERTY_H__
diff --git a/src/Systeminfo/JSSystemInfoSIM.cpp b/src/Systeminfo/JSSystemInfoSIM.cpp
new file mode 100755 (executable)
index 0000000..9b65568
--- /dev/null
@@ -0,0 +1,387 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoSIM.h"
+
+#include "plugin_config.h"
+#include <SecurityExceptions.h>
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+using namespace WrtDeviceApis::Commons;
+
+struct SystemInfoSIMHolder {
+    SystemInfoSIMPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_SIM = "SystemInfoSIM";
+const char* SYSTEMINFO_SIM_STATE = "state";
+const char* SYSTEMINFO_SIM_OPERATOR_NAME = "operatorName";
+const char* SYSTEMINFO_SIM_MSISDN = "msisdn";
+const char* SYSTEMINFO_SIM_ICCID = "iccid";
+const char* SYSTEMINFO_SIM_MCC = "mcc";
+const char* SYSTEMINFO_SIM_MNC = "mnc";
+const char* SYSTEMINFO_SIM_MSIN = "msin";
+const char* SYSTEMINFO_SIM_SPN = "spn";
+}
+
+JSClassDefinition JSSystemInfoSIM::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_SIM, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoSIM::m_property[] = {
+        { SYSTEMINFO_SIM_STATE, getState, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_SIM_OPERATOR_NAME, getOperatorName, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_SIM_MSISDN, getMsisdn, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_SIM_ICCID, getIccid, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_SIM_MCC, getMcc, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_SIM_MNC, getMnc, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_SIM_SPN, getSpn, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_SIM_MSIN, getMsin, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoSIM::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoSIM::m_jsClassRef =
+        JSClassCreate(JSSystemInfoSIM::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoSIM::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoSIMPtr JSSystemInfoSIM::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoSIMHolder* priv =
+            static_cast<SystemInfoSIMHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoSIM::setPrivateObject(JSObjectRef object,
+        SystemInfoSIMPtr native)
+{
+    SystemInfoSIMHolder* priv =
+            static_cast<SystemInfoSIMHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoSIM::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoSIM given");
+        throw UnknownException("NULL pointer to SystemInfoSIM given");
+    }
+
+    SystemInfoSIMPtr sim = std::dynamic_pointer_cast<SystemInfoSIM>(
+            native);
+
+    if (!sim) {
+        LOGE("Invalid pointer to SystemInfoSIM given");
+        throw UnknownException("Invalid pointer to SystemInfoSIM given");
+    }
+
+    SystemInfoSIMHolder* priv = new(std::nothrow) SystemInfoSIMHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = sim;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoSIM::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoSIM::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoSIMHolder* priv =
+            static_cast<SystemInfoSIMHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoSIM::getState(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ACE_ACCESS_CHECK(
+            AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_PROPERTY_SIM_VALUE);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+        );
+        SystemInfoSIMPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getState());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getState failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoSIM::getOperatorName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ACE_ACCESS_CHECK(
+            AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_PROPERTY_SIM_VALUE);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+        );
+        SystemInfoSIMPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getOperatorName());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getOperatorName failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoSIM::getMsisdn(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ACE_ACCESS_CHECK(
+            AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_PROPERTY_PARTNER_VALUE);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+        );
+        SystemInfoSIMPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getMsisdn());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMsisdn failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoSIM::getIccid(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ACE_ACCESS_CHECK(
+            AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_PROPERTY_SIM_VALUE);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+        );
+        SystemInfoSIMPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getIccid());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getIccid failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoSIM::getMcc(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ACE_ACCESS_CHECK(
+            AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_PROPERTY_SIM_VALUE);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+        );
+        SystemInfoSIMPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context,
+                static_cast<unsigned long>(priv->getMcc()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMcc failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoSIM::getMnc(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ACE_ACCESS_CHECK(
+            AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_PROPERTY_SIM_VALUE);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+        );
+        SystemInfoSIMPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context,
+                static_cast<unsigned long>(priv->getMnc()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMnc failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoSIM::getMsin(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ACE_ACCESS_CHECK(
+            AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_PROPERTY_PARTNER_VALUE);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+        );
+        SystemInfoSIMPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getMsin());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMsin failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoSIM::getSpn(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        ACE_ACCESS_CHECK(
+            AceSecurityStatus status = SYSTEMINFO_CHECK_ACCESS(
+                    SYSTEMINFO_FUNCTION_API_GET_PROPERTY_SIM_VALUE);
+            TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+        );
+        SystemInfoSIMPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getSpn());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getSpn failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoSIM.h b/src/Systeminfo/JSSystemInfoSIM.h
new file mode 100755 (executable)
index 0000000..2f2cfb5
--- /dev/null
@@ -0,0 +1,112 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_SIM_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_SIM_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoSIM.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoSIM {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoSIMPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoSIMPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getState(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getOperatorName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getMsisdn(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getIccid(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getMcc(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getMnc(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getMsin(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getSpn(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_SIM_H__
diff --git a/src/Systeminfo/JSSystemInfoStorage.cpp b/src/Systeminfo/JSSystemInfoStorage.cpp
new file mode 100755 (executable)
index 0000000..84b7532
--- /dev/null
@@ -0,0 +1,183 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoStorage.h"
+#include "JSSystemInfoStorageUnit.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+struct SystemInfoStorageHolder {
+    SystemInfoStoragePtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_STORAGE = "SystemInfoStorage";
+
+const char* SYSTEMINFO_STORAGE_UNITS = "units";
+}
+
+JSClassDefinition JSSystemInfoStorage::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_STORAGE, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoStorage::m_property[] = {
+        { SYSTEMINFO_STORAGE_UNITS, getUnits, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoStorage::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoStorage::m_jsClassRef =
+        JSClassCreate(JSSystemInfoStorage::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoStorage::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoStoragePtr JSSystemInfoStorage::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoStorageHolder* priv =
+            static_cast<SystemInfoStorageHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoStorage::setPrivateObject(JSObjectRef object,
+        SystemInfoStoragePtr native)
+{
+    SystemInfoStorageHolder* priv =
+            static_cast<SystemInfoStorageHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoStorage::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoStorage given");
+        throw UnknownException("NULL pointer to SystemInfoStorage given");
+    }
+
+    SystemInfoStoragePtr storage = std::dynamic_pointer_cast<SystemInfoStorage>(
+            native);
+
+    if (!storage) {
+        LOGE("Invalid pointer to SystemInfoStorage given");
+        throw UnknownException("Invalid pointer to SystemInfoStorage given");
+    }
+
+    SystemInfoStorageHolder* priv = new(std::nothrow) SystemInfoStorageHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = storage;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoStorage::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoStorage::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoStorageHolder* priv =
+            static_cast<SystemInfoStorageHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoStorage::getUnits(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoStoragePtr priv = getPrivateObject(context, object);
+        return JSSystemInfoStorageUnit::unitsArrayToJSObjectArray(context, priv->getUnits());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getUnits failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoStorage.h b/src/Systeminfo/JSSystemInfoStorage.h
new file mode 100755 (executable)
index 0000000..43c0509
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_STORAGE_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_STORAGE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoStorage.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoStorage {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoStoragePtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoStoragePtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getUnits(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_STORAGE_H__
diff --git a/src/Systeminfo/JSSystemInfoStorageUnit.cpp b/src/Systeminfo/JSSystemInfoStorageUnit.cpp
new file mode 100755 (executable)
index 0000000..541ac06
--- /dev/null
@@ -0,0 +1,269 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoStorageUnit.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+struct SystemInfoStorageUnitHolder {
+    SystemInfoStorageUnitPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_STORAGE_UNIT = "SystemInfoStorageUnit";
+
+const char* SYSTEMINFO_STORAGE_UNIT_TYPE = "type";
+const char* SYSTEMINFO_STORAGE_UNIT_CAPACITY = "capacity";
+const char* SYSTEMINFO_STORAGE_UNIT_AVAILABLE_CAPACITY = "availableCapacity";
+const char* SYSTEMINFO_STORAGE_UNIT_IS_REMOVABLE = "isRemovable";
+const char* SYSTEMINFO_STORAGE_UNIT_IS_REMOVEABLE = "isRemoveable";
+}
+
+JSClassDefinition JSSystemInfoStorageUnit::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_STORAGE_UNIT, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoStorageUnit::m_property[] = {
+        { SYSTEMINFO_STORAGE_UNIT_TYPE, getType, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_STORAGE_UNIT_CAPACITY, getCapacity, NULL,
+                 kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_STORAGE_UNIT_AVAILABLE_CAPACITY, getAvailableCapacity, NULL,
+                  kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_STORAGE_UNIT_IS_REMOVABLE, isRemovable, NULL,
+                  kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_STORAGE_UNIT_IS_REMOVEABLE, isRemovable, NULL,
+                  kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoStorageUnit::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoStorageUnit::m_jsClassRef =
+        JSClassCreate(JSSystemInfoStorageUnit::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoStorageUnit::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoStorageUnitPtr JSSystemInfoStorageUnit::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoStorageUnitHolder* priv =
+            static_cast<SystemInfoStorageUnitHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoStorageUnit::setPrivateObject(JSObjectRef object,
+        SystemInfoStorageUnitPtr native)
+{
+    SystemInfoStorageUnitHolder* priv =
+            static_cast<SystemInfoStorageUnitHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoStorageUnit::makeJSObject(JSContextRef context,
+        SystemInfoStorageUnitPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoStorageUnit given");
+        throw UnknownException("NULL pointer to SystemInfoStorageUnit given");
+    }
+
+    SystemInfoStorageUnitHolder* priv = new(std::nothrow) SystemInfoStorageUnitHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoStorageUnit::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoStorageUnit::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoStorageUnitHolder* priv =
+            static_cast<SystemInfoStorageUnitHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef JSSystemInfoStorageUnit::unitsArrayToJSObjectArray(JSContextRef context,
+            const UnitsPtrVector& units) {
+    LOGD("Entered");
+    size_t count = units.size();
+
+    JSObjectRef array[count];
+    for (size_t i = 0; i < count; ++i) {
+        array[i] = JSSystemInfoStorageUnit::makeJSObject(context, units[i]);
+    }
+    JSObjectRef result = JSObjectMakeArray(context, count,
+            count > 0 ? array : NULL, NULL);
+    if (!result) {
+        LOGW("Failed to create SystemInfoStorageUnit array");
+        throw UnknownException("SystemInfoStorageUnit array is null");
+    }
+    LOGD("return");
+    return result;
+}
+
+JSValueRef JSSystemInfoStorageUnit::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoStorageUnitPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, SystemInfoStorageUnit::typeToString(priv->getType()));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getType failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoStorageUnit::getCapacity(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoStorageUnitPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getCapacity());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getCapacity failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoStorageUnit::getAvailableCapacity(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoStorageUnitPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getAvailableCapacity());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getAvailableCapacity failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoStorageUnit::isRemovable(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoStorageUnitPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->isRemovable());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("isRemovable failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoStorageUnit.h b/src/Systeminfo/JSSystemInfoStorageUnit.h
new file mode 100755 (executable)
index 0000000..5e7639e
--- /dev/null
@@ -0,0 +1,98 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_STORAGE_UNIT_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_STORAGE_UNIT_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoStorageUnit.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoStorageUnit {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoStorageUnitPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoStorageUnitPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoStorageUnitPtr native);
+
+    /**
+     * Function converts units array into JSArray
+     */
+    static JSObjectRef unitsArrayToJSObjectArray(JSContextRef context,
+            const UnitsPtrVector& units);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getCapacity(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getAvailableCapacity(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef isRemovable(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_STORAGE_UNIT_H__
diff --git a/src/Systeminfo/JSSystemInfoWifiNetwork.cpp b/src/Systeminfo/JSSystemInfoWifiNetwork.cpp
new file mode 100755 (executable)
index 0000000..5a92a13
--- /dev/null
@@ -0,0 +1,303 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSystemInfoProperty.h"
+#include "JSSystemInfoWifiNetwork.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace DeviceAPI::Common;
+
+struct SystemInfoWifiNetworkHolder {
+    SystemInfoWifiNetworkPtr ptr;
+};
+
+namespace {
+const char* SYSTEMINFO_SYSTEMINFO_WIFI_NETWORK = "SystemInfoWifiNetwork";
+
+const char* SYSTEMINFO_WIFI_NETWORK_STATUS = "status";
+const char* SYSTEMINFO_WIFI_NETWORK_SSID = "ssid";
+const char* SYSTEMINFO_WIFI_NETWORK_IP_ADDRESS = "ipAddress";
+const char* SYSTEMINFO_WIFI_NETWORK_IPV6_ADDRESS = "ipv6Address";
+const char* SYSTEMINFO_WIFI_NETWORK_MAC_ADDRESS = "macAddress";
+const char* SYSTEMINFO_WIFI_NETWORK_SIGNAL_STRENGTH = "signalStrength";
+}
+
+JSClassDefinition JSSystemInfoWifiNetwork::m_classInfo = {
+        0, // current (and only) version is 0
+        kJSClassAttributeNone, //attributes
+        SYSTEMINFO_SYSTEMINFO_WIFI_NETWORK, //class name
+        JSSystemInfoProperty::getClassRef(), // parent class
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL  //convertToType,
+};
+
+JSStaticValue JSSystemInfoWifiNetwork::m_property[] = {
+        { SYSTEMINFO_WIFI_NETWORK_STATUS, getStatus, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_WIFI_NETWORK_SSID, getSsid, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_WIFI_NETWORK_IP_ADDRESS, getIpAddress, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_WIFI_NETWORK_IPV6_ADDRESS, getIpv6Address, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_WIFI_NETWORK_MAC_ADDRESS, getMacAddress, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { SYSTEMINFO_WIFI_NETWORK_SIGNAL_STRENGTH, getSignalStrength, NULL,
+                kJSPropertyAttributeDontDelete | kJSPropertyAttributeReadOnly },
+        { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSystemInfoWifiNetwork::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSystemInfoWifiNetwork::m_jsClassRef =
+        JSClassCreate(JSSystemInfoWifiNetwork::getClassInfo());
+
+JSClassRef DLL_EXPORT JSSystemInfoWifiNetwork::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SystemInfoWifiNetworkPtr JSSystemInfoWifiNetwork::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SystemInfoWifiNetworkHolder* priv =
+            static_cast<SystemInfoWifiNetworkHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSystemInfoWifiNetwork::setPrivateObject(JSObjectRef object,
+        SystemInfoWifiNetworkPtr native)
+{
+    SystemInfoWifiNetworkHolder* priv =
+            static_cast<SystemInfoWifiNetworkHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSystemInfoWifiNetwork::makeJSObject(JSContextRef context,
+        SystemInfoPropertyPtr native)
+{
+    if (!native) {
+        LOGE("NULL pointer to SystemInfoWifiNetwork given");
+        throw UnknownException("NULL pointer to SystemInfoWifiNetwork given");
+    }
+
+    SystemInfoWifiNetworkPtr wifi =
+            std::dynamic_pointer_cast<SystemInfoWifiNetwork>(native);
+
+    if (!wifi) {
+        LOGE("Invalid pointer to SystemInfoWifiNetwork given");
+        throw UnknownException("Invalid pointer to SystemInfoWifiNetwork given");
+    }
+
+    SystemInfoWifiNetworkHolder* priv = new(std::nothrow) SystemInfoWifiNetworkHolder();
+    if (!priv) {
+        LOGE("Failed to allocate memory");
+        throw UnknownException("Failed to allocate memory");
+    }
+    priv->ptr = wifi;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSystemInfoWifiNetwork::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSystemInfoWifiNetwork::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SystemInfoWifiNetworkHolder* priv =
+            static_cast<SystemInfoWifiNetworkHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSValueRef JSSystemInfoWifiNetwork::getStatus(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoWifiNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getStatus());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getStatus failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoWifiNetwork::getSsid(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoWifiNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getSsid());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getSsid failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoWifiNetwork::getIpAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoWifiNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getIpAddress());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getIpAddress failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoWifiNetwork::getIpv6Address(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoWifiNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getIpv6Address());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getIpv6Address failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoWifiNetwork::getMacAddress(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoWifiNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getMacAddress());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getMacAddress failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSSystemInfoWifiNetwork::getSignalStrength(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef property_name,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SystemInfoWifiNetworkPtr priv = getPrivateObject(context, object);
+
+        return JSUtil::toJSValueRef(context, priv->getSignalStrength());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Exception caught: name: %s, msg: %s",
+                err.getName().c_str(), err.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("getSignalStrength failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/JSSystemInfoWifiNetwork.h b/src/Systeminfo/JSSystemInfoWifiNetwork.h
new file mode 100755 (executable)
index 0000000..c0e821b
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_WIFI_NETWORK_H__
+#define __TIZEN_SYSTEMINFO_JS_SYSTEMINFO_WIFI_NETWORK_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SystemInfoWifiNetwork.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class JSSystemInfoWifiNetwork {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SystemInfoWifiNetworkPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SystemInfoWifiNetworkPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SystemInfoPropertyPtr native);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values
+     * for the static properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getStatus(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getSsid(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getIpAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getIpv6Address(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getMacAddress(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+
+    static JSValueRef getSignalStrength(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef property_name,
+            JSValueRef* exception);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_JS_SYSTEMINFO_WIFI_NETWORK_H__
diff --git a/src/Systeminfo/SystemInfo.cpp b/src/Systeminfo/SystemInfo.cpp
new file mode 100755 (executable)
index 0000000..df7f8e6
--- /dev/null
@@ -0,0 +1,1729 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SystemInfo.h"
+#include "SystemInfoDeviceCapability.h"
+#include "SystemInfoProperty.h"
+#include "SystemInfoUtil.h"
+#include "JSSystemInfoBattery.h"
+#include "JSSystemInfoLocale.h"
+#include "JSSystemInfoStorage.h"
+#include "JSSystemInfoDisplay.h"
+#include "JSSystemInfoDeviceOrientation.h"
+#include "JSSystemInfoCpu.h"
+#include "JSSystemInfoBuild.h"
+#include "JSSystemInfoPeripheral.h"
+#include "JSSystemInfoNetwork.h"
+#include "JSSystemInfoMemory.h"
+
+#ifdef FEATURE_OPTIONAL_WI_FI
+#include "JSSystemInfoWifiNetwork.h"
+#endif
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+#include "JSSystemInfoCellularNetwork.h"
+#include "JSSystemInfoSIM.h"
+#endif
+
+#include <algorithm>
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+#include <device.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+const double PROPERTY_WATCHER_TIME = 1;
+const int MEMORY_TO_BYTE = 1024;
+const int BASE_GATHERING_INTERVAL = 100;
+
+}
+
+CpuInfo SystemInfo::m_cpu_info;
+
+std::mutex SystemInfo::m_cpu_info_lock;
+
+using namespace DeviceAPI::Common;
+
+SystemInfo::SystemInfo() :
+                m_storage_timer(NULL),
+                m_cpu_timer(NULL),
+                m_cpu_last_load(0),
+                m_connection_handle(NULL),
+                m_current_id(0),
+                m_sensor_handle(NULL)
+{
+    LOGD("Entered");
+
+    // create thread pool with max threads = 1 to make API calls async but
+    // only one call at time
+    m_pool = g_thread_pool_new(getPropertyValueThread, NULL, 1, true, NULL);
+
+    m_sensor_handle = SystemInfoDeviceOrientation::connectSensor();
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+    LOGD("Entered");
+    char **cp_list = NULL;
+    unsigned int modem_num = 0;
+    *m_tapi_handle = NULL;
+
+    cp_list = tel_get_cp_name_list();
+
+    if (cp_list != NULL) {
+        while (cp_list[modem_num]) {
+            LOGD("cp_name = %d", cp_list[modem_num]);
+            m_tapi_handle[modem_num] = tel_init(cp_list[modem_num]);
+            if (m_tapi_handle[modem_num] == NULL) {
+                LOGE("Failed to connect with tapi, handle is null");
+                g_strfreev(cp_list);
+            }
+            modem_num++;
+        }
+    } else {
+        LOGE("Failed to get cp list");
+    }
+#endif
+}
+
+SystemInfo::~SystemInfo()
+{
+    LOGD("Entered");
+
+    std::for_each(m_watcher_map.begin(), m_watcher_map.end(),
+            [] (const std::pair<unsigned long, Ecore_Timer*>& watcher) {
+                Ecore_Timer* timer = watcher.second;
+                if (timer) {
+                    ecore_timer_del(timer);
+                    timer = NULL;
+                }
+            });
+
+    if (!m_battery_callbacks.empty()) {
+        unregisterVconfCallback(VCONFKEY_SYSMAN_BATTERY_CAPACITY, SystemInfo::onBatteryChanged);
+        unregisterVconfCallback(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, SystemInfo::onBatteryChanged);
+    }
+
+    if (!m_peripheral_callbacks.empty()) {
+        unregisterVconfCallback(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS,
+                SystemInfo::onPeripheralChanged);
+        unregisterVconfCallback(VCONFKEY_SYSMAN_HDMI, SystemInfo::onPeripheralChanged);
+        unregisterVconfCallback(VCONFKEY_POPSYNC_ACTIVATED_KEY, SystemInfo::onPeripheralChanged);
+    }
+
+    if (!m_device_orientation_callbacks.empty()) {
+        unregisterVconfCallback(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL,
+                SystemInfo::onDeviceAutoRotationChanged);
+        sensord_unregister_event(m_sensor_handle, AUTO_ROTATION_EVENT_CHANGE_STATE);
+    }
+
+    SystemInfoDeviceOrientation::disconnectSensor(m_sensor_handle);
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+    if (!m_cellular_network_callbacks.empty() || !m_wifi_network_callbacks.empty()) {
+        //wifi and cellular has common ip callback
+        unregisterIpChangeCallback();
+    }
+
+    if (!m_cellular_network_callbacks.empty()) {
+        unregisterVconfCallback(VCONFKEY_TELEPHONY_FLIGHT_MODE, onConnectionNetworkParamChanged);
+        unregisterVconfCallback(VCONFKEY_TELEPHONY_CELLID, onConnectionNetworkParamChanged);
+        unregisterVconfCallback(VCONFKEY_TELEPHONY_LAC, onConnectionNetworkParamChanged);
+        unregisterVconfCallback(VCONFKEY_TELEPHONY_SVC_ROAM, onConnectionNetworkParamChanged);
+    }
+#endif
+    if (!m_locale_callbacks.empty()) {
+        if (SYSTEM_SETTINGS_ERROR_NONE
+                != system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE)) {
+            LOGE("unregistration of language change callback failed");
+        }
+        if (SYSTEM_SETTINGS_ERROR_NONE
+                != system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY)) {
+            LOGE("unregistration of country change callback failed");
+        }
+    }
+
+    if (!m_storage_callbacks.empty()) {
+        unregisterVconfCallback(VCONFKEY_SYSMAN_MMC_STATUS, SystemInfo::mmcStatusChanged);
+    }
+
+    if (!m_memory_callbacks.empty()) {
+        unregisterVconfCallback(VCONFKEY_SYSMAN_LOW_MEMORY, SystemInfo::onMemoryChanged);
+    }
+
+    stopAndDestroyTimer(&m_cpu_timer, std::string("Cpu"));
+    stopAndDestroyTimer(&m_storage_timer, std::string("Storage"));
+
+    //finish only current task and wait for thread to stop
+    g_thread_pool_free(m_pool, true, true);
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+    unsigned int i = 0;
+    while (m_tapi_handle[i]) {
+        tel_deinit(m_tapi_handle[i]);
+        i++;
+    }
+#endif
+
+    for (auto it = m_processing_properties.begin(); it != m_processing_properties.end(); ++it) {
+        delete *it;
+    }
+    m_processing_properties.clear();
+
+#ifdef FEATURE_OPTIONAL_WI_FI
+    if (NULL != m_connection_handle) {
+        connection_destroy(m_connection_handle);
+    }
+#endif
+}
+
+SystemInfo& SystemInfo::getInstance()
+{
+    static SystemInfo instance;
+    return instance;
+}
+
+long long SystemInfo::getTotalMemory()
+{
+    LOGD("Entered");
+
+    unsigned int value = 0;
+
+    int ret = device_memory_get_total(&value);
+    if (ret != DEVICE_ERROR_NONE) {
+        std::string log_msg = "Failed to get total memory: ";
+        LOGE("%s %d", log_msg.c_str(), ret);
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+
+    return static_cast<long long>(value * MEMORY_TO_BYTE);
+}
+
+long long SystemInfo::getAvailableMemory()
+{
+    LOGD("Entered");
+
+    unsigned int value = 0;
+
+    int ret = device_memory_get_available(&value);
+    if (ret != DEVICE_ERROR_NONE) {
+        std::string log_msg = "Failed to get total memory: ";
+        LOGE("%s %d", log_msg.c_str(), ret);
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+
+    return static_cast<long long>(value * MEMORY_TO_BYTE);
+}
+
+SystemInfoDeviceCapabilityPtr SystemInfo::getCapabilities()
+{
+    SystemInfoDeviceCapabilityPtr capability(new SystemInfoDeviceCapability());
+    return capability;
+}
+
+unsigned long SystemInfo::getCount(SystemInfoPropertyId propertyId)
+{
+    LOGD("Entered");
+
+    unsigned long count = 0;
+
+    switch (propertyId) {
+        case SystemInfoPropertyId::BATTERY:
+        case SystemInfoPropertyId::CPU:
+        case SystemInfoPropertyId::STORAGE:
+        case SystemInfoPropertyId::DISPLAY:
+        case SystemInfoPropertyId::DEVICE_ORIENTATION:
+        case SystemInfoPropertyId::BUILD:
+        case SystemInfoPropertyId::LOCALE:
+        case SystemInfoPropertyId::NETWORK:
+        case SystemInfoPropertyId::PERIPHERAL:
+        case SystemInfoPropertyId::MEMORY:
+            count = DEFAULT_PROPERTY_COUNT;
+            break;
+#ifdef FEATURE_OPTIONAL_WI_FI
+        case SystemInfoPropertyId::WIFI_NETWORK:
+            count = DEFAULT_PROPERTY_COUNT;
+            break;
+#endif
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+        case SystemInfoPropertyId::CELLULAR_NETWORK:
+            count = DEFAULT_PROPERTY_COUNT;
+            break;
+        case SystemInfoPropertyId::SIM:
+            count = TAPI_HANDLE_MAX;
+#endif
+            break;
+        default:
+            std::string log_msg = "Not supported property: " + std::to_string(propertyId);
+    }
+    return count;
+}
+
+gboolean SystemInfo::getPropertyValueCallback(void *data)
+{
+    LOGD("Entered");
+
+    auto holder = static_cast<PropertyCallbackDataHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return false;
+    }
+    auto callback = holder->ptr;
+    if (!callback) {
+        LOGE("callback is null");
+        delete holder;
+        holder = NULL;
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        delete holder;
+        holder = NULL;
+        return false;
+    }
+
+    try {
+        JSObjectRef js_property = NULL;
+        JSObjectRef js_array = JSCreateArrayObject(context, 0, NULL);
+        JSObjectRef js_result = NULL;
+        bool isArrayCallback = callback->isArrayCallback();
+
+        if (js_array == NULL) {
+            std::string log_msg = "Failed to create JSPropertyValueArray";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException(0, log_msg);
+        }
+
+        std::vector<SystemInfoPropertyHolder*> properties = callback->getPropertyArray();
+        LOGD("%d objects exist", properties.size());
+        LOGD("%d property", callback->getPropertyId());
+
+        try {
+            for (size_t i = 0; i < properties.size(); i++) {
+                SystemInfoPropertyPtr property = properties[i]->ptr;
+                LOGD("Entered");
+                if (property == NULL) {
+                    std::string log_msg = "property is null";
+                    LOGE("%s", log_msg.c_str());
+                    SystemInfoUtil::throwSystemInfoException(0, log_msg);
+                }
+
+                switch (callback->getPropertyId()) {
+                    case SystemInfoPropertyId::BATTERY:
+                        js_property = JSSystemInfoBattery::makeJSObject(context, property);
+                        break;
+                    case SystemInfoPropertyId::CPU:
+                        js_property = JSSystemInfoCpu::makeJSObject(context, property);
+                        break;
+                    case SystemInfoPropertyId::STORAGE:
+                        js_property = JSSystemInfoStorage::makeJSObject(context, property);
+                        break;
+                    case SystemInfoPropertyId::DISPLAY:
+                        js_property = JSSystemInfoDisplay::makeJSObject(context, property);
+                        break;
+                    case SystemInfoPropertyId::DEVICE_ORIENTATION:
+                        js_property = JSSystemInfoDeviceOrientation::makeJSObject(context,
+                                property);
+                        break;
+                    case SystemInfoPropertyId::BUILD:
+                        js_property = JSSystemInfoBuild::makeJSObject(context, property);
+                        break;
+                    case SystemInfoPropertyId::LOCALE:
+                        js_property = JSSystemInfoLocale::makeJSObject(context, property);
+                        break;
+                    case SystemInfoPropertyId::NETWORK:
+                        js_property = JSSystemInfoNetwork::makeJSObject(context, property);
+                        break;
+#ifdef FEATURE_OPTIONAL_WI_FI
+                    case SystemInfoPropertyId::WIFI_NETWORK:
+                        js_property = JSSystemInfoWifiNetwork::makeJSObject(context, property);
+                        break;
+#endif
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+                    case SystemInfoPropertyId::CELLULAR_NETWORK:
+                        js_property = JSSystemInfoCellularNetwork::makeJSObject(context, property);
+                        break;
+                    case SystemInfoPropertyId::SIM:
+                        js_property = JSSystemInfoSIM::makeJSObject(context, property);
+                        break;
+#endif
+                    case SystemInfoPropertyId::PERIPHERAL:
+                        js_property = JSSystemInfoPeripheral::makeJSObject(context, property);
+                        break;
+                    case SystemInfoPropertyId::MEMORY:
+                        js_property = JSSystemInfoMemory::makeJSObject(context, property);
+                        break;
+                    default:
+                        std::string log_msg = "Not supported property";
+                        LOGE("%s", log_msg.c_str());
+                        SystemInfoUtil::throwSystemInfoException<NotSupportedException>(0, log_msg);
+                }
+
+                if (!isArrayCallback) {
+                    break;
+                }
+
+                if (!JSSetArrayElement(context, js_array, i, js_property)) {
+                    std::string log_msg = "Failed to add property into array";
+                    LOGE("%s", log_msg.c_str());
+                    SystemInfoUtil::throwSystemInfoException(0, log_msg);
+                }
+            }
+
+            if (isArrayCallback) {
+                js_result = js_array;
+            } else {
+                js_result = js_property;
+            }
+
+        } catch (const BasePlatformException &err) {
+            LOGE("getPropertyValueCallback fails, %s: %s", err.getName().c_str(),
+                    err.getMessage().c_str());
+            JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context, err);
+            callback->callErrorCallback(error);
+        } catch (...) {
+            LOGE("getPropertyValueCallback fails");
+            JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "UnknownError");
+            callback->callErrorCallback(error);
+        }
+
+        if (js_result != NULL) {
+            callback->callSuccessCallback(js_result);
+        } else {
+            LOGE("Invalid callback data");
+            JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context,
+                    JSWebAPIErrorFactory::UNKNOWN_ERROR, "property object creation failed");
+            callback->callErrorCallback(error);
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("getPropertyValueCallback fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("getPropertyValueCallback fails");
+    }
+
+    delete holder;
+    holder = NULL;
+
+    return false;
+}
+
+void SystemInfo::notifyGetPropertyValueReady()
+{
+    LOGD("Entered");
+    std::lock_guard < std::mutex > lock(m_processing_properties_lock);
+    for (auto it = m_processing_properties.begin(); it != m_processing_properties.end(); ++it) {
+        if ((*it)->ptr->isPropertyReady()) {
+            if (!g_idle_add(getPropertyValueCallback, *it)) {
+                LOGE("g_idle_add fails");
+                delete *it;
+            }
+            m_processing_properties.erase(it);
+            break;
+        }
+    }
+}
+
+void SystemInfo::addProcessingProperty(PropertyCallbackDataHolder* holder)
+{
+    std::lock_guard < std::mutex > lock(m_processing_properties_lock);
+    m_processing_properties.push_back(holder);
+}
+
+#ifdef FEATURE_OPTIONAL_WI_FI
+void SystemInfo::registerIpChangeCallback()
+{
+    LOGD("Registering connection callback");
+    connection_h handle = getConnectionHandle();
+    int ret = connection_set_ip_address_changed_cb(handle, onConnectionIpAddressChanged, NULL);
+    if (CONNECTION_ERROR_NONE != ret) {
+        std::string log_msg = "Failed to register ip change callback";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+        SystemInfoUtil::throwConnectionException(ret, log_msg);
+    }
+}
+
+void SystemInfo::unregisterIpChangeCallback()
+{
+    LOGD("Unregistering connection callback");
+    connection_h handle = getConnectionHandle();
+
+    int ret = connection_unset_ip_address_changed_cb(handle);
+    if (CONNECTION_ERROR_NONE != ret) {
+        std::string log_msg = "Failed to unregister ip change callback";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+        SystemInfoUtil::throwConnectionException(ret, log_msg);
+    }
+}
+#else
+void SystemInfo::registerIpChangeCallback()
+{
+    LOGD("Registering connection callback");
+    //Not supported
+}
+
+void SystemInfo::unregisterIpChangeCallback()
+{
+    LOGD("Unregistering connection callback");
+    //Not supported
+}
+#endif
+connection_h SystemInfo::getConnectionHandle()
+{
+    if (NULL == m_connection_handle) {
+        int ret = connection_create(&m_connection_handle);
+        if (CONNECTION_ERROR_NONE != ret) {
+            std::string log_msg = "Failed to create connection";
+            LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            SystemInfoUtil::throwConnectionException(ret, log_msg);
+        }
+    }
+    return m_connection_handle;
+}
+
+void SystemInfo::onConnectionIpAddressChanged(const char* /*ipv4_address*/,
+        const char* /*ipv6_address*/, void* /*user_data*/)
+{
+    LOGD("Entered");
+    SystemInfo::getInstance().broadcastCellularNetworkChanged();
+    SystemInfo::getInstance().broadcastWifiNetworkChanged();
+}
+
+void SystemInfo::onConnectionNetworkParamChanged(keynode_t *node, void *user_data)
+{
+    LOGD("Entered");
+    SystemInfo::getInstance().broadcastCellularNetworkChanged();
+}
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+void SystemInfo::broadcastCellularNetworkChanged()
+{
+    try {
+        SystemInfoPropertyPtr property(new SystemInfoCellularNetwork(m_tapi_handle));
+
+        PVCLmap::iterator itr = m_cellular_network_callbacks.begin();
+
+        while (itr != m_cellular_network_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+            callback->setNativeProperty(property);
+
+            PropertyCallbackDataHolder* holder = new (std::nothrow) PropertyCallbackDataHolder();
+            if (!holder) {
+                std::string log_msg = "Failed to allocate memory";
+                LOGE("%s", log_msg.c_str());
+                SystemInfoUtil::throwSystemInfoException(0, log_msg);
+            }
+            holder->ptr = callback;
+
+            guint id = g_idle_add(getPropertyValueCallback, holder);
+            if (!id) {
+                LOGE("g_idle_add fails");
+                delete holder;
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("broadcastCellularNetworkChanged fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("broadcastCellularNetworkChanged fails");
+    }
+}
+#else
+void SystemInfo::broadcastCellularNetworkChanged()
+{
+    LOGD("Entered");
+    //Not supported
+}
+#endif
+
+#ifdef FEATURE_OPTIONAL_WI_FI
+void SystemInfo::broadcastWifiNetworkChanged()
+{
+    try {
+        SystemInfoPropertyPtr property(new SystemInfoWifiNetwork());
+
+        PVCLmap::iterator itr = m_wifi_network_callbacks.begin();
+
+        while (itr != m_wifi_network_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+            callback->setNativeProperty(property);
+
+            PropertyCallbackDataHolder* holder = new (std::nothrow) PropertyCallbackDataHolder();
+            if (!holder) {
+                std::string log_msg = "Failed to allocate memory";
+                LOGE("%s", log_msg.c_str());
+                SystemInfoUtil::throwSystemInfoException(0, log_msg);
+            }
+            holder->ptr = callback;
+
+            guint id = g_idle_add(getPropertyValueCallback, holder);
+            if (!id) {
+                LOGE("g_idle_add failed");
+                delete holder;
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("broadcastWifiNetworkChanged failed, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("broadcastWifiNetworkChanged failed");
+    }
+}
+#else
+void SystemInfo::broadcastWifiNetworkChanged()
+{
+    LOGD("Entered");
+    //Not supported
+}
+#endif
+
+void SystemInfo::getPropertyValueThread(gpointer data, gpointer user_data)
+{
+    LOGD("Entered");
+
+    auto holder = static_cast<PropertyCallbackDataHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return;
+    }
+    auto callback = holder->ptr;
+    if (!callback) {
+        LOGE("callback is null");
+        delete holder;
+        holder = NULL;
+        return;
+    }
+
+    bool add_to_idle = false;
+    int modemNum = 0;
+
+    try {
+        SystemInfoPropertyPtr property;
+
+        switch (callback->getPropertyId()) {
+            case SystemInfoPropertyId::BATTERY:
+                property.reset(new SystemInfoBattery());
+                break;
+            case SystemInfoPropertyId::CPU:
+                property = createSystemInfoCpu();
+                break;
+            case SystemInfoPropertyId::STORAGE:
+                property.reset(new SystemInfoStorage());
+                break;
+            case SystemInfoPropertyId::DISPLAY:
+                property.reset(new SystemInfoDisplay());
+                break;
+            case SystemInfoPropertyId::DEVICE_ORIENTATION:
+                property.reset(new SystemInfoDeviceOrientation());
+                break;
+            case SystemInfoPropertyId::BUILD:
+                property.reset(new SystemInfoBuild());
+                break;
+            case SystemInfoPropertyId::LOCALE:
+                property.reset(new SystemInfoLocale());
+                break;
+            case SystemInfoPropertyId::NETWORK:
+                property.reset(new SystemInfoNetwork());
+                break;
+#ifdef FEATURE_OPTIONAL_WI_FI
+            case SystemInfoPropertyId::WIFI_NETWORK:
+                property.reset(new SystemInfoWifiNetwork());
+                break;
+#endif
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+            case SystemInfoPropertyId::CELLULAR_NETWORK:
+                property.reset(new SystemInfoCellularNetwork(getInstance().m_tapi_handle));
+                break;
+            case SystemInfoPropertyId::SIM: {
+                modemNum = 0;
+                callback->clearArray();
+                while (modemNum < TAPI_HANDLE_MAX) {
+                    property.reset(new SystemInfoSIM(getInstance().m_tapi_handle[modemNum]));
+                    if (property) {
+                        SystemInfoPropertyHolder *propertyHolder =
+                                new (std::nothrow) SystemInfoPropertyHolder();
+                        propertyHolder->ptr = property;
+                        callback->addNativeProperty(propertyHolder);
+                    } else {
+                        std::string log_msg = "Failed to create property object";
+                        LOGE("%s", log_msg.c_str());
+                        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+                    }
+                    modemNum++;
+                }
+                add_to_idle = callback->isPropertyReady();
+                break;
+            }
+#endif
+            case SystemInfoPropertyId::PERIPHERAL:
+                property.reset(new SystemInfoPeripheral());
+                break;
+            case SystemInfoPropertyId::MEMORY:
+                property.reset(new SystemInfoMemory());
+                break;
+            default:
+                std::string log_msg = "Not supported property";
+                LOGE("%s", log_msg.c_str());
+                SystemInfoUtil::throwSystemInfoException<NotSupportedException>(0, log_msg);
+        }
+        if (callback->isArrayEmpty()) {
+            if (property) {
+                callback->setNativeProperty(property);
+                add_to_idle = callback->isPropertyReady();
+            } else {
+                std::string log_msg = "Failed to create property object";
+                LOGE("%s", log_msg.c_str());
+                SystemInfoUtil::throwSystemInfoException(0, log_msg);
+            }
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("getPropertyValueThread fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+        callback->setError(err.getName(), err.getMessage());
+        add_to_idle = true;
+    } catch (...) {
+        LOGE("getPropertyValueThread fails");
+        callback->setError("UnknownError", "getPropertyValueThread fails");
+        add_to_idle = true;
+    }
+
+    if (add_to_idle) {
+        if (callback->isError()) {
+            if (!g_idle_add(complete, data)) {
+                LOGE("g_idle_add fails");
+                delete holder;
+                holder = NULL;
+            }
+        } else {
+            if (!g_idle_add(getPropertyValueCallback, data)) {
+                LOGE("g_idle_add fails");
+                delete holder;
+                holder = NULL;
+            }
+        }
+    } else {
+        LOGD("Property is being processed, not calling js callback");
+        getInstance().addProcessingProperty(holder);
+    }
+    return;
+}
+
+void SystemInfo::getPropertyValue(PropertyCallbackDataPtr callback)
+{
+    LOGD("Entered");
+    if (!callback) {
+        std::string log_msg = "callback is null";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+    PropertyCallbackDataHolder* holder = new (std::nothrow) PropertyCallbackDataHolder();
+    if (!holder) {
+        std::string log_msg = "Failed to allocate memory";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+    holder->ptr = callback;
+
+    if (!g_thread_pool_push(m_pool, static_cast<gpointer>(holder), NULL)) {
+        delete holder;
+        holder = NULL;
+        std::string log_msg = "Failed to add task to thread pool";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+}
+
+unsigned long SystemInfo::addPropertyValueChangeListener(PropertyCallbackDataPtr callback)
+{
+    LOGD("Entered");
+
+    JSContextRef context = callback->getContext();
+    if (!GlobalContextManager::getInstance()->isAliveGlobalContext(context)) {
+        LOGE("context was closed");
+        return 0;
+    }
+
+    //Register the successCallback to receive system events
+    //that the status of the requested properties may have changed.
+    //If property value is 'BUILD', listener would not be registered
+    unsigned long new_id = ++m_current_id;
+    std::pair<unsigned long, PropertyCallbackDataPtr> property_cb(new_id, callback);
+
+    // Check type of property for which listener should be registered
+    switch (callback->getPropertyId()) {
+        case SystemInfoPropertyId::BATTERY: {
+            m_battery_callbacks.insert(property_cb);
+            if (m_battery_callbacks.size() == 1) {
+                registerVconfCallback(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+                        SystemInfo::onBatteryChanged);
+                registerVconfCallback(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
+                        SystemInfo::onBatteryChanged);
+            }
+            LOGD("Added callback for BATTERY, id: %d", new_id);
+            break;
+        }
+        case SystemInfoPropertyId::CPU: {
+            m_cpu_callbacks.insert(property_cb);
+            if (m_cpu_callbacks.size() == 1) {
+                if (!m_cpu_timer) {
+                    LOGD("Creating timer for Cpu listener");
+                    m_cpu_timer = ecore_timer_add(PROPERTY_WATCHER_TIME, SystemInfo::onCpuChanged,
+                    NULL);
+                } else {
+                    LOGE("Timer not created");
+                }
+            }
+            LOGD("Added callback for CPU, id: %d", new_id);
+            break;
+        }
+        case SystemInfoPropertyId::STORAGE: {
+            m_storage_callbacks.insert(property_cb);
+            LOGD("m_storage_callbacks.size() = %d", m_storage_callbacks.size());
+            if (m_storage_callbacks.size() == 1) {
+                registerVconfCallback(VCONFKEY_SYSMAN_MMC_STATUS, SystemInfo::mmcStatusChanged);
+                if (!m_storage_timer) {
+                    LOGD("Creating timer for Storage listener");
+                    m_storage_timer = ecore_timer_add(PROPERTY_WATCHER_TIME,
+                            SystemInfo::onStorageChanged, NULL);
+                } else {
+                    LOGE("Timer not created");
+                }
+            }
+            LOGD("Added callback for STORAGE, id: %d", new_id);
+            break;
+        }
+        case SystemInfoPropertyId::DISPLAY: {
+            m_display_callbacks.insert(property_cb);
+            if (m_display_callbacks.size() == 1) {
+                registerVconfCallback(VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
+                        SystemInfo::onDisplayChanged);
+            }
+            LOGD("Added callback for DISPLAY, id: %d", new_id);
+            break;
+        }
+        case SystemInfoPropertyId::DEVICE_ORIENTATION: {
+            m_device_orientation_callbacks.insert(property_cb);
+            if (m_device_orientation_callbacks.size() == 1) {
+                registerVconfCallback(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL,
+                        SystemInfo::onDeviceAutoRotationChanged);
+                unsigned int interval = BASE_GATHERING_INTERVAL;
+                int ret = sensord_register_event(m_sensor_handle, AUTO_ROTATION_EVENT_CHANGE_STATE,
+                        interval, 0, SystemInfo::onDeviceOrientationChanged, NULL);
+                if (0 != ret) {
+                    LOGE("Failed to register auto rotation event listener");
+                } else {
+                    LOGD("sensord_unregister_event succeed to gather data");
+                }
+            }
+            LOGD("Added callback for DEVICE_ORIENTATION, id: %d", new_id);
+            break;
+        }
+        case SystemInfoPropertyId::BUILD: {
+            LOGD("BUILD property's value is a fixed value");
+            m_inactive_callbacks.insert(property_cb);
+            break;
+        }
+        case SystemInfoPropertyId::LOCALE: {
+            m_locale_callbacks.insert(property_cb);
+            if (m_locale_callbacks.size() == 1) {
+                if (SYSTEM_SETTINGS_ERROR_NONE
+                        != system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY,
+                                SystemInfo::onLocaleChanged, NULL)) {
+                    std::string log_msg = "Failed to register country change callback";
+                    LOGE("%s", log_msg.c_str());
+                    SystemInfoUtil::throwSystemInfoException(0, log_msg);
+                }
+                if (SYSTEM_SETTINGS_ERROR_NONE
+                        != system_settings_set_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE,
+                                SystemInfo::onLocaleChanged, NULL)) {
+                    std::string log_msg = "Failed to register language change callback";
+                    LOGE("%s", log_msg.c_str());
+                    SystemInfoUtil::throwSystemInfoException(0, log_msg);
+                }
+            }
+            LOGD("Added callback for LOCALE, id: %d", new_id);
+            break;
+        }
+        case SystemInfoPropertyId::NETWORK: {
+            m_network_callbacks.insert(property_cb);
+            LOGD("Added callback for NETWORK, id: %d", new_id);
+            break;
+        }
+        case SystemInfoPropertyId::WIFI_NETWORK: {
+#ifdef FEATURE_OPTIONAL_WI_FI
+            m_wifi_network_callbacks.insert(property_cb);
+            LOGD("Added callback for WIFI_NETWORK, id: %d", new_id);
+            //register callback if there were no callbacks in cellular and
+            //this was new callback for wifi
+            if (0 == m_cellular_network_callbacks.size() && 1 == m_wifi_network_callbacks.size()) {
+                registerIpChangeCallback();
+            }
+#else
+            LOGE("WIFI_NETWORK is not supported");
+            m_inactive_callbacks.insert(property_cb);
+            callback->setError(JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, "Not supported property");
+
+#endif
+            break;
+        }
+
+        case SystemInfoPropertyId::CELLULAR_NETWORK: {
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+            m_cellular_network_callbacks.insert(property_cb);
+            LOGD("Added callback for CELLULAR_NETWORK, id: %d", new_id);
+            if (1 == m_cellular_network_callbacks.size()) {
+                if (0 == m_wifi_network_callbacks.size()) {
+                    //register callback if there were no callbacks in wifi and
+                    //this was new callback for cellular
+                    registerIpChangeCallback();
+                }
+                registerVconfCallback(VCONFKEY_TELEPHONY_FLIGHT_MODE,
+                        onConnectionNetworkParamChanged);
+                registerVconfCallback(VCONFKEY_TELEPHONY_CELLID, onConnectionNetworkParamChanged);
+                registerVconfCallback(VCONFKEY_TELEPHONY_LAC, onConnectionNetworkParamChanged);
+                registerVconfCallback(VCONFKEY_TELEPHONY_SVC_ROAM, onConnectionNetworkParamChanged);
+            }
+#else
+            LOGE("CELLULAR_NETWORK is not supported");
+            m_inactive_callbacks.insert(property_cb);
+            callback->setError(JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, "Not supported property");
+#endif
+            break;
+        }
+        case SystemInfoPropertyId::SIM: {
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+            //SIM listeners are not supported by core API, so we just
+            //store callback
+            m_sim_callbacks.insert(property_cb);
+            LOGD("Added callback for SIM, id: %d", new_id);
+#else
+            LOGE("SIM is not supported");
+            m_inactive_callbacks.insert(property_cb);
+            callback->setError(JSWebAPIErrorFactory::NOT_SUPPORTED_ERROR, "Not supported property");
+#endif
+            break;
+        }
+        case SystemInfoPropertyId::PERIPHERAL: {
+            m_peripheral_callbacks.insert(property_cb);
+            if (m_peripheral_callbacks.size() == 1) {
+                /*check if the key exists.*/
+                int value = 0;
+                if (vconf_get_int(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &value) != -1) {
+                    registerVconfCallback(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS,
+                            SystemInfo::onPeripheralChanged);
+                }
+                if (vconf_get_int(VCONFKEY_SYSMAN_HDMI, &value) != -1) {
+                    registerVconfCallback(VCONFKEY_SYSMAN_HDMI, SystemInfo::onPeripheralChanged);
+                }
+                if (vconf_get_int(VCONFKEY_POPSYNC_ACTIVATED_KEY, &value) != -1) {
+                    registerVconfCallback(VCONFKEY_POPSYNC_ACTIVATED_KEY,
+                            SystemInfo::onPeripheralChanged);
+                }
+            }
+            LOGD("Added callback for PERIPHERAL, id: %d", new_id);
+            break;
+        }
+        case SystemInfoPropertyId::MEMORY: {
+            m_memory_callbacks.insert(property_cb);
+            if (m_memory_callbacks.size() == 1) {
+                /*check if the key exists.*/
+                int value = 0;
+                if (vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &value) != -1) {
+                    registerVconfCallback(VCONFKEY_SYSMAN_LOW_MEMORY, SystemInfo::onMemoryChanged);
+                }
+            }
+            LOGD("Added callback for MEMORY, id: %d", new_id);
+            break;
+        }
+        default:
+            std::string log_msg = "Not supported property";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<NotSupportedException>(0, log_msg);
+    }
+    startPropertyWatcherTimer(new_id, callback->getOptions().timeout);
+
+    PropertyCallbackDataHolder* holder = new (std::nothrow) PropertyCallbackDataHolder();
+    if (!holder) {
+        std::string log_msg = "Failed to allocate memory";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+    holder->ptr = callback;
+
+    if (!g_idle_add(complete, holder)) {
+        LOGE("g_idle addition failed");
+    }
+
+    return new_id;
+}
+
+Eina_Bool SystemInfo::onCpuChanged(void* _event_ptr)
+{
+    LOGD("Entered");
+    SystemInfo::getInstance().broadcastCpuChanged();
+    return ECORE_CALLBACK_RENEW;
+}
+
+void SystemInfo::broadcastCpuChanged()
+{
+    LOGD("Entered");
+
+    try {
+        PVCLmap::iterator itr = m_cpu_callbacks.begin();
+
+        SystemInfoCpuPtr cpu = createSystemInfoCpu();
+        double load = cpu->getLoad();
+        if (load == m_cpu_last_load)
+            return;
+
+        m_cpu_last_load = load;
+
+        while (itr != m_cpu_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+
+            SystemInfoOptions opt = callback->getOptions();
+            if (((opt.high_threshold == 0) && (opt.low_threshold == 0))
+                    || ((opt.high_threshold > 0) && (load >= opt.high_threshold))
+                    || ((opt.low_threshold > 0) && (load <= opt.low_threshold))) {
+                callback->setNativeProperty(cpu);
+
+                PropertyCallbackDataHolder* holder =
+                        new (std::nothrow) PropertyCallbackDataHolder();
+                if (!holder) {
+                    std::string log_msg = "Failed to allocate memory";
+                    LOGE("%s", log_msg.c_str());
+                    SystemInfoUtil::throwSystemInfoException(0, log_msg);
+                }
+                holder->ptr = callback;
+
+                guint id = g_idle_add(getPropertyValueCallback, holder);
+                if (!id) {
+                    LOGE("g_idle_add fails");
+                    delete holder;
+                }
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("getCpuValue fails, %s: %s", err.getName().c_str(), err.getMessage().c_str());
+    } catch (...) {
+        LOGE("getCpuValue fails");
+    }
+}
+
+void SystemInfo::removePropertyValueChangeListener(JSContextRef context, unsigned long id)
+{
+    LOGD("Entered");
+
+    JSContextRef g_ctx = NULL;
+    bool on_timeout = false;
+    if (context != NULL) {
+        g_ctx = Common::GlobalContextManager::getInstance()->getGlobalContext(context);
+    } else {
+        //it is call from onPropertyWatcherTimeout, context will not be checked
+        on_timeout = true;
+    }
+    if (m_battery_callbacks.find(id) != m_battery_callbacks.end()) {
+        if (on_timeout || m_battery_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_battery_callbacks[id]->setActive(false);
+            m_battery_callbacks.erase(id);
+            if (m_battery_callbacks.empty()) {
+                unregisterVconfCallback(VCONFKEY_SYSMAN_BATTERY_CAPACITY,
+                        SystemInfo::onBatteryChanged);
+                unregisterVconfCallback(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW,
+                        SystemInfo::onBatteryChanged);
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    } else if (m_storage_callbacks.find(id) != m_storage_callbacks.end()) {
+        if (on_timeout || m_storage_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_storage_callbacks[id]->setActive(false);
+            m_storage_callbacks.erase(id);
+            if (m_storage_callbacks.empty()) {
+                unregisterVconfCallback(VCONFKEY_SYSMAN_MMC_STATUS, SystemInfo::mmcStatusChanged);
+                stopAndDestroyTimer(&m_storage_timer, std::string("Storage"));
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    } else if (m_cpu_callbacks.find(id) != m_cpu_callbacks.end()) {
+        if (on_timeout || m_cpu_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_cpu_callbacks[id]->setActive(false);
+            m_cpu_callbacks.erase(id);
+            if (m_cpu_callbacks.empty()) {
+                stopAndDestroyTimer(&m_cpu_timer, std::string("Cpu"));
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    } else if (m_display_callbacks.find(id) != m_display_callbacks.end()) {
+        if (on_timeout || m_display_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_display_callbacks[id]->setActive(false);
+            m_display_callbacks.erase(id);
+            if (m_display_callbacks.empty()) {
+                unregisterVconfCallback(VCONFKEY_SETAPPL_LCD_BRIGHTNESS,
+                        SystemInfo::onDisplayChanged);
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    } else if (m_peripheral_callbacks.find(id) != m_peripheral_callbacks.end()) {
+        if (on_timeout || m_peripheral_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_peripheral_callbacks[id]->setActive(false);
+            m_peripheral_callbacks.erase(id);
+            int value = 0;
+            if (m_peripheral_callbacks.empty()) {
+                if (vconf_get_int(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &value) != -1) {
+                    unregisterVconfCallback(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS,
+                            SystemInfo::onPeripheralChanged);
+                }
+                if (vconf_get_int(VCONFKEY_SYSMAN_HDMI, &value) != -1) {
+                    unregisterVconfCallback(VCONFKEY_SYSMAN_HDMI, SystemInfo::onPeripheralChanged);
+                }
+                if (vconf_get_int(VCONFKEY_POPSYNC_ACTIVATED_KEY, &value) != -1) {
+                    unregisterVconfCallback(VCONFKEY_POPSYNC_ACTIVATED_KEY,
+                            SystemInfo::onPeripheralChanged);
+                }
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    } else if (m_device_orientation_callbacks.find(id) != m_device_orientation_callbacks.end()) {
+        if (on_timeout || m_device_orientation_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_device_orientation_callbacks[id]->setActive(false);
+            m_device_orientation_callbacks.erase(id);
+            if (m_device_orientation_callbacks.empty()) {
+                unregisterVconfCallback(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL,
+                        SystemInfo::onDeviceAutoRotationChanged);
+                sensord_unregister_event(m_sensor_handle, AUTO_ROTATION_EVENT_CHANGE_STATE);
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    } else if (m_locale_callbacks.find(id) != m_locale_callbacks.end()) {
+        if (on_timeout || m_locale_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_locale_callbacks[id]->setActive(false);
+            m_locale_callbacks.erase(id);
+            if (m_locale_callbacks.empty()) {
+                if (SYSTEM_SETTINGS_ERROR_NONE
+                        != system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE)) {
+                    LOGE("unregistration of language change callback failed");
+                }
+                if (SYSTEM_SETTINGS_ERROR_NONE
+                        != system_settings_unset_changed_cb(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY)) {
+                    LOGE("unregistration of country change callback failed");
+                }
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    } else if (m_network_callbacks.find(id) != m_network_callbacks.end()) {
+        if (on_timeout || m_network_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_network_callbacks[id]->setActive(false);
+            m_network_callbacks.erase(id);
+            if (m_wifi_network_callbacks.empty() && m_cellular_network_callbacks.empty()) {
+                //wifi and cellular has common core callback
+                unregisterIpChangeCallback();
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    }
+#ifdef FEATURE_OPTIONAL_WI_FI
+    else if (m_wifi_network_callbacks.find(id) != m_wifi_network_callbacks.end()) {
+        if (on_timeout || m_wifi_network_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_wifi_network_callbacks[id]->setActive(false);
+            m_wifi_network_callbacks.erase(id);
+            if (m_wifi_network_callbacks.empty()) {
+                if (m_cellular_network_callbacks.empty()) {
+                    //wifi and cellular has common core callback
+                    unregisterIpChangeCallback();
+                }
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    }
+#endif
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+    else if (m_cellular_network_callbacks.find(id) != m_cellular_network_callbacks.end()) {
+        if (on_timeout || m_cellular_network_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_cellular_network_callbacks[id]->setActive(false);
+            m_cellular_network_callbacks.erase(id);
+            if (m_cellular_network_callbacks.empty()) {
+                if (m_wifi_network_callbacks.empty()) {
+                    //wifi and cellular has common core callback
+                    unregisterIpChangeCallback();
+                }
+                unregisterVconfCallback(VCONFKEY_TELEPHONY_FLIGHT_MODE,
+                        onConnectionNetworkParamChanged);
+                unregisterVconfCallback(VCONFKEY_TELEPHONY_CELLID, onConnectionNetworkParamChanged);
+                unregisterVconfCallback(VCONFKEY_TELEPHONY_LAC, onConnectionNetworkParamChanged);
+                unregisterVconfCallback(VCONFKEY_TELEPHONY_SVC_ROAM,
+                        onConnectionNetworkParamChanged);
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    } else if (m_sim_callbacks.find(id) != m_sim_callbacks.end()) {
+        if (on_timeout || m_sim_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_sim_callbacks[id]->setActive(false);
+            m_sim_callbacks.erase(id);
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    }
+#endif
+    else if (m_memory_callbacks.find(id) != m_memory_callbacks.end()) {
+        if (on_timeout || m_memory_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_memory_callbacks[id]->setActive(false);
+            m_memory_callbacks.erase(id);
+            if (m_memory_callbacks.empty()) {
+                unregisterVconfCallback(VCONFKEY_SYSMAN_LOW_MEMORY, SystemInfo::onMemoryChanged);
+            }
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    } else if (m_inactive_callbacks.find(id) != m_inactive_callbacks.end()) {
+        if (on_timeout || m_inactive_callbacks[id]->getContext() == g_ctx) {
+            stopPropertyWatcherTimer(id);
+            m_inactive_callbacks[id]->setActive(false);
+            m_inactive_callbacks.erase(id);
+        } else {
+            std::string log_msg = "Removing callbacks from another context is not allowed";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+        }
+    }
+
+    else {
+        std::string log_msg = "ListenerId: " + std::to_string(id) + " not found";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException<InvalidValuesException>(0, log_msg);
+    }
+    return;
+}
+
+void SystemInfo::startPropertyWatcherTimer(unsigned long listener_id, unsigned long timeout)
+{
+    LOGD("Entered");
+
+    if (timeout > 0) {
+        double value = static_cast<double>(timeout) / 1000.0;
+        unsigned long* id = new (std::nothrow) unsigned long(listener_id);
+        if (!id) {
+            std::string log_msg = "Failed to allocate memory";
+            LOGE("%s", log_msg.c_str());
+            SystemInfoUtil::throwSystemInfoException(0, log_msg);
+        }
+        Ecore_Timer* timer = ecore_timer_add(value, SystemInfo::onPropertyWatcherTimeout,
+                (void *) id);
+        if (!timer) {
+            std::string log_msg = "Failed to add timer for listener id";
+            LOGE("%s, %d", log_msg.c_str(), listener_id);
+            SystemInfoUtil::throwSystemInfoException(0, log_msg);
+        }
+        m_watcher_map[listener_id] = timer;
+    }
+}
+
+void SystemInfo::stopPropertyWatcherTimer(unsigned long listener_id)
+{
+    LOGD("Entered");
+
+    std::map<unsigned long, Ecore_Timer*>::iterator watcher_it = m_watcher_map.find(listener_id);
+    if (watcher_it != m_watcher_map.end()) {
+        stopAndDestroyTimer(&watcher_it->second, std::to_string(watcher_it->first));
+        m_watcher_map.erase(watcher_it);
+    } else {
+        LOGW("Timer not set for listener id: %u", listener_id);
+    }
+}
+
+Eina_Bool SystemInfo::onPropertyWatcherTimeout(void* event_ptr)
+{
+    LOGD("Entered");
+
+    unsigned long *listener_id = static_cast<unsigned long*>(event_ptr);
+    try {
+        if (listener_id) {
+            SystemInfo::getInstance().removePropertyValueChangeListener(NULL, *listener_id);
+        } else {
+            LOGE("Listener id is NULL");
+        }
+    } catch (...) {
+        LOGE("Unexpected exception");
+    }
+    delete listener_id;
+
+    return ECORE_CALLBACK_CANCEL;
+}
+
+void SystemInfo::onBatteryChanged(keynode_t *node, void *event_ptr)
+{
+    LOGD("Entered");
+
+    SystemInfo::getInstance().broadcastBatteryChanged();
+}
+
+void SystemInfo::broadcastBatteryChanged()
+{
+    LOGD("Entered");
+
+    try {
+        PVCLmap::iterator itr = m_battery_callbacks.begin();
+
+        while (itr != m_battery_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+            SystemInfoBatteryPtr battery(new SystemInfoBattery());
+            SystemInfoOptions opt = callback->getOptions();
+            if (((opt.high_threshold == 0) && (opt.low_threshold == 0))
+                    || ((opt.high_threshold > 0) && (battery->getLevel() >= opt.high_threshold))
+                    || ((opt.low_threshold > 0) && (battery->getLevel() <= opt.low_threshold))) {
+                callback->setNativeProperty(battery);
+
+                PropertyCallbackDataHolder* holder =
+                        new (std::nothrow) PropertyCallbackDataHolder();
+                if (!holder) {
+                    std::string log_msg = "Failed to allocate memory";
+                    LOGE("%s", log_msg.c_str());
+                    SystemInfoUtil::throwSystemInfoException(0, log_msg);
+                }
+                holder->ptr = callback;
+
+                guint id = g_idle_add(getPropertyValueCallback, holder);
+                if (!id) {
+                    LOGE("g_idle_add fails");
+                    delete holder;
+                }
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("broadcastBatteryChanged fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("broadcastBatteryChanged fails");
+    }
+}
+
+Eina_Bool SystemInfo::onStorageChanged(void *event_ptr)
+{
+    LOGD("Entered");
+
+    SystemInfo::getInstance().broadcastStorageChanged();
+    return ECORE_CALLBACK_RENEW;
+}
+
+void SystemInfo::mmcStatusChanged(keynode_t *node, void *event_ptr)
+{
+    LOGD("Entered");
+    SystemInfo::getInstance().broadcastStorageChanged();
+}
+
+void SystemInfo::broadcastStorageChanged()
+{
+    LOGD("Entered");
+
+    try {
+        PVCLmap::iterator itr = m_storage_callbacks.begin();
+
+        SystemInfoStoragePtr storage(new SystemInfoStorage());
+        if (last_storage) {
+            if (*last_storage == *storage) {
+                LOGD("Storage didn't change. Returning.");
+                return;
+            }
+        }
+        last_storage = storage;
+
+        while (itr != m_storage_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+            callback->setNativeProperty(storage);
+
+            PropertyCallbackDataHolder* holder = new (std::nothrow) PropertyCallbackDataHolder();
+            if (!holder) {
+                std::string log_msg = "Failed to allocate memory";
+                LOGE("%s", log_msg.c_str());
+                SystemInfoUtil::throwSystemInfoException(0, log_msg);
+            }
+            holder->ptr = callback;
+
+            guint id = g_idle_add(getPropertyValueCallback, holder);
+            if (!id) {
+                LOGE("g_idle_add failed");
+                delete holder;
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("broadcastStorageChanged failed, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("broadcastStorageChanged failed");
+    }
+}
+
+void SystemInfo::onDisplayChanged(keynode_t *node, void *event_ptr)
+{
+    LOGD("Entered");
+
+    SystemInfo::getInstance().broadcastDisplayChanged();
+}
+
+void SystemInfo::broadcastDisplayChanged()
+{
+    LOGD("Entered");
+
+    try {
+        PVCLmap::iterator itr = m_display_callbacks.begin();
+
+        while (itr != m_display_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+            SystemInfoDisplayPtr display(new SystemInfoDisplay());
+            SystemInfoOptions opt = callback->getOptions();
+            if (((opt.high_threshold == 0) && (opt.low_threshold == 0))
+                    || ((opt.high_threshold > 0) && (display->getBrightness() >= opt.high_threshold))
+                    || ((opt.low_threshold > 0) && (display->getBrightness() <= opt.low_threshold))) {
+                callback->setNativeProperty(display);
+
+                PropertyCallbackDataHolder* holder =
+                        new (std::nothrow) PropertyCallbackDataHolder();
+                if (!holder) {
+                    std::string log_msg = "Failed to allocate memory";
+                    LOGE("%s", log_msg.c_str());
+                    SystemInfoUtil::throwSystemInfoException(0, log_msg);
+                }
+                holder->ptr = callback;
+
+                guint id = g_idle_add(getPropertyValueCallback, holder);
+                if (!id) {
+                    LOGE("g_idle_add failed");
+                    delete holder;
+                }
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("broadcastDisplayChanged failed, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("broadcastDisplayChanged failed");
+    }
+}
+
+void SystemInfo::onDeviceAutoRotationChanged(keynode_t *node, void *event_ptr)
+{
+    LOGD("Entered");
+    SystemInfo::getInstance().broadcastDeviceOrientationChanged();
+}
+
+void SystemInfo::onDeviceOrientationChanged(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data)
+{
+    LOGD("Entered");
+    int rotation = 0;
+
+    LOGD("size of the data value array:%d", data->value_count);
+    if (data->value_count > 0) {
+        rotation = data->values[0];
+        LOGD("ratation value : %d", rotation);
+        if (rotation != AUTO_ROTATION_DEGREE_UNKNOWN) {
+            SystemInfo::getInstance().broadcastDeviceOrientationChanged();
+        }
+    } else {
+        LOGE("failed to get data : the size of array is less than 0");
+    }
+}
+
+void SystemInfo::broadcastDeviceOrientationChanged()
+{
+    LOGD("Entered");
+
+    try {
+        PVCLmap::iterator itr = m_device_orientation_callbacks.begin();
+
+        while (itr != m_device_orientation_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+            SystemInfoDeviceOrientationPtr dev_orientation(new SystemInfoDeviceOrientation());
+            callback->setNativeProperty(dev_orientation);
+
+            PropertyCallbackDataHolder* holder = new (std::nothrow) PropertyCallbackDataHolder();
+            if (!holder) {
+                std::string log_msg = "Failed to allocate memory";
+                LOGE("%s", log_msg.c_str());
+                SystemInfoUtil::throwSystemInfoException(0, log_msg);
+            }
+            holder->ptr = callback;
+
+            guint id = g_idle_add(getPropertyValueCallback, holder);
+            if (!id) {
+                LOGE("g_idle_add failed");
+                delete holder;
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("broadcastDeviceOrientationChanged failed, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("broadcastDeviceOrientationChanged failed");
+    }
+}
+
+void SystemInfo::onLocaleChanged(system_settings_key_e key, void* event_ptr)
+{
+    LOGD("Entered");
+
+    SystemInfo::getInstance().broadcastLocaleChanged();
+}
+
+void SystemInfo::broadcastLocaleChanged()
+{
+    LOGD("Entered");
+
+    try {
+        PVCLmap::iterator itr = m_locale_callbacks.begin();
+
+        while (itr != m_locale_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+            SystemInfoLocalePtr locale(new SystemInfoLocale());
+            callback->setNativeProperty(locale);
+
+            PropertyCallbackDataHolder* holder = new (std::nothrow) PropertyCallbackDataHolder();
+            if (!holder) {
+                std::string log_msg = "Failed to allocate memory";
+                LOGE("%s", log_msg.c_str());
+                SystemInfoUtil::throwSystemInfoException(0, log_msg);
+            }
+            holder->ptr = callback;
+
+            guint id = g_idle_add(getPropertyValueCallback, holder);
+            if (!id) {
+                LOGE("g_idle_add failed");
+                delete holder;
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("broadcastLocaleChanged failed, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("broadcastLocaleChanged failed");
+    }
+}
+
+SystemInfoCpuPtr SystemInfo::createSystemInfoCpu()
+{
+    std::lock_guard < std::mutex > lock(m_cpu_info_lock);
+    return std::make_shared < SystemInfoCpu > (m_cpu_info);
+}
+
+void SystemInfo::stopAndDestroyTimer(Ecore_Timer ** _p_timer, const std::string & _msg)
+{
+    if (_p_timer && *_p_timer) {
+        LOGD("Deleting timer for %s listener", _msg.c_str());
+        ecore_timer_del(*_p_timer);
+        *_p_timer = NULL;
+    } else {
+        LOGD("Deleting timer for %s listener failed, timer already NULL", _msg.c_str());
+    }
+}
+
+void SystemInfo::onPeripheralChanged(keynode_t* /*node*/, void* /*event_ptr*/)
+{
+    LOGD("Entered");
+
+    SystemInfo::getInstance().broadcastPeripheralChanged();
+}
+
+void SystemInfo::broadcastPeripheralChanged()
+{
+    LOGD("Entered");
+
+    try {
+        PVCLmap::iterator itr = m_peripheral_callbacks.begin();
+        SystemInfoPeripheralPtr p_peripheral(new SystemInfoPeripheral());
+
+        while (itr != m_peripheral_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+            callback->setNativeProperty(p_peripheral);
+
+            PropertyCallbackDataHolder* holder = new (std::nothrow) PropertyCallbackDataHolder();
+            if (!holder) {
+                std::string log_msg = "Failed to allocate memory";
+                LOGE("%s", log_msg.c_str());
+                SystemInfoUtil::throwSystemInfoException(0, log_msg);
+            }
+            holder->ptr = callback;
+
+            guint id = g_idle_add(getPropertyValueCallback, holder);
+            if (!id) {
+                LOGE("g_idle_add fails");
+                delete holder;
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("broadcastPeripheralChanged fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("broadcastPeripheralChanged fails");
+    }
+}
+
+void SystemInfo::onMemoryChanged(keynode_t* /*node*/, void* /*event_ptr*/)
+{
+    LOGD("Entered");
+    SystemInfo::getInstance().broadcastMemoryChanged();
+}
+
+void SystemInfo::broadcastMemoryChanged()
+{
+    LOGD("Entered");
+
+    try {
+        PVCLmap::iterator itr = m_memory_callbacks.begin();
+        SystemInfoMemoryPtr p_memory(new SystemInfoMemory());
+
+        while (itr != m_memory_callbacks.end()) {
+            PropertyCallbackDataPtr callback = itr->second;
+            callback->setNativeProperty(p_memory);
+
+            PropertyCallbackDataHolder* holder = new (std::nothrow) PropertyCallbackDataHolder();
+            if (!holder) {
+                std::string log_msg = "Failed to allocate memory";
+                LOGE("%s", log_msg.c_str());
+                SystemInfoUtil::throwSystemInfoException(0, log_msg);
+            }
+            holder->ptr = callback;
+
+            guint id = g_idle_add(getPropertyValueCallback, holder);
+            if (!id) {
+                LOGE("g_idle_add fails");
+                delete holder;
+            }
+            ++itr;
+        }
+    } catch (const BasePlatformException &err) {
+        LOGE("broadcastMemoryChanged fails, %s: %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    } catch (...) {
+        LOGE("broadcastMemoryChanged fails");
+    }
+}
+
+void SystemInfo::registerVconfCallback(const char *in_key, vconf_callback_fn cb)
+{
+    if (0 != vconf_notify_key_changed(in_key, cb, NULL)) {
+        std::string log_msg = "Failed to register vconf callback";
+        LOGE("%s, %s", log_msg.c_str(), in_key);
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+}
+
+void SystemInfo::unregisterVconfCallback(const char *in_key, vconf_callback_fn cb)
+{
+    if (0 != vconf_ignore_key_changed(in_key, cb)) {
+        std::string log_msg = "Failed to unregister vconf callback";
+        LOGE("%s, %s", log_msg.c_str(), in_key);
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+}
+
+gboolean SystemInfo::complete(void *data)
+{
+    LOGD("Entered");
+
+    auto holder = static_cast<PropertyCallbackDataHolder*>(data);
+    if (!holder) {
+        LOGE("callback holder is null");
+        return false;
+    }
+    auto callback = holder->ptr;
+    if (!callback) {
+        LOGE("callback is null");
+        delete holder;
+        holder = NULL;
+        return false;
+    }
+
+    JSContextRef context = callback->getContext();
+
+    if (callback->isError()) {
+        LOGD("ErrorCallback triggered");
+        JSObjectRef error = JSWebAPIErrorFactory::makeErrorObject(context, callback->getErrorName(),
+                callback->getErrorMessage());
+        callback->callErrorCallback(error);
+    }
+
+    delete holder;
+    holder = NULL;
+
+    return false;
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfo.h b/src/Systeminfo/SystemInfo.h
new file mode 100755 (executable)
index 0000000..3c8e39b
--- /dev/null
@@ -0,0 +1,196 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_H__
+
+#include "SystemInfoPropertySuccessCallbackData.h"
+#include "SystemInfoDeviceCapability.h"
+#include "SystemInfoStorage.h"
+#include "SystemInfoDeviceOrientation.h"
+#include "SystemInfoLocale.h"
+
+#include <glib.h>
+#include <Ecore.h>
+#include <vconf.h>
+#include <memory>
+#include <mutex>
+#include <vector>
+#include <map>
+#include <net_connection.h>
+#include <system_settings.h>
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+#include <tapi_common.h>
+#endif
+
+#define TAPI_HANDLE_MAX 2
+#define DEFAULT_PROPERTY_COUNT 1
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+//! Map that stores PropertyValueChangeListeners
+typedef std::map<unsigned long, PropertyCallbackDataPtr> PVCLmap;
+
+class SystemInfoCpu;
+
+class SystemInfo {
+public:
+    static SystemInfo& getInstance();
+    virtual ~SystemInfo();
+
+    long long getTotalMemory();
+    long long getAvailableMemory();
+
+    SystemInfoDeviceCapabilityPtr getCapabilities();
+    void getPropertyValue(PropertyCallbackDataPtr callback);
+
+    unsigned long getCount(SystemInfoPropertyId propertyId);
+
+    //! Interface for listener's manipulation (registration and removal)
+    unsigned long addPropertyValueChangeListener(PropertyCallbackDataPtr callback);
+    void removePropertyValueChangeListener(JSContextRef context, unsigned long id);
+
+    /**
+     * Notify that one of processed callbacks is ready to be called
+     */
+    void notifyGetPropertyValueReady();
+
+private:
+    SystemInfo();
+    SystemInfo(const SystemInfo&);
+    SystemInfo& operator=(const SystemInfo&);
+
+    static gboolean getPropertyValueCallback(void *data);
+    static void getPropertyValueThread(gpointer data, gpointer user_data);
+    void startPropertyWatcherTimer(unsigned long listener_id, unsigned long timeout);
+    void stopPropertyWatcherTimer(unsigned long listener_id);
+    static Eina_Bool onPropertyWatcherTimeout(void* event_ptr);
+
+    static gboolean complete(void *data);
+
+    static void onBatteryChanged(keynode_t *node, void *event_ptr);
+    void broadcastBatteryChanged();
+
+    static Eina_Bool onStorageChanged(void *event_ptr);
+    static void mmcStatusChanged(keynode_t *node, void *event_ptr);
+    void broadcastStorageChanged();
+
+    static void onDisplayChanged(keynode_t *node, void *event_ptr);
+    void broadcastDisplayChanged();
+
+    static void onDeviceAutoRotationChanged(keynode_t *node, void *event_ptr);
+    static void onDeviceOrientationChanged(sensor_t sensor, unsigned int event_type, sensor_data_t *data, void *user_data);
+
+    void broadcastDeviceOrientationChanged();
+
+    static Eina_Bool onCpuChanged(void* event_ptr);
+    void broadcastCpuChanged();
+
+    void stopAndDestroyTimer(Ecore_Timer ** _p_timer, const std::string & _msg);
+
+    static void onPeripheralChanged(keynode_t *node, void *event_ptr);
+    void broadcastPeripheralChanged();
+
+    static void onMemoryChanged(keynode_t *node, void *event_ptr);
+    void broadcastMemoryChanged();
+
+    static void onLocaleChanged(system_settings_key_e key, void* event_ptr);
+    void broadcastLocaleChanged();
+
+    void addProcessingProperty(PropertyCallbackDataHolder* holder);
+
+    static void registerVconfCallback(const char *in_key, vconf_callback_fn cb);
+    static void unregisterVconfCallback(const char *in_key, vconf_callback_fn cb);
+    connection_h getConnectionHandle();
+
+    void registerIpChangeCallback();
+    void unregisterIpChangeCallback();
+    static void onConnectionIpAddressChanged(const char* ipv4_address, const char* ipv6_address,
+            void* user_data);
+    static void onConnectionNetworkParamChanged(keynode_t *node, void *user_data);
+    void broadcastCellularNetworkChanged();
+
+    void broadcastWifiNetworkChanged();
+
+    //! Handler for thread pool
+    GThreadPool* m_pool;
+
+    //! Highest used id (in most cases id of last registered listener)
+    unsigned long m_current_id;
+
+    //! Mutex for m_processing_properties
+    std::mutex m_processing_properties_lock;
+
+    //! Callbacks for each property is stored in separate
+    //! collections to simplify adding and searching on call
+    //! mutex is not used because core API callback is called by main thread
+    PVCLmap m_battery_callbacks;
+    PVCLmap m_cpu_callbacks;
+    PVCLmap m_storage_callbacks;
+    PVCLmap m_display_callbacks;
+    PVCLmap m_device_orientation_callbacks;
+    PVCLmap m_locale_callbacks;
+    PVCLmap m_network_callbacks;
+
+    PVCLmap m_wifi_network_callbacks;
+
+    PVCLmap m_cellular_network_callbacks;
+    PVCLmap m_sim_callbacks;
+
+    PVCLmap m_peripheral_callbacks;
+    PVCLmap m_memory_callbacks;
+    PVCLmap m_inactive_callbacks;
+
+    //! Map for timeout functionality
+    std::map<unsigned long, Ecore_Timer*> m_watcher_map;
+
+    //! Timer for a storage listener
+    Ecore_Timer *m_storage_timer;
+    std::shared_ptr<SystemInfoStorage> last_storage;
+
+    static CpuInfo m_cpu_info;
+    static std::shared_ptr<SystemInfoCpu> createSystemInfoCpu();
+    static std::mutex m_cpu_info_lock;
+
+    //! Timer for a cpu load listener
+    Ecore_Timer *m_cpu_timer;
+    double m_cpu_last_load;
+    int m_sensor_handle;
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+    //! Handle for tapi communication
+    TapiHandle *m_tapi_handle[TAPI_HANDLE_MAX+1];
+#else
+    void *m_tapi_handle;
+#endif
+
+#ifdef FEATURE_OPTIONAL_WI_FI
+    //! Handle for net connection
+    connection_h m_connection_handle;
+#else
+    void *m_connection_handle;
+#endif
+    //! A list of properties being processed asynchronously
+    std::vector<PropertyCallbackDataHolder*> m_processing_properties;
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_H__
diff --git a/src/Systeminfo/SystemInfoBattery.cpp b/src/Systeminfo/SystemInfoBattery.cpp
new file mode 100755 (executable)
index 0000000..3c0d14c
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <vconf.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "SystemInfoBattery.h"
+#include "SystemInfoUtil.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+    const double REMANING_BATTERY_CHARGE_MAX = 100.0;
+}
+
+SystemInfoBattery::SystemInfoBattery()
+{
+    LOGD("Entered");
+
+    m_level = fetchLevel();
+    m_is_charging = fetchIsCharging();
+}
+
+SystemInfoBattery::~SystemInfoBattery()
+{
+    LOGD("Entered");
+}
+
+double SystemInfoBattery::getLevel() const
+{
+    return m_level;
+}
+
+bool SystemInfoBattery::isCharging() const
+{
+    return m_is_charging;
+}
+
+double SystemInfoBattery::fetchLevel()
+{
+    LOGD("Entered");
+    int value = 0;
+
+    int ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CAPACITY, &value);
+    if (ret != VCONF_OK) {
+        std::string log_msg = "Failed to get battery capacity";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+
+    return static_cast<double>(value) / REMANING_BATTERY_CHARGE_MAX;
+}
+
+bool SystemInfoBattery::fetchIsCharging()
+{
+    LOGD("Entered");
+    int value = 0;
+
+    int ret = vconf_get_int(VCONFKEY_SYSMAN_BATTERY_CHARGE_NOW, &value);
+    if (ret != VCONF_OK) {
+        std::string log_msg = "Failed to get battery change";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+
+    return (0 != value);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoBattery.h b/src/Systeminfo/SystemInfoBattery.h
new file mode 100755 (executable)
index 0000000..84ad3d3
--- /dev/null
@@ -0,0 +1,50 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_BATTERY_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_BATTERY_H__
+
+#include <memory>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoBattery;
+typedef std::shared_ptr<SystemInfoBattery> SystemInfoBatteryPtr;
+
+class SystemInfoBattery : public SystemInfoProperty {
+public:
+    SystemInfoBattery();
+    virtual ~SystemInfoBattery();
+
+    double getLevel() const;
+    bool isCharging() const;
+
+private:
+    double m_level;
+    bool m_is_charging;
+
+    double fetchLevel();
+    bool fetchIsCharging();
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_BATTERY_H__
diff --git a/src/Systeminfo/SystemInfoBuild.cpp b/src/Systeminfo/SystemInfoBuild.cpp
new file mode 100755 (executable)
index 0000000..9e09b63
--- /dev/null
@@ -0,0 +1,81 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "SystemInfoBuild.h"
+#include "SystemInfoUtil.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+    const char* SYSTEM_INFO_MODEL_NAME = "tizen.org/system/model_name";
+    const char* SYSTEM_INFO_MANUFACTURER= "tizen.org/system/manufacturer";
+    const char* SYSTEM_INFO_BUILD_STRING= "tizen.org/system/build.string";
+}
+
+SystemInfoBuild::SystemInfoBuild() :
+    m_model(fetchPlatformString(SYSTEM_INFO_MODEL_NAME)),
+    m_manufacturer(fetchPlatformString(SYSTEM_INFO_MANUFACTURER)),
+    m_build_version(fetchPlatformString(SYSTEM_INFO_BUILD_STRING))
+{
+    LOGD("Entered");
+}
+
+std::string SystemInfoBuild::fetchPlatformString(const char* _build_info)
+{
+    LOGD("Entered");
+
+    char* platform_c_string;
+    std::string platform_string = "";
+
+    int ret = system_info_get_platform_string(_build_info, &platform_c_string);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        std::string log_msg = "Failed to get model name";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+        SystemInfoUtil::throwSystemInfoException(ret, log_msg);
+    } else {
+        if (platform_c_string) {
+            LOGD("Build platfrom string %s", platform_c_string);
+            platform_string = platform_c_string;
+            free(platform_c_string);
+        }
+    }
+    return platform_string;
+}
+
+SystemInfoBuild::~SystemInfoBuild()
+{
+    LOGD("Entered");
+}
+
+const std::string SystemInfoBuild::getModel() const
+{
+    return m_model;
+}
+
+const std::string SystemInfoBuild::getManufacturer() const
+{
+    return m_manufacturer;
+}
+
+const std::string SystemInfoBuild::getBuildVersion() const
+{
+    return m_build_version;
+}
+
+} // namespace SystemInfo
+} // namespace DeviceAPI
diff --git a/src/Systeminfo/SystemInfoBuild.h b/src/Systeminfo/SystemInfoBuild.h
new file mode 100755 (executable)
index 0000000..9250e6a
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_BUILDINFO_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_BUILDINFO_H__
+
+#include "SystemInfoProperty.h"
+#include <memory>
+#include <system_info.h>
+#include <system_info_internal.h>
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoBuild;
+typedef std::shared_ptr<SystemInfoBuild> SystemInfoBuildPtr;
+
+class SystemInfoBuild : public SystemInfoProperty {
+public:
+    SystemInfoBuild();
+    virtual ~SystemInfoBuild();
+
+    const std::string getModel() const;
+    const std::string getManufacturer() const;
+    const std::string getBuildVersion() const;
+
+private:
+
+    std::string fetchPlatformString(const char* _build_info);
+    std::string fetchPlatformString(system_info_key_e _build_info);
+
+    const std::string m_model;
+    const std::string m_manufacturer;
+    const std::string m_build_version;
+
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif // __TIZEN_SYSTEMINFO_SYSTEMINFO_BUILDINFO_H__
diff --git a/src/Systeminfo/SystemInfoCellularNetwork.cpp b/src/Systeminfo/SystemInfoCellularNetwork.cpp
new file mode 100755 (executable)
index 0000000..504e2d6
--- /dev/null
@@ -0,0 +1,305 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <device.h>
+#include <vconf.h>
+#include <stdlib.h>
+#include <ITapiModem.h>
+#include <net_connection.h>
+#include <ITapiNetwork.h>
+#include "SystemInfoCellularNetwork.h"
+#include "SystemInfoUtil.h"
+
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+const char* CONNECTION_OFF = "OFF";
+const char* CONNECTION_ON = "ON";
+}
+
+SystemInfoCellularNetwork::SystemInfoCellularNetwork(TapiHandle **tapi_handle) :
+    m_mcc(0),
+    m_mnc(0),
+    m_cell_id(0),
+    m_lac(0),
+    m_is_roaming(false),
+    m_is_flight_mode(false)
+{
+    LOGD("Entered");
+
+    fetchVconfSettings();
+    fetchConnection(tapi_handle);
+}
+
+SystemInfoCellularNetwork::~SystemInfoCellularNetwork()
+{
+    LOGD("Entered");
+}
+
+std::string SystemInfoCellularNetwork::getStatus() const
+{
+    return m_status;
+}
+
+std::string SystemInfoCellularNetwork::getApn() const
+{
+    return m_apn;
+}
+
+std::string SystemInfoCellularNetwork::getIpAddress() const
+{
+    return m_ip_address;
+}
+
+std::string SystemInfoCellularNetwork::getIpv6Address() const
+{
+    return m_ipv6_address;
+}
+
+unsigned short SystemInfoCellularNetwork::getMcc() const
+{
+    return m_mcc;
+}
+
+unsigned short SystemInfoCellularNetwork::getMnc() const
+{
+    return m_mnc;
+}
+
+unsigned short SystemInfoCellularNetwork::getCellId() const
+{
+    return m_cell_id;
+}
+
+unsigned short SystemInfoCellularNetwork::getLac() const
+{
+    return m_lac;
+}
+
+bool SystemInfoCellularNetwork::isRoaming() const
+{
+    return m_is_roaming;
+}
+
+bool SystemInfoCellularNetwork::isFlightMode() const
+{
+    return m_is_flight_mode;
+}
+
+std::string SystemInfoCellularNetwork::getImei() const
+{
+    return m_imei;
+}
+
+void SystemInfoCellularNetwork::fetchVconfSettings()
+{
+    int result;
+    int ret = 0;
+
+    ret = vconf_get_bool(VCONFKEY_TELEPHONY_FLIGHT_MODE, &result);
+    if (ret != VCONF_OK) {
+        LOGE("Failed to get is_flight_mode value");
+    }
+    m_is_flight_mode = (0 != result) ? true : false;
+}
+
+void SystemInfoCellularNetwork::fetchConnection(TapiHandle **tapi_handle)
+{
+    connection_type_e connection_type;
+    connection_profile_h profile_handle = NULL;
+    char* apn = NULL;
+    char* ip_addr = NULL;
+    char* imei = NULL;
+    connection_h connection_handle;
+    TelNetworkDefaultDataSubs_t default_subs = TAPI_NETWORK_DEFAULT_DATA_SUBS_SIM1;
+    TapiHandle *handle;
+    TelSimImsiInfo_t imsi;
+    char* plmn;
+    int plmnValue;
+    int roam;
+    int cellid;
+    int lac;
+    unsigned short mcc_devider = 1000;
+    char **cp_list = NULL;
+    int ret = 0;
+
+    //capi network doesn't support using connection handle created in
+    //other thread, so we need to create it here
+    ret = connection_create(&connection_handle);
+    if (ret != CONNECTION_ERROR_NONE) {
+        LOGE("Failed to create connection: %d, %s", ret,
+                SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+    }
+
+    try {
+        ret = connection_get_type(connection_handle, &connection_type);
+        if (ret != CONNECTION_ERROR_NONE) {
+            LOGE("Failed to get connection type: %d, %s", ret,
+                    SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+        }
+
+        if (CONNECTION_TYPE_CELLULAR == connection_type) {
+            m_status = CONNECTION_ON;
+
+            ret = connection_get_current_profile(connection_handle, &profile_handle);
+            if (ret != CONNECTION_ERROR_NONE) {
+                LOGE("Failed to get profile: %d, %s", ret,
+                        SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            }
+
+            ret = connection_profile_get_cellular_apn(profile_handle, &apn);
+            if (ret != CONNECTION_ERROR_NONE) {
+                LOGE("Failed to get apn name: %d, %s", ret,
+                        SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            }
+            m_apn = apn;
+            free(apn);
+
+            ret = connection_profile_get_ip_address(profile_handle, CONNECTION_ADDRESS_FAMILY_IPV4,
+                    &ip_addr);
+            if (ret == CONNECTION_ERROR_NONE) {
+                LOGD("Success to get ipv4");
+                m_ip_address = ip_addr;
+                free(ip_addr);
+            } else {
+                LOGE("Failed to get ip address: %d, %s", ret,
+                        SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            }
+
+            ip_addr = NULL;
+            ret = connection_profile_get_ip_address(profile_handle, CONNECTION_ADDRESS_FAMILY_IPV6,
+                    &ip_addr);
+            if (ret == CONNECTION_ERROR_NONE) {
+                LOGD("Success to get ipv6");
+                m_ipv6_address = ip_addr;
+                free(ip_addr);
+            } else if (CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED != ret) {
+                LOGE("Failed to get ipv6 address: %d, %s", ret,
+                        SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            }
+        } else {
+            m_status = CONNECTION_OFF;
+
+            ret = connection_get_default_cellular_service_profile(connection_handle,
+                    CONNECTION_CELLULAR_SERVICE_TYPE_INTERNET, &profile_handle);
+            if (ret == CONNECTION_ERROR_NONE) {
+                ret = connection_profile_get_cellular_apn(profile_handle, &apn);
+                if (ret == CONNECTION_ERROR_NONE) {
+                    LOGD("Success to get apn");
+                    m_apn = apn;
+                    free(apn);
+                } else {
+                    LOGE("Failed to get default apn name: %d, %s", ret,
+                            SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+                }
+            } else {
+                LOGE("Failed to get default profile: %d, %s", ret,
+                        SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            }
+        }
+
+        handle = tel_init(NULL);
+        ret = tel_get_network_default_data_subscription(handle, &default_subs);
+        if (ret != TAPI_API_SUCCESS) {
+            LOGE("Failed to get default subscriber: %d, %s", ret,
+                    SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+        } else {
+            LOGD("Success to get default subscription");
+            tel_deinit(handle);
+            handle = NULL;
+
+            cp_list = tel_get_cp_name_list();
+            handle = tel_init(cp_list[default_subs]);
+        }
+
+        if (handle == NULL) {
+            LOGE("It's failed to get handle");
+        }
+
+        imei = tel_get_misc_me_imei_sync(handle);
+        if (NULL != imei) {
+            LOGD("Success to get imei");
+            m_imei = imei;
+            free(imei);
+        } else {
+            LOGE("Failed to get imei, NULL pointer. Setting empty value.");
+            m_imei = "";
+        }
+
+        ret = tel_get_property_string(handle, TAPI_PROP_NETWORK_PLMN, &plmn);
+        if (ret != TAPI_API_SUCCESS) {
+            LOGE("Failed to get plmn value, %d, %s", ret,
+                    SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+        } else {
+            LOGD("plmn : %s", plmn);
+            plmnValue = atoi(plmn);
+            if (plmnValue < 100000) {
+                mcc_devider = 100;
+            }
+            m_mcc = plmnValue / mcc_devider;
+            m_mnc = plmnValue % mcc_devider;
+            LOGD("mcc : %d, mnc : %d", m_mcc, m_mnc);
+        }
+
+        ret = tel_get_property_int(handle, TAPI_PROP_NETWORK_ROAMING_STATUS, &roam);
+        if (ret != TAPI_API_SUCCESS) {
+            LOGE("Failed to get roaming status, %d, %s", ret,
+                    SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+        } else {
+            LOGD("roaming : %d", roam);
+            m_is_roaming = (0 != roam) ? true : false;
+        }
+
+        ret = tel_get_property_int(handle, TAPI_PROP_NETWORK_CELLID, &cellid);
+        if (ret != TAPI_API_SUCCESS) {
+            LOGE("Failed to get cell id, %d, %s", ret,
+                    SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+        } else {
+            LOGD("cellid : %d", cellid);
+            m_cell_id = cellid;
+        }
+
+        ret = tel_get_property_int(handle, TAPI_PROP_NETWORK_LAC, &lac);
+        if (ret != TAPI_API_SUCCESS) {
+            LOGE("Failed to get lac, %d, %s", ret,
+                    SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+        } else {
+            LOGD("lac : %d", lac);
+            m_lac = lac;
+        }
+
+    } catch (...) {
+        if (NULL != profile_handle) {
+            connection_profile_destroy(profile_handle);
+        }
+        connection_destroy(connection_handle);
+        tel_deinit(handle);
+        throw;
+    }
+    if (NULL != profile_handle) {
+        connection_profile_destroy(profile_handle);
+    }
+    connection_destroy(connection_handle);
+    tel_deinit(handle);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoCellularNetwork.h b/src/Systeminfo/SystemInfoCellularNetwork.h
new file mode 100755 (executable)
index 0000000..a5a3583
--- /dev/null
@@ -0,0 +1,70 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_CELLULAR_NETWORK_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_CELLULAR_NETWORK_H__
+
+#include <memory>
+#include <ITapiSim.h>
+#include <string>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoCellularNetwork;
+typedef std::shared_ptr<SystemInfoCellularNetwork> SystemInfoCellularNetworkPtr;
+
+class SystemInfoCellularNetwork : public SystemInfoProperty {
+public:
+    SystemInfoCellularNetwork(TapiHandle **tapi_handle);
+    virtual ~SystemInfoCellularNetwork();
+
+    std::string getStatus() const;
+    std::string getApn() const;
+    std::string getIpAddress() const;
+    std::string getIpv6Address() const;
+    unsigned short getMcc() const;
+    unsigned short getMnc() const;
+    unsigned short getCellId() const;
+    unsigned short getLac() const;
+    bool isRoaming() const;
+    bool isFlightMode() const;
+    std::string getImei() const;
+
+private:
+    std::string m_status;
+    std::string m_apn;
+    std::string m_ip_address;
+    std::string m_ipv6_address;
+    unsigned short m_mcc;
+    unsigned short m_mnc;
+    unsigned short m_cell_id;
+    unsigned short m_lac;
+    bool m_is_roaming;
+    bool m_is_flight_mode;
+    std::string m_imei;
+
+    void fetchVconfSettings();
+    void fetchConnection(TapiHandle **tapi_handle);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_CELLULAR_NETWORK_H__
diff --git a/src/Systeminfo/SystemInfoCpu.cpp b/src/Systeminfo/SystemInfoCpu.cpp
new file mode 100755 (executable)
index 0000000..c5458d3
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SystemInfoCpu.h"
+#include "SystemInfoUtil.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+SystemInfoCpu::SystemInfoCpu(CpuInfo & _cpu_info) :
+                m_load(fetchLoad(_cpu_info))
+{
+    LOGD("Entered");
+}
+
+SystemInfoCpu::~SystemInfoCpu()
+{
+    LOGD("Entered");
+}
+
+double SystemInfoCpu::getLoad() const
+{
+    return m_load;
+}
+
+double SystemInfoCpu::fetchLoad(CpuInfo & _cpu_info)
+{
+    LOGD("Entered");
+
+    FILE *fp = NULL;
+    fp = fopen("/proc/stat", "r");
+    if (fp == NULL) {
+        std::string error_msg("Can not open /proc/stat for reading");
+        LOGE("%s", error_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, error_msg);
+    }
+
+    long long usr = 0;
+    long long system = 0;
+    long long nice = 0;
+    long long idle = 0;
+    double load = 0;
+
+    int read_ret = fscanf(fp, "%*s %lld %lld %lld %lld", &usr, &system, &nice, &idle);
+    fclose(fp);
+
+    if (4 == read_ret) {
+        long long total = usr + nice + system + idle - _cpu_info.usr - _cpu_info.nice
+                - _cpu_info.system - _cpu_info.idle;
+        long long diff_idle = idle - _cpu_info.idle;
+        if ((total > 0LL) && (diff_idle > 0LL)) {
+            load = static_cast<double>(diff_idle) / total * 100LL;
+            _cpu_info.usr = usr;
+            _cpu_info.system = system;
+            _cpu_info.nice = nice;
+            _cpu_info.idle = idle;
+            _cpu_info.load = load;
+        } else {
+            LOGW("Cannot calculate cpu load, previous value returned");
+            load = _cpu_info.load;
+        }
+    } else {
+        std::string error_msg("Could not read /proc/stat");
+        LOGE("%s", error_msg.c_str());
+        throw Common::UnknownException(error_msg.c_str());
+    }
+
+    LOGD("Cpu load : %f", load);
+    return load / 100.0;
+}
+
+} // namespace SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoCpu.h b/src/Systeminfo/SystemInfoCpu.h
new file mode 100755 (executable)
index 0000000..9244dc6
--- /dev/null
@@ -0,0 +1,46 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_CPU_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_CPU_H__
+
+#include <memory>
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoCpu;
+typedef std::shared_ptr<SystemInfoCpu> SystemInfoCpuPtr;
+
+class SystemInfoCpu : public SystemInfoProperty {
+public:
+    SystemInfoCpu(CpuInfo & _cpu_info);
+    virtual ~SystemInfoCpu();
+
+    double getLoad() const;
+
+private:
+
+    double m_load;
+    double fetchLoad(CpuInfo & _cpu_info);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif // __TIZEN_SYSTEMINFO_SYSTEMINFO_CPU_H__
diff --git a/src/Systeminfo/SystemInfoDeviceCapability.cpp b/src/Systeminfo/SystemInfoDeviceCapability.cpp
new file mode 100755 (executable)
index 0000000..2720786
--- /dev/null
@@ -0,0 +1,1176 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <fstream>
+#include <system_info.h>
+#include <system_info_internal.h>
+
+#include "SystemInfoDeviceCapability.h"
+#include "SystemInfoUtil.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+
+#ifdef PROFILE_MOBILE
+const char* DEVICE_PROFILE = "MOBILE";
+#elif PROFILE_MOBILE_FULL
+const char* DEVICE_PROFILE = "MOBILE_FULL"; //TODO to be removed
+#elif PROFILE_MOBILE_WEB
+const char* DEVICE_PROFILE = "MOBILE_WEB"; //TODO to be removed
+#elif PROFILE_WEARABLE
+const char* DEVICE_PROFILE = "WEARABLE";
+#elif PROFILE_TV
+const char* DEVICE_PROFILE = "TV";
+#else
+const char* DEVICE_PROFILE = "";
+#endif
+
+const char* OPENGLES_TEXTURE_DELIMITER = "/";
+const char* OPENGLES_TEXTURE_UTC = "utc";
+const char* OPENGLES_TEXTURE_PTC = "ptc";
+const char* OPENGLES_TEXTURE_ETC = "etc";
+const char* OPENGLES_TEXTURE_3DC = "3dc";
+const char* OPENGLES_TEXTURE_ATC = "atc";
+const char* OPENGLES_TEXTURE_PVRTC = "pvrtc";
+}
+
+SystemInfoDeviceCapability::SystemInfoDeviceCapability()
+{
+    LOGD("Entered");
+}
+
+SystemInfoDeviceCapability::~SystemInfoDeviceCapability()
+{
+    LOGD("Entered");
+}
+
+bool SystemInfoDeviceCapability::isAccount()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/account");
+}
+
+bool SystemInfoDeviceCapability::isArchive()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/archive");
+}
+
+bool SystemInfoDeviceCapability::isBadge()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/badge");
+}
+
+bool SystemInfoDeviceCapability::isBookmark()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/bookmark");
+}
+
+bool SystemInfoDeviceCapability::isCalendar()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/calendar");
+}
+
+bool SystemInfoDeviceCapability::isContact()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/contact");
+}
+
+bool SystemInfoDeviceCapability::isDataControl()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/datacontrol");
+}
+
+bool SystemInfoDeviceCapability::isDataSync()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/datasync");
+}
+
+bool SystemInfoDeviceCapability::isDownload()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/download");
+}
+
+bool SystemInfoDeviceCapability::isExif()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/exif");
+}
+
+bool SystemInfoDeviceCapability::isMessagingEmail()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/email");
+}
+
+bool SystemInfoDeviceCapability::isBluetooth()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.bluetooth");
+}
+
+bool SystemInfoDeviceCapability::isBluetoothAudioCall()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.bluetooth.audio.call");
+}
+
+bool SystemInfoDeviceCapability::isBluetoothAudioMedia()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.bluetooth.audio.media");
+}
+
+bool SystemInfoDeviceCapability::isBluetootHealth()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.bluetooth.health");
+}
+
+bool SystemInfoDeviceCapability::isBluetootHID()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.bluetooth.hid");
+}
+
+bool SystemInfoDeviceCapability::isBluetootLE()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.bluetooth.le");
+}
+
+bool SystemInfoDeviceCapability::isBluetootOPP()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.bluetooth.opp");
+}
+
+bool SystemInfoDeviceCapability::isBluetoothAlwaysOn()
+{
+    LOGD("Entered");
+#ifdef FEATURE_OPTIONAL_BT_ALWAYS_ON
+    return true;
+#else
+    return false;
+#endif
+}
+
+std::string SystemInfoDeviceCapability::isCoreAPIVersion()
+{
+    LOGD("Entered");
+    return "2.3";
+}
+
+bool SystemInfoDeviceCapability::isNfc()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.nfc");
+}
+
+bool SystemInfoDeviceCapability::isNfcEmulation()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.nfc.card_emulation");
+}
+
+bool SystemInfoDeviceCapability::isPush()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.push");
+}
+
+bool SystemInfoDeviceCapability::isSecureElement()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.secure_element");
+}
+
+bool SystemInfoDeviceCapability::isTelephony()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.telephony");
+}
+
+bool SystemInfoDeviceCapability::isTelephonyMMS()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.telephony.mms");
+}
+
+bool SystemInfoDeviceCapability::isNotification()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/notification");
+}
+
+bool SystemInfoDeviceCapability::isWebSetting()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/websetting");
+}
+
+bool SystemInfoDeviceCapability::isSystemSetting()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/systemsetting");
+}
+
+bool SystemInfoDeviceCapability::isSystemSettingHomeScreen()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/systemsetting.home_screen");
+}
+
+bool SystemInfoDeviceCapability::isSystemSettingLockScreen()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/systemsetting.lock_screen");
+}
+
+bool SystemInfoDeviceCapability::isSystemSettingIncomingCall()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/systemsetting.incoming_call");
+}
+
+bool SystemInfoDeviceCapability::isSystemSettingNotificationEmail()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/systemsetting.notification_email");
+}
+
+bool SystemInfoDeviceCapability::isBattery()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/battery");
+}
+
+bool SystemInfoDeviceCapability::isAccelerometer()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.accelerometer");
+}
+
+bool SystemInfoDeviceCapability::isAccelerometerWakeup()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.accelerometer.wakeup");
+}
+
+bool SystemInfoDeviceCapability::isActivityRecognition()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.activity_recognition");
+}
+
+bool SystemInfoDeviceCapability::isBarometer()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.barometer");
+}
+
+bool SystemInfoDeviceCapability::isBarometerWakeup()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.barometer.wakeup");
+}
+
+bool SystemInfoDeviceCapability::isGestureRecognition()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.gesture_recognition");
+}
+
+bool SystemInfoDeviceCapability::isGravity()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.gravity");
+}
+
+bool SystemInfoDeviceCapability::isGyroscope()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.gyroscope");
+}
+
+bool SystemInfoDeviceCapability::isGyroscopeWakeup()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.gyroscope.wakeup");
+}
+
+bool SystemInfoDeviceCapability::isHumidity()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.humidity");
+}
+
+bool SystemInfoDeviceCapability::isLinearAcceleration()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.linear_acceleration");
+}
+
+bool SystemInfoDeviceCapability::isMagnetometer()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.magnetometer");
+}
+
+bool SystemInfoDeviceCapability::isMagnetometerWakeup()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.magnetometer.wakeup");
+}
+
+bool SystemInfoDeviceCapability::isPhotometer()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.photometer");
+}
+
+bool SystemInfoDeviceCapability::isPhotometerWakeup()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.photometer.wakeup");
+}
+
+bool SystemInfoDeviceCapability::isProximity()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.proximity");
+}
+
+bool SystemInfoDeviceCapability::isProximityWakeup()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.proximity.wakeup");
+}
+
+bool SystemInfoDeviceCapability::isTiltmeter()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.tiltmeter");
+}
+
+bool SystemInfoDeviceCapability::isTiltmeterWakeup()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.tiltmeter.wakeup");
+}
+
+bool SystemInfoDeviceCapability::isRotationVector()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.rotation_vector");
+}
+
+bool SystemInfoDeviceCapability::isTemperature()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.temperature");
+}
+
+bool SystemInfoDeviceCapability::isUltraviolet()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.ultraviolet");
+}
+
+bool SystemInfoDeviceCapability::isPedometer()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.pedometer");
+}
+
+bool SystemInfoDeviceCapability::isWristUp()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.wrist_up");
+}
+
+bool SystemInfoDeviceCapability::isHumanActivityMonitor()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/humanactivitymonitor");
+}
+
+bool SystemInfoDeviceCapability::isHrm()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sensor.heart_rate_monitor");
+}
+
+bool SystemInfoDeviceCapability::isCamera()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/camera");
+}
+
+bool SystemInfoDeviceCapability::isCameraFront()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/camera.front");
+}
+
+bool SystemInfoDeviceCapability::isCameraFrontFlash()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/camera.front.flash");
+}
+
+bool SystemInfoDeviceCapability::isCameraBack()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/camera.back");
+}
+
+bool SystemInfoDeviceCapability::isCameraBackFlash()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/camera.back.flash");
+}
+
+bool SystemInfoDeviceCapability::isFmRadio()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/fmradio");
+}
+
+bool SystemInfoDeviceCapability::isGraphicsAcceleration()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/graphics.acceleration");
+}
+
+bool SystemInfoDeviceCapability::isLed()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/led");
+}
+
+bool SystemInfoDeviceCapability::isInputKeyboard()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/input.keyboard");
+}
+
+bool SystemInfoDeviceCapability::isInputKeyboardLayout()
+{
+    LOGD("Entered");
+    std::string input_keyboard_layout = getValueString("tizen.org/feature/input.keyboard.layout");
+
+    bool input_keyboard = getValueBool("tizen.org/feature/input.keyboard");
+
+    // according to SystemInfo-DeviceCapabilities-dependency-table
+    // inputKeyboard   inputKeyboardLayout
+    //  O               O                   Possible
+    //  O               X                   Possible
+    //  X               X                   Possible
+    //  X               O                   Impossible
+
+    return input_keyboard ? !(input_keyboard_layout.empty()) : false;
+}
+
+std::string SystemInfoDeviceCapability::getInputKeyboardLayout()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/feature/input.keyboard.layout");
+}
+
+bool SystemInfoDeviceCapability::isLocation()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/location");
+}
+
+bool SystemInfoDeviceCapability::isLocationGps()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/location.gps");
+}
+
+bool SystemInfoDeviceCapability::isLocationWps()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/location.wps");
+}
+
+bool SystemInfoDeviceCapability::isLocationBatch()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/location.batch");
+}
+
+bool SystemInfoDeviceCapability::isMultimediaTranscoder()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/multimedia.transcoder");
+}
+
+bool SystemInfoDeviceCapability::isMicrophone()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/microphone");
+}
+
+bool SystemInfoDeviceCapability::isMultiTouchPinchZoon()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/multi_point_touch.pinch_zoom");
+}
+
+unsigned short SystemInfoDeviceCapability::getMultiTouchCount()
+{
+    LOGD("Entered");
+    return getValueInt("tizen.org/feature/multi_point_touch.point_count");
+}
+
+bool SystemInfoDeviceCapability::isNfcReservedPush()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.nfc.reserved_push");
+}
+
+bool SystemInfoDeviceCapability::isTelephonySMS()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.telephony.sms");
+}
+
+bool SystemInfoDeviceCapability::isWifi()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.wifi");
+}
+
+bool SystemInfoDeviceCapability::isWifiDirect()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/network.wifi.direct");
+}
+
+bool SystemInfoDeviceCapability::isAutoRotation()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.auto_rotation");
+}
+unsigned short SystemInfoDeviceCapability::getScreenBpp()
+{
+    LOGD("Entered");
+    return getValueInt("tizen.org/feature/screen.bpp");
+}
+
+bool SystemInfoDeviceCapability::isScreen()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.all");
+}
+
+bool SystemInfoDeviceCapability::isScreenCoordinateSystemSizeLarge()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.coordinate_system.size.large");
+}
+
+bool SystemInfoDeviceCapability::isScreenCoordinateSystemSizeNormal()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.coordinate_system.size.normal");
+}
+
+unsigned short SystemInfoDeviceCapability::getScreenDpi()
+{
+    LOGD("Entered");
+    return getValueInt("tizen.org/feature/screen.dpi");
+}
+
+bool SystemInfoDeviceCapability::isScreenOutputHdmi()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.output.hdmi");
+}
+
+bool SystemInfoDeviceCapability::isScreenOutputRca()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.output.rca");
+}
+
+bool SystemInfoDeviceCapability::isUsbAccessory()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/usb.accessory");
+}
+
+bool SystemInfoDeviceCapability::isUsbHost()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/usb.host");
+}
+
+bool SystemInfoDeviceCapability::isWebService()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/web.service");
+}
+
+unsigned short SystemInfoDeviceCapability::getScreenHeight()
+{
+    LOGD("Entered");
+    int height = getValueInt("tizen.org/feature/screen.height");
+    return height;
+}
+
+bool SystemInfoDeviceCapability::isScreenSizeAll()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.all");
+}
+
+bool SystemInfoDeviceCapability::isScreenSizeLarge()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.large");
+}
+
+bool SystemInfoDeviceCapability::isScreenSizeNormal()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal");
+}
+
+bool SystemInfoDeviceCapability::isScreenSize320_320()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal.320.320");
+}
+
+bool SystemInfoDeviceCapability::isScreenSize240_400()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal.240.400");
+}
+
+bool SystemInfoDeviceCapability::isScreenSize320_480()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal.320.480");
+}
+
+bool SystemInfoDeviceCapability::isScreenSize360_480()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal.360.480");
+}
+
+bool SystemInfoDeviceCapability::isScreenSize540_960()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal.540.960");
+}
+
+bool SystemInfoDeviceCapability::isScreenSize600_1024()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal.600.1024");
+}
+
+bool SystemInfoDeviceCapability::isScreenSize480_800()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal.480.800");
+}
+
+bool SystemInfoDeviceCapability::isScreenSize720_1280()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal.720.1280");
+}
+
+bool SystemInfoDeviceCapability::isScreenSize1080_1920()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/screen.size.normal.1080.1920");
+}
+
+unsigned short SystemInfoDeviceCapability::getScreenWidth()
+{
+    LOGD("Entered");
+    int width = getValueInt("tizen.org/feature/screen.width");
+    return width;
+}
+
+bool SystemInfoDeviceCapability::isDataEncryption()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/database.encryption");
+}
+
+bool SystemInfoDeviceCapability::isNativeOspCompatible()
+{
+    LOGD("Entered");
+#ifdef PROFILE_WEARABLE
+    return false;
+#else
+    return getValueBool("tizen.org/feature/platform.native.osp_compatible");
+#endif
+}
+
+std::string SystemInfoDeviceCapability::getOpenglesTextureFormat()
+{
+    LOGD("Entered");
+    if (!getValueBool("tizen.org/feature/opengles")) {
+        // this exception is converted to "Undefined" value in JS layer
+        std::string log_msg = "OpenGL-ES is not supported";
+        LOGE("%s", log_msg.c_str());
+    }
+    std::string texture_format = "";
+    if (getValueBool("tizen.org/feature/opengles.texture_format.utc")) {
+        texture_format += OPENGLES_TEXTURE_UTC;
+    }
+    if (getValueBool("tizen.org/feature/opengles.texture_format.ptc")) {
+        if (!texture_format.empty()) {
+            texture_format += OPENGLES_TEXTURE_DELIMITER;
+        }
+        texture_format += OPENGLES_TEXTURE_PTC;
+    }
+    if (getValueBool("tizen.org/feature/opengles.texture_format.etc")) {
+        if (!texture_format.empty()) {
+            texture_format += OPENGLES_TEXTURE_DELIMITER;
+        }
+        texture_format += OPENGLES_TEXTURE_ETC;
+    }
+    if (getValueBool("tizen.org/feature/opengles.texture_format.3dc")) {
+        if (!texture_format.empty()) {
+            texture_format += OPENGLES_TEXTURE_DELIMITER;
+        }
+        texture_format += OPENGLES_TEXTURE_3DC;
+    }
+    if (getValueBool("tizen.org/feature/opengles.texture_format.atc")) {
+        if (!texture_format.empty()) {
+            texture_format += OPENGLES_TEXTURE_DELIMITER;
+        }
+        texture_format += OPENGLES_TEXTURE_ATC;
+    }
+    if (getValueBool("tizen.org/feature/opengles.texture_format.pvrtc")) {
+        if (!texture_format.empty()) {
+            texture_format += OPENGLES_TEXTURE_DELIMITER;
+        }
+        texture_format += OPENGLES_TEXTURE_PVRTC;
+    }
+    if (texture_format.empty()) {
+        // this exception is converted to "Undefined" value in JS layer
+        std::string log_msg = "Platform error while getting OpenGL-ES texture format";
+        LOGE("%s", log_msg.c_str());
+    }
+    return texture_format;
+}
+
+bool SystemInfoDeviceCapability::isOpenglesTextureFormat3DC()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/opengles.texture_format.3dc");
+}
+
+bool SystemInfoDeviceCapability::isOpenglesTextureFormatATC()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/opengles.texture_format.atc");
+}
+
+bool SystemInfoDeviceCapability::isOpenglesTextureFormatETC()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/opengles.texture_format.etc");
+}
+
+bool SystemInfoDeviceCapability::isOpenglesTextureFormatPTC()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/opengles.texture_format.ptc");
+}
+
+bool SystemInfoDeviceCapability::isOpenglesTextureFormatPVRTC()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/opengles.texture_format.pvrtc");
+}
+
+bool SystemInfoDeviceCapability::isOpenglesTextureFormatUTC()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/opengles.texture_format.utc");
+}
+
+bool SystemInfoDeviceCapability::isOpengles()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/opengles");
+}
+
+bool SystemInfoDeviceCapability::isOpenglesVersion11()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/opengles.version.1_1");
+}
+
+bool SystemInfoDeviceCapability::isOpenglesVersion20()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/opengles.version.2_0");
+}
+
+bool SystemInfoDeviceCapability::isShellAppWidget()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/shell.appwidget");
+}
+
+bool SystemInfoDeviceCapability::isSipVoip()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/sip.voip");
+}
+
+bool SystemInfoDeviceCapability::isSpeechRecognition()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/speech.recognition");
+}
+
+bool SystemInfoDeviceCapability::isSpeechSynthesis()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/speech.synthesis");
+}
+
+bool SystemInfoDeviceCapability::isVisionFaceRecognition()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/vision.face_recognition");
+}
+
+bool SystemInfoDeviceCapability::isVisionImageRecognition()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/vision.image_recognition");
+}
+
+bool SystemInfoDeviceCapability::isVisionQrcodeGeneration()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/vision.qrcode_generation");
+}
+
+bool SystemInfoDeviceCapability::isVisionQrcodeRecognition()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/vision.qrcode_recognition");
+}
+
+std::string SystemInfoDeviceCapability::getPlatfomCoreCpuArch()
+{
+    LOGD("Entered");
+    std::string result = "";
+    if (getValueBool("tizen.org/feature/platform.core.cpu.arch.armv6")) {
+        result = "armv6";
+    }
+    if (getValueBool("tizen.org/feature/platform.core.cpu.arch.armv7")) {
+        if (!result.empty()) {
+            result += " | armv7";
+        } else {
+            result = "armv7";
+        }
+    }
+    if (getValueBool("tizen.org/feature/platform.core.cpu.arch.x86")) {
+        if (!result.empty()) {
+            result += " | x86";
+        } else {
+            result = "x86";
+        }
+    }
+    if (result.empty()) {
+        LOGE("Platform error while retrieving platformCoreCpuArch: result is empty");
+    }
+    return result;
+}
+
+bool SystemInfoDeviceCapability::getPlatfomCoreCpuArchArmv7()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/platform.core.cpu.arch.armv7");
+}
+
+bool SystemInfoDeviceCapability::getPlatfomCoreCpuArchArmv6()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/platform.core.cpu.arch.armv6");
+}
+
+bool SystemInfoDeviceCapability::getPlatfomCoreCpuArchX86()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/platform.core.cpu.arch.x86");
+}
+
+long SystemInfoDeviceCapability::getPlatformCoreCpuFrequency()
+{
+    LOGD("Entered");
+    double freq = 0;
+    int ret = 0;
+
+    ret = system_info_get_value_double(SYSTEM_INFO_KEY_CORE_CPU_FREQ, &freq);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        LOGE("Failed to get cpu frequency, %d, %s", ret, SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+    } else {
+        LOGD("cpu frequency : %d", freq);
+    }
+
+    return static_cast<long>(freq);
+}
+
+std::string SystemInfoDeviceCapability::getPlatfomCoreFpuArch()
+{
+    LOGD("Entered");
+    std::string result = "";
+    if (getValueBool("tizen.org/feature/platform.core.fpu.arch.sse2")) {
+        result = "sse2";
+    }
+    if (getValueBool("tizen.org/feature/platform.core.fpu.arch.sse3")) {
+        if (!result.empty()) {
+            result += " | sse3";
+        } else {
+            result = "sse3";
+        }
+    }
+    if (getValueBool("tizen.org/feature/platform.core.fpu.arch.ssse3")) {
+        if (!result.empty()) {
+            result += " | ssse3";
+        } else {
+            result = "ssse3";
+        }
+    }
+    if (getValueBool("tizen.org/feature/platform.core.fpu.arch.vfpv2")) {
+        if (!result.empty()) {
+            result += " | vfpv2";
+        } else {
+            result = "vfpv2";
+        }
+    }
+    if (getValueBool("tizen.org/feature/platform.core.fpu.arch.vfpv3")) {
+        if (!result.empty()) {
+            result += " | vfpv3";
+        } else {
+            result = "vfpv3";
+        }
+    }
+    if (result.empty()) {
+        LOGE("Platform error while retrieving platformCoreFpuArch: result is empty");
+    }
+    return result;
+}
+
+bool SystemInfoDeviceCapability::getPlatfomCoreFpuArchSSE2()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/platform.core.fpu.arch.sse2");
+}
+
+bool SystemInfoDeviceCapability::getPlatfomCoreFpuArchSSE3()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/platform.core.fpu.arch.sse3");
+}
+
+bool SystemInfoDeviceCapability::getPlatfomCoreFpuArchSSSE3()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/platform.core.fpu.arch.ssse3");
+}
+
+bool SystemInfoDeviceCapability::getPlatfomCoreFpuArchVFPV2()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/platform.core.fpu.arch.vfpv2");
+}
+
+bool SystemInfoDeviceCapability::getPlatfomCoreFpuArchVFPV3()
+{
+    LOGD("Entered");
+    return getValueBool("tizen.org/feature/platform.core.fpu.arch.vfpv3");
+}
+
+std::string SystemInfoDeviceCapability::getWebApiVersion()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/feature/platform.web.api.version");
+}
+
+std::string SystemInfoDeviceCapability::getPlatformVersionName()
+{
+    LOGD("Entered");
+    return "";
+}
+
+std::string SystemInfoDeviceCapability::getPlatformName()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/system/platform.name");
+}
+
+std::string SystemInfoDeviceCapability::getProfile()
+{
+    LOGD("Entered");
+    return DEVICE_PROFILE;
+}
+
+std::string SystemInfoDeviceCapability::getDuid()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/system/tizenid");
+}
+
+std::string SystemInfoDeviceCapability::getPlatformVersion()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/feature/platform.version");
+}
+
+std::string SystemInfoDeviceCapability::getNativeApiVersion()
+{
+    LOGD("Entered");
+#ifdef PROFILE_WEARABLE
+    return "";
+#else
+    return getValueString("tizen.org/feature/platform.native.api.version");
+#endif
+}
+
+std::string SystemInfoDeviceCapability::getBuildDate()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/system/build.date");
+}
+
+std::string SystemInfoDeviceCapability::getBuildString()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/system/build.string");
+}
+
+std::string SystemInfoDeviceCapability::getBuildTime()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/system/build.time");
+}
+
+std::string SystemInfoDeviceCapability::getBuildManafacture()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/system/manufacturer");
+}
+
+std::string SystemInfoDeviceCapability::getModelName()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/system/model_name");
+}
+
+std::string SystemInfoDeviceCapability::getPlatformCommunicationProcessor()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/system/platform.communication_processor");
+}
+
+std::string SystemInfoDeviceCapability::getPlatformProcessor()
+{
+    LOGD("Entered");
+    return getValueString("tizen.org/system/platform.processor");
+}
+
+bool SystemInfoDeviceCapability::getValueBool(const char *key)
+{
+    bool value = false;
+
+    int ret = system_info_get_platform_bool(key, &value);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        std::string log_msg = "Platform error while getting bool value: ";
+        log_msg += std::string(key);
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+        SystemInfoUtil::throwSystemInfoException(ret, log_msg);
+    }
+
+    LOGD("value[%s]: %s", key, value ? "true" : "false");
+    return value;
+}
+
+int SystemInfoDeviceCapability::getValueInt(const char *key)
+{
+    int value = 0;
+
+    int ret = system_info_get_platform_int(key, &value);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        std::string log_msg = "Platform error while getting int value: ";
+        log_msg += std::string(key);
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+        SystemInfoUtil::throwSystemInfoException(ret, log_msg);
+    }
+
+    LOGD("value[%s]: %d", key, value);
+    return value;
+}
+
+std::string SystemInfoDeviceCapability::getValueString(const char *key)
+{
+    char* value = NULL;
+    std::string str_value = "";
+
+    int ret = system_info_get_platform_string(key, &value);
+    if (ret == SYSTEM_INFO_ERROR_NONE) {
+        if (value != NULL) {
+            str_value = value;
+            free(value);
+            value = NULL;
+        }
+    } else {
+        std::string log_msg = "Platform error while getting string value: ";
+        log_msg += std::string(key);
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+        SystemInfoUtil::throwSystemInfoException(ret, log_msg);
+    }
+
+    LOGD("value[%s]: %s", key, value);
+    return str_value;
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoDeviceCapability.h b/src/Systeminfo/SystemInfoDeviceCapability.h
new file mode 100755 (executable)
index 0000000..03d81c7
--- /dev/null
@@ -0,0 +1,262 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_DEVICE_CAPABILITY_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_DEVICE_CAPABILITY_H__
+
+#include <string>
+#include <memory>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoDeviceCapability;
+typedef std::shared_ptr<SystemInfoDeviceCapability> SystemInfoDeviceCapabilityPtr;
+
+typedef unsigned char byte;
+
+class SystemInfoDeviceCapability {
+public:
+    SystemInfoDeviceCapability();
+    virtual ~SystemInfoDeviceCapability();
+
+    /*API*/
+    bool isAccount();
+    bool isArchive();
+    bool isBadge();
+    bool isBookmark();
+    bool isCalendar();
+    bool isContact();
+    bool isDataControl();
+    bool isDataSync();
+    bool isDownload();
+    bool isExif();
+    bool isSystemSetting();
+    bool isSystemSettingHomeScreen();
+    bool isSystemSettingLockScreen();
+    bool isSystemSettingIncomingCall();
+    bool isSystemSettingNotificationEmail();
+    bool isWebSetting();
+    bool isMessagingEmail();
+    bool isTelephony();
+    bool isTelephonyMMS();
+    bool isNotification();
+
+    /*Battery*/
+    bool isBattery();
+
+    /*Camera*/
+    bool isCamera();
+    bool isCameraFront();
+    bool isCameraFrontFlash();
+    bool isCameraBack();
+    bool isCameraBackFlash();
+
+    /*Database*/
+    bool isDataEncryption();
+
+    /*Fm radio*/
+    bool isFmRadio();
+
+    /*Graphic*/
+    bool isGraphicsAcceleration();
+
+    /*LED*/
+    bool isLed();
+
+    /*Input*/
+    bool isInputKeyboard();
+    bool isInputKeyboardLayout();
+    std::string getInputKeyboardLayout();
+
+    /*Location*/
+    bool isLocation();
+    bool isLocationGps();
+    bool isLocationWps();
+    bool isLocationBatch();
+
+    /*Multimedia transcoder*/
+    bool isMultimediaTranscoder();
+
+    /*Microphone*/
+    bool isMicrophone();
+
+    /*Multi-touch*/
+    bool isMultiTouchPinchZoon();
+    unsigned short getMultiTouchCount();
+
+    /*Network*/
+    bool isBluetoothAlwaysOn();
+    bool isBluetooth();
+    bool isBluetoothAudioCall();
+    bool isBluetoothAudioMedia();
+    bool isBluetootHealth();
+    bool isBluetootHID();
+    bool isBluetootLE();
+    bool isBluetootOPP();
+    bool isNfc();
+    bool isNfcEmulation();
+    bool isNfcReservedPush();
+    bool isPush();
+    bool isSecureElement();
+    bool isWifi();
+    bool isWifiDirect();
+
+    /*OpenGL ES*/
+    bool isOpengles();
+    std::string getOpenglesTextureFormat();
+    bool isOpenglesTextureFormat3DC();
+    bool isOpenglesTextureFormatATC();
+    bool isOpenglesTextureFormatETC();
+    bool isOpenglesTextureFormatPTC();
+    bool isOpenglesTextureFormatPVRTC();
+    bool isOpenglesTextureFormatUTC();
+    bool isOpenglesVersion11();
+    bool isOpenglesVersion20();
+
+    /*Platform*/
+    std::string isCoreAPIVersion();
+    std::string getPlatfomCoreCpuArch();
+    bool getPlatfomCoreCpuArchArmv6();
+    bool getPlatfomCoreCpuArchArmv7();
+    bool getPlatfomCoreCpuArchX86();
+    long getPlatformCoreCpuFrequency();
+    std::string getPlatfomCoreFpuArch();
+    bool getPlatfomCoreFpuArchSSE2();
+    bool getPlatfomCoreFpuArchSSE3();
+    bool getPlatfomCoreFpuArchSSSE3();
+    bool getPlatfomCoreFpuArchVFPV2();
+    bool getPlatfomCoreFpuArchVFPV3();
+    std::string getNativeApiVersion();
+    bool isNativeOspCompatible();
+    std::string getPlatformVersion();
+    std::string getWebApiVersion();
+    std::string getPlatformVersionName();
+
+    /*Profile*/
+    std::string getProfile();
+
+    /*Screen*/
+    bool isAutoRotation();
+    unsigned short getScreenBpp();
+    bool isScreen();
+    bool isScreenCoordinateSystemSizeLarge();
+    bool isScreenCoordinateSystemSizeNormal();
+    unsigned short getScreenDpi();
+    unsigned short getScreenHeight();
+    bool isScreenOutputHdmi();
+    bool isScreenOutputRca();
+    bool isScreenSizeAll();
+    bool isScreenSizeLarge();
+    bool isScreenSizeNormal();
+    bool isScreenSize240_400();
+    bool isScreenSize320_320();
+    bool isScreenSize320_480();
+    bool isScreenSize360_480();
+    bool isScreenSize480_800();
+    bool isScreenSize540_960();
+    bool isScreenSize600_1024();
+    bool isScreenSize720_1280();
+    bool isScreenSize1080_1920();
+    unsigned short getScreenWidth();
+
+    /*Sensors*/
+    bool isAccelerometer();
+    bool isAccelerometerWakeup();
+    bool isActivityRecognition();
+    bool isBarometer();
+    bool isBarometerWakeup();
+    bool isGestureRecognition();
+    bool isGravity();
+    bool isGyroscope();
+    bool isGyroscopeWakeup();
+    bool isHrm();
+    bool isHumidity();
+    bool isLinearAcceleration();
+    bool isMagnetometer();
+    bool isMagnetometerWakeup();
+    bool isPedometer();
+    bool isPhotometer();
+    bool isPhotometerWakeup();
+//    bool isPressure();
+    bool isProximity();
+    bool isProximityWakeup();
+    bool isRotationVector();
+    bool isTemperature();
+    bool isTiltmeter();
+    bool isTiltmeterWakeup();
+    bool isUltraviolet();
+    bool isWristUp();
+    bool isHumanActivityMonitor();
+
+    /*Shell*/
+    bool isShellAppWidget();
+
+    /*Sip*/
+    bool isSipVoip();
+
+    /*Speech*/
+    bool isSpeechRecognition();
+    bool isSpeechSynthesis();
+
+    /*USB*/
+    bool isUsbAccessory();
+    bool isUsbHost();
+
+    /*Web service*/
+    bool isWebService();
+
+    /*Vision*/
+    bool isVisionFaceRecognition();
+    bool isVisionImageRecognition();
+    bool isVisionQrcodeGeneration();
+    bool isVisionQrcodeRecognition();
+
+    /*build information*/
+    std::string getBuildDate();
+    std::string getBuildString();
+    std::string getBuildTime();
+    std::string getBuildManafacture();
+
+    /*duid*/
+    std::string getDuid();
+
+    /*model name*/
+    std::string getModelName();
+
+    /*platform*/
+    std::string getPlatformName();
+    std::string getPlatformCommunicationProcessor();
+    std::string getPlatformProcessor();
+
+    //to be removed
+    bool isTelephonySMS();
+
+    std::string generateDuid();
+    std::string generateId(char* pDeviceString);
+    void generateCrc64(char* pDeviceString, unsigned long long int& value);
+    std::string base32Encode(byte* value);
+
+private:
+    bool getValueBool(const char *key);
+    int getValueInt(const char *key);
+    std::string getValueString(const char *key);
+};
+
+} // SystemInfo
+} // DeviceAPI
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_DEVICE_CAPABILITY_H__
diff --git a/src/Systeminfo/SystemInfoDeviceOrientation.cpp b/src/Systeminfo/SystemInfoDeviceOrientation.cpp
new file mode 100755 (executable)
index 0000000..bc94a1e
--- /dev/null
@@ -0,0 +1,166 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <vconf.h>
+#include <Logger.h>
+#include <PlatformException.h>
+#include "SystemInfoDeviceOrientation.h"
+#include "SystemInfo.h"
+#include "SystemInfoUtil.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+    const std::string ORIENTATION_PORTRAIT_PRIMARY = "PORTRAIT_PRIMARY";
+    const std::string ORIENTATION_PORTRAIT_SECONDARY = "PORTRAIT_SECONDARY";
+    const std::string ORIENTATION_LANDSCAPE_PRIMARY = "LANDSCAPE_PRIMARY";
+    const std::string ORIENTATION_LANDSCAPE_SECONDARY = "LANDSCAPE_SECONDARY";
+}
+
+SystemInfoDeviceOrientation::SystemInfoDeviceOrientation()
+{
+    LOGD("Entered");
+
+    m_status = fetchStatus();
+    m_is_auto_rotation = fetchIsAutoRotation();
+}
+
+SystemInfoDeviceOrientation::~SystemInfoDeviceOrientation()
+{
+    LOGD("Entered");
+}
+
+std::string SystemInfoDeviceOrientation::getStatus() const
+{
+    LOGD("Entered");
+    return m_status;
+}
+
+bool SystemInfoDeviceOrientation::isAutoRotation() const
+{
+    LOGD("Entered");
+    return m_is_auto_rotation;
+}
+
+std::string SystemInfoDeviceOrientation::fetchStatus()
+{
+    LOGD("Entered");
+    int rotation = 0;
+    std::string status = ORIENTATION_PORTRAIT_PRIMARY;
+
+    sensor_data_t data;
+    int handle = connectSensor();
+
+    int ret = sensord_get_data(handle, AUTO_ROTATION_BASE_DATA_SET, &data);
+    if (ret < 0) {
+        LOGE("Failed to get data(sensord_get_data)");
+    }
+
+    LOGD("size of the data value array:%d", data.value_count);
+    if (data.value_count > 0 ) {
+        rotation = data.values[0];
+        LOGD("ratation value : %d", rotation);
+    } else {
+        LOGE("Failed to get data : the size of array is less than 0");
+    }
+
+    switch (rotation) {
+        case AUTO_ROTATION_DEGREE_UNKNOWN:
+        case AUTO_ROTATION_DEGREE_0:
+            LOGD("AUTO_ROTATION_DEGREE_0");
+            status = ORIENTATION_PORTRAIT_PRIMARY;
+            break;
+        case AUTO_ROTATION_DEGREE_90:
+            LOGD("AUTO_ROTATION_DEGREE_90");
+            status = ORIENTATION_LANDSCAPE_PRIMARY;
+            break;
+        case AUTO_ROTATION_DEGREE_180:
+            LOGD("AUTO_ROTATION_DEGREE_180");
+            status = ORIENTATION_PORTRAIT_SECONDARY;
+            break;
+        case AUTO_ROTATION_DEGREE_270:
+            LOGD("AUTO_ROTATION_DEGREE_270");
+            status = ORIENTATION_LANDSCAPE_SECONDARY;
+            break;
+        default:
+            LOGE("Received unexpected data: %u", rotation);
+            throw Common::UnknownException("Received unexpected data");
+    }
+
+    disconnectSensor(handle);
+
+    return status;
+}
+
+bool SystemInfoDeviceOrientation::fetchIsAutoRotation()
+{
+    LOGD("Entered");
+    int is_auto_rotation = 0;
+    int ret = 0;
+
+    ret = vconf_get_bool(VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL, &is_auto_rotation);
+    if (ret == VCONF_OK) {
+        if (is_auto_rotation) {
+            return true;
+        }
+    } else {
+        std::string log_msg = "Failed to check VCONFKEY_SETAPPL_AUTO_ROTATE_SCREEN_BOOL";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+    return false;
+}
+
+int SystemInfoDeviceOrientation::connectSensor()
+{
+    LOGD("Entered");
+    sensor_t sensor;
+    sensor = sensord_get_sensor(AUTO_ROTATION_SENSOR);
+
+    int handle_orientation = sensord_connect(sensor);
+    if (handle_orientation < 0) {
+        std::string log_msg = "Failed to connect auto rotation sensor";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+
+    int state = sensord_start(handle_orientation, 0);
+    if(state < 0) {
+        sensord_disconnect(handle_orientation);
+        std::string log_msg = "Failed to start auto rotation sensor";
+        LOGE("%s", log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+    LOGD("Sensor starts successfully = %d", handle_orientation);
+    return handle_orientation;
+}
+
+void SystemInfoDeviceOrientation::disconnectSensor(int handle_orientation)
+{
+    LOGD("Entered");
+
+    int state = sensord_stop(handle_orientation);
+    LOGD("handle_orientation sf_stop state = %d", state);
+
+    state = sensord_disconnect(handle_orientation);
+    LOGD("handle_orientation sf_disconnect state = %d", state);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoDeviceOrientation.h b/src/Systeminfo/SystemInfoDeviceOrientation.h
new file mode 100755 (executable)
index 0000000..519d1f6
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_DEVICE_ORIENTATION_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_DEVICE_ORIENTATION_H__
+
+#include <memory>
+#include <sensor_internal.h>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoDeviceOrientation;
+
+typedef std::shared_ptr<SystemInfoDeviceOrientation> SystemInfoDeviceOrientationPtr;
+
+class SystemInfoDeviceOrientation: public SystemInfoProperty {
+public:
+    SystemInfoDeviceOrientation();
+    virtual ~SystemInfoDeviceOrientation();
+
+    std::string getStatus() const;
+    std::string fetchStatus();
+
+    static int connectSensor();
+    static void disconnectSensor(int handle_orientation);
+
+    bool isAutoRotation() const;
+    bool fetchIsAutoRotation();
+
+private:
+    std::string m_status;
+    bool m_is_auto_rotation;
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_DEVICE_ORIENTATION_H__
diff --git a/src/Systeminfo/SystemInfoDisplay.cpp b/src/Systeminfo/SystemInfoDisplay.cpp
new file mode 100755 (executable)
index 0000000..6f29a83
--- /dev/null
@@ -0,0 +1,178 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Logger.h>
+#include <vconf.h>
+#include <system_info.h>
+#include <system_info_internal.h>
+#include <PlatformException.h>
+#include "SystemInfoDisplay.h"
+#include "SystemInfoUtil.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+const double DISPLAY_BRIGHTNESS_DIVIDE_VALUE = 100;
+}
+
+SystemInfoDisplay::SystemInfoDisplay() :
+    m_resolution_width(0),
+    m_resolution_height(0),
+    m_dots_per_inch_width(0),
+    m_dots_per_inch_height(0),
+    m_physical_width(fetchPhysicalWidth()),
+    m_physical_height(fetchPhysicalHeight()),
+    m_brightness(fetchBrightness())
+{
+    LOGD("Entered");
+    fetchResolution();
+    fetchDotsPerInch();
+}
+
+SystemInfoDisplay::~SystemInfoDisplay()
+{
+    LOGD("Entered");
+}
+
+void SystemInfoDisplay::fetchResolution()
+{
+    LOGD("Entered");
+    int height = 0;
+    int width = 0;
+    int ret = 0;
+
+    ret = system_info_get_platform_int("tizen.org/feature/screen.width", &width);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        std::string log_msg = "Failed to get 'tizen.org/feature/screen.width' value";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+        SystemInfoUtil::throwSystemInfoException(ret, log_msg);
+    }
+    m_resolution_width = width;
+
+    ret = system_info_get_platform_int("tizen.org/feature/screen.height", &height);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        std::string log_msg = "Failed to get 'tizen.org/feature/screen.height' value";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+        SystemInfoUtil::throwSystemInfoException(ret, log_msg);
+    }
+    m_resolution_height = height;
+}
+
+void SystemInfoDisplay::fetchDotsPerInch()
+{
+    LOGD("Entered");
+    int dots_per_inch = 0;
+    int ret = 0;
+
+    ret = system_info_get_platform_int("tizen.org/feature/screen.dpi", &dots_per_inch);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        std::string log_msg = "Failed to get 'tizen.org/feature/screen.dpi' value";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+        SystemInfoUtil::throwSystemInfoException(ret, log_msg);
+    } else {
+        m_dots_per_inch_width = dots_per_inch;
+        m_dots_per_inch_height = dots_per_inch;
+    }
+}
+
+double SystemInfoDisplay::fetchPhysicalWidth()
+{
+    LOGD("Entered");
+    int physical_width = 0;
+    int ret = 0;
+
+    ret = system_info_get_value_int(SYSTEM_INFO_KEY_PHYSICAL_SCREEN_WIDTH, &physical_width);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        std::string log_msg = "Failed to get physical screen width value";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+    }
+
+    return physical_width;
+}
+
+double SystemInfoDisplay::fetchPhysicalHeight()
+{
+    LOGD("Entered");
+    int physical_height = 0;
+    int ret = 0;
+
+    ret = system_info_get_value_int(SYSTEM_INFO_KEY_PHYSICAL_SCREEN_HEIGHT, &physical_height);
+    if (ret != SYSTEM_INFO_ERROR_NONE) {
+        std::string log_msg = "Failed to get physical screen height value";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSystemInfoErrorMessage(ret).c_str());
+    }
+
+    return physical_height;
+}
+
+double SystemInfoDisplay::fetchBrightness()
+{
+    LOGD("Entered");
+    int brightness = 0;
+    int ret = 0;
+
+    ret = vconf_get_int(VCONFKEY_SETAPPL_LCD_BRIGHTNESS, &brightness);
+    if (ret != VCONF_OK) {
+        LOGE("Cannot get brightness value of display");
+    } else {
+        return static_cast<double>(brightness) / DISPLAY_BRIGHTNESS_DIVIDE_VALUE;
+    }
+    return brightness;
+}
+
+unsigned long SystemInfoDisplay::getResolutionWidth() const
+{
+    return m_resolution_width;
+}
+
+unsigned long SystemInfoDisplay::getResolutionHeight() const
+{
+    return m_resolution_height;
+}
+
+unsigned long SystemInfoDisplay::getDotsPerInchWidth() const
+{
+    return m_dots_per_inch_width;
+}
+
+unsigned long SystemInfoDisplay::getDotsPerInchHeight() const
+{
+    return m_dots_per_inch_height;
+}
+
+double SystemInfoDisplay::getPhysicalWidth() const
+{
+    return m_physical_width;
+}
+
+double SystemInfoDisplay::getPhysicalHeight() const
+{
+    return m_physical_height;
+}
+double SystemInfoDisplay::getBrightness() const
+{
+    return m_brightness;
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoDisplay.h b/src/Systeminfo/SystemInfoDisplay.h
new file mode 100755 (executable)
index 0000000..8283170
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_DISPLAY_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_DISPLAY_H__
+
+#include <memory>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoDisplay;
+typedef std::shared_ptr<SystemInfoDisplay> SystemInfoDisplayPtr;
+
+class SystemInfoDisplay : public SystemInfoProperty {
+public:
+    SystemInfoDisplay();
+    virtual ~SystemInfoDisplay();
+
+    unsigned long getResolutionWidth() const;
+    unsigned long getResolutionHeight() const;
+    unsigned long getDotsPerInchWidth() const;
+    unsigned long getDotsPerInchHeight() const;
+    double getPhysicalWidth() const;
+    double getPhysicalHeight() const;
+    double getBrightness() const;
+
+private:
+    void fetchResolution();
+    void fetchDotsPerInch();
+    double fetchPhysicalWidth();
+    double fetchPhysicalHeight();
+    double fetchBrightness();
+
+    unsigned long m_resolution_width;
+    unsigned long m_resolution_height;
+    unsigned long m_dots_per_inch_width;
+    unsigned long m_dots_per_inch_height;
+    double m_physical_width;
+    double m_physical_height;
+    double m_brightness;
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_DISPLAY_H__
diff --git a/src/Systeminfo/SystemInfoLocale.cpp b/src/Systeminfo/SystemInfoLocale.cpp
new file mode 100755 (executable)
index 0000000..81be0ef
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include <system_settings.h>
+
+#include "SystemInfoLocale.h"
+#include "SystemInfoUtil.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+SystemInfoLocale::SystemInfoLocale()
+{
+    LOGD("Entered");
+
+    m_language = fetchLanguage();
+    m_country = fetchCountry();
+}
+
+SystemInfoLocale::~SystemInfoLocale()
+{
+    LOGD("Entered");
+}
+
+std::string SystemInfoLocale::getLanguage() const
+{
+    return m_language;
+}
+
+std::string SystemInfoLocale::getCountry() const
+{
+    return m_country;
+}
+
+std::string SystemInfoLocale::fetchLanguage()
+{
+    LOGD("Entered");
+
+    char* language = NULL;
+    std::string str_language = "";
+    std::string log_msg = "";
+    int ret = 0;
+
+    ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_LANGUAGE, &language);
+    if (ret == SYSTEM_SETTINGS_ERROR_NONE) {
+        if (NULL != language) {
+            LOGD("language : %s", language);
+            str_language = language;
+            free(language);
+        }
+    } else {
+        log_msg = "Failed to get language info";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSettingErrorMessage(ret).c_str());
+        SystemInfoUtil::throwSettingException(ret, log_msg);
+    }
+    return str_language;
+}
+
+std::string SystemInfoLocale::fetchCountry()
+{
+    LOGD("Entered");
+
+    char* country = NULL;
+    std::string str_country = "";
+    std::string log_msg = "";
+    int ret = 0;
+
+    ret = system_settings_get_value_string(SYSTEM_SETTINGS_KEY_LOCALE_COUNTRY, &country);
+    if (ret == SYSTEM_SETTINGS_ERROR_NONE) {
+        if (NULL != country) {
+            LOGD("country : %s", country);
+            char* token = NULL;
+            token = strtok(country, ".");
+            if (NULL != token) {
+                str_country = token;
+            }
+            free(country);
+        }
+    } else {
+        log_msg = "Failed to get country info";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getSettingErrorMessage(ret).c_str());
+        SystemInfoUtil::throwSettingException(ret, log_msg);
+    }
+    return str_country;
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoLocale.h b/src/Systeminfo/SystemInfoLocale.h
new file mode 100755 (executable)
index 0000000..a25e85f
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_LOCALE_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_LOCALE_H__
+
+#include <memory>
+#include <string>
+#include <runtime_info.h>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoLocale;
+typedef std::shared_ptr<SystemInfoLocale> SystemInfoLocalePtr;
+
+class SystemInfoLocale : public SystemInfoProperty {
+public:
+    SystemInfoLocale();
+    virtual ~SystemInfoLocale();
+
+    std::string getLanguage() const;
+    std::string getCountry() const;
+
+private:
+    std::string m_language;
+    std::string m_country;
+
+    std::string fetchLanguage();
+    std::string fetchCountry();
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_LOCALE_H__
diff --git a/src/Systeminfo/SystemInfoMemory.cpp b/src/Systeminfo/SystemInfoMemory.cpp
new file mode 100755 (executable)
index 0000000..fa67f9d
--- /dev/null
@@ -0,0 +1,75 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <vconf.h>
+#include <PlatformException.h>
+#include <Logger.h>
+
+#include "SystemInfoMemory.h"
+#include "SystemInfoUtil.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+    const std::string MEMORY_STATE_NORMAL = "NORMAL";
+    const std::string MEMORY_STATE_WARNING = "WARNING";
+}
+
+SystemInfoMemory::SystemInfoMemory()
+{
+    LOGD("Entered");
+    m_status = fetchStatus();
+}
+
+SystemInfoMemory::~SystemInfoMemory()
+{
+    LOGD("Entered");
+}
+
+std::string SystemInfoMemory::getStatus() const
+{
+    return m_status;
+}
+
+std::string SystemInfoMemory::fetchStatus()
+{
+    LOGD("Entered");
+    int status = 0;
+
+    int ret = vconf_get_int(VCONFKEY_SYSMAN_LOW_MEMORY, &status);
+    if (ret != VCONF_OK) {
+        std::string log_msg = "Platform error while getting low memory status: ";
+        LOGE("%d, %s", ret, log_msg.c_str());
+        SystemInfoUtil::throwSystemInfoException(0, log_msg);
+    }
+
+    switch (status) {
+        case VCONFKEY_SYSMAN_LOW_MEMORY_NORMAL:
+            return MEMORY_STATE_NORMAL;
+        case VCONFKEY_SYSMAN_LOW_MEMORY_SOFT_WARNING:
+            return MEMORY_STATE_WARNING;
+        case VCONFKEY_SYSMAN_LOW_MEMORY_HARD_WARNING:
+            return MEMORY_STATE_WARNING;
+        default:
+            return MEMORY_STATE_NORMAL;
+    }
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoMemory.h b/src/Systeminfo/SystemInfoMemory.h
new file mode 100755 (executable)
index 0000000..cc288d3
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_MEMORY_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_MEMORY_H__
+
+#include <memory>
+#include <string>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoMemory;
+typedef std::shared_ptr<SystemInfoMemory> SystemInfoMemoryPtr;
+
+class SystemInfoMemory : public SystemInfoProperty {
+public:
+    SystemInfoMemory();
+    virtual ~SystemInfoMemory();
+
+    std::string getStatus() const;
+
+private:
+    std::string m_status;
+
+    std::string fetchStatus();
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_MEMORY_H__
diff --git a/src/Systeminfo/SystemInfoNetwork.cpp b/src/Systeminfo/SystemInfoNetwork.cpp
new file mode 100755 (executable)
index 0000000..3c72760
--- /dev/null
@@ -0,0 +1,187 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+
+#include <Logger.h>
+#include <vconf.h>
+#include <net_connection.h>
+#include <PlatformException.h>
+#include "SystemInfoNetwork.h"
+#include "SystemInfoUtil.h"
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+#include <ITapiNetwork.h>
+#endif
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+const char* NETWORK_TYPE_NONE = "NONE";
+const char* NETWORK_TYPE_2G = "2G";
+const char* NETWORK_TYPE_2_5G = "2.5G";
+const char* NETWORK_TYPE_3G = "3G";
+const char* NETWORK_TYPE_4G = "4G";
+const char* NETWORK_TYPE_WIFI = "WIFI";
+const char* NETWORK_TYPE_ETHERNET = "ETHERNET";
+const char* NETWORK_TYPE_UNKNOWN = "UNKNOWN";
+}
+
+SystemInfoNetwork::SystemInfoNetwork()
+{
+    LOGD("Entered");
+}
+
+SystemInfoNetwork::~SystemInfoNetwork()
+{
+    LOGD("Entered");
+}
+
+SystemInfoNetwork::NetworkType SystemInfoNetwork::getNetworkType() const
+{
+    LOGD("Entered");
+
+    connection_h connection_handle;
+    connection_type_e connection_type;
+    NetworkType type = NONE;
+    int ret = 0;
+
+    ret = connection_create(&connection_handle);
+    if (ret != CONNECTION_ERROR_NONE) {
+        std::string log_msg = "Failed to create connection";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+        SystemInfoUtil::throwConnectionException(ret, log_msg);
+    }
+
+    try {
+        ret = connection_get_type(connection_handle, &connection_type);
+        if (ret != CONNECTION_ERROR_NONE) {
+            std::string log_msg = "Failed to get connection type";
+            LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            SystemInfoUtil::throwConnectionException(ret, log_msg);
+        }
+
+        switch (connection_type) {
+            case CONNECTION_TYPE_DISCONNECTED:
+                type = NONE;
+                break;
+            case CONNECTION_TYPE_WIFI:
+                type = WIFI;
+                break;
+            case CONNECTION_TYPE_CELLULAR: {
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+                TapiHandle *handle = tel_init(NULL);
+                char **cp_list = NULL;
+                TelNetworkDefaultDataSubs_t default_subs = TAPI_NETWORK_DEFAULT_DATA_SUBS_SIM1;
+
+                ret = tel_get_network_default_data_subscription(handle, &default_subs);
+                if (ret != TAPI_API_SUCCESS) {
+                    LOGE("Failed to get default subscriber id, %d, %s", ret,
+                            SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+                } else {
+                    tel_deinit(handle);
+                    handle = NULL;
+
+                    cp_list = tel_get_cp_name_list();
+                    handle = tel_init(cp_list[default_subs]);
+                    if (handle == NULL) {
+                        LOGE("Failed to get handle");
+                    }
+                }
+
+                int svc_type = -1;
+                ret = tel_get_property_int(handle, TAPI_PROP_NETWORK_SERVICE_TYPE, &svc_type);
+                if (ret != TAPI_API_SUCCESS) {
+                    LOGE("Failed to get default service type, %d, %s", ret,
+                            SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+                }
+
+                LOGD("svc_type %d", svc_type);
+                switch (svc_type) {
+                    case TAPI_NETWORK_SERVICE_TYPE_2G:
+                        type = TYPE_2G;
+                        break;
+                    case TAPI_NETWORK_SERVICE_TYPE_2_5G:
+                    case TAPI_NETWORK_SERVICE_TYPE_2_5G_EDGE:
+                        type = TYPE_2_5G;
+                        break;
+                    case TAPI_NETWORK_SERVICE_TYPE_3G:
+                        type = TYPE_3G;
+                        break;
+                    case TAPI_NETWORK_SERVICE_TYPE_HSDPA:
+                    case TAPI_NETWORK_SERVICE_TYPE_LTE:
+                        type = TYPE_4G;
+                        break;
+                    default:
+                        type = NONE;
+                }
+                tel_deinit(handle);
+                handle = NULL;
+#else
+                type = NONE;
+#endif
+                break;
+            }
+            case CONNECTION_TYPE_ETHERNET:
+                type = ETHERNET;
+                break;
+            default:
+                LOGE("Incorrect type: %d", connection_type);
+                SystemInfoUtil::throwConnectionException(0, "Incorrect type");
+        }
+    } catch (...) {
+        connection_destroy(connection_handle);
+        SystemInfoUtil::throwConnectionException(0, "Cannot create get type");
+    }
+
+    connection_destroy(connection_handle);
+    return type;
+}
+
+std::string SystemInfoNetwork::getNetworkTypeString() const
+{
+    switch (getNetworkType()) {
+        case NONE:
+            return NETWORK_TYPE_NONE;
+        case TYPE_2G:
+            return NETWORK_TYPE_2G;
+        case TYPE_2_5G:
+            return NETWORK_TYPE_2_5G;
+        case TYPE_3G:
+            return NETWORK_TYPE_3G;
+        case TYPE_4G:
+            return NETWORK_TYPE_4G;
+        case WIFI:
+            return NETWORK_TYPE_WIFI;
+        case ETHERNET:
+            return NETWORK_TYPE_ETHERNET;
+        case UNKNOWN:
+            return NETWORK_TYPE_UNKNOWN;
+        default:
+            LOGE("Incorrect type: %d", getNetworkType());
+            SystemInfoUtil::throwConnectionException<TypeMismatchException>(0, "Incorrect type");
+    }
+    return "";
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoNetwork.h b/src/Systeminfo/SystemInfoNetwork.h
new file mode 100755 (executable)
index 0000000..cc69bbc
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_NETWORK_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_NETWORK_H__
+
+#include <memory>
+#include <string>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoNetwork;
+typedef std::shared_ptr<SystemInfoNetwork> SystemInfoNetworkPtr;
+
+class SystemInfoNetwork : public SystemInfoProperty {
+public:
+    SystemInfoNetwork();
+    virtual ~SystemInfoNetwork();
+
+    enum NetworkType {
+        NONE,
+        TYPE_2G,
+        TYPE_2_5G,
+        TYPE_3G,
+        TYPE_4G,
+        WIFI,
+        ETHERNET,
+        UNKNOWN
+    };
+    NetworkType getNetworkType() const;
+    std::string getNetworkTypeString() const;
+
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_NETWORK_H__
diff --git a/src/Systeminfo/SystemInfoPeripheral.cpp b/src/Systeminfo/SystemInfoPeripheral.cpp
new file mode 100755 (executable)
index 0000000..b254893
--- /dev/null
@@ -0,0 +1,62 @@
+#include "SystemInfoPeripheral.h"
+#include <PlatformException.h>
+#include <Logger.h>
+#include <vconf.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+SystemInfoPeripheral::SystemInfoPeripheral() :
+                m_is_video_output_on(fetchIsVideoOutputOn())
+{
+    LOGD("Entered");
+}
+
+SystemInfoPeripheral::~SystemInfoPeripheral()
+{
+    LOGD("Entered");
+}
+
+bool SystemInfoPeripheral::isVideoOutputOn() const
+{
+    return m_is_video_output_on;
+}
+
+bool SystemInfoPeripheral::fetchIsVideoOutputOn()
+{
+    LOGD("Entered");
+    int hdmi_status = 0, wireless_display_status = 0, popsync_status = 0;
+    int ret = 0;
+
+    ret = vconf_get_int(VCONFKEY_MIRACAST_WFD_SOURCE_STATUS, &wireless_display_status);
+    if (ret == VCONF_OK) {
+        if (VCONFKEY_MIRACAST_WFD_SOURCE_ON == wireless_display_status) {
+            return true;
+        }
+    } else {
+        LOGE("Failed to get wireless display status");
+    }
+
+    ret = vconf_get_int(VCONFKEY_SYSMAN_HDMI, &hdmi_status);
+    if (ret == VCONF_OK) {
+        if (VCONFKEY_SYSMAN_HDMI_CONNECTED == hdmi_status) {
+            return true;
+        }
+    } else {
+        LOGE("Failed to get hdmi status");
+    }
+
+    ret = vconf_get_int(VCONFKEY_POPSYNC_ACTIVATED_KEY, &popsync_status);
+    if (ret == VCONF_OK) {
+        if (1 == popsync_status) {
+            return true;
+        }
+    } else {
+        LOGE("Failed to get popsync status");
+    }
+
+    return false;
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoPeripheral.h b/src/Systeminfo/SystemInfoPeripheral.h
new file mode 100755 (executable)
index 0000000..433b8b2
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_PERIPHERAL_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_PERIPHERAL_H__
+
+#include <memory>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoPeripheral;
+typedef std::shared_ptr<SystemInfoPeripheral> SystemInfoPeripheralPtr;
+
+class SystemInfoPeripheral : public SystemInfoProperty {
+public:
+    SystemInfoPeripheral();
+    virtual ~SystemInfoPeripheral();
+
+    bool isVideoOutputOn() const;
+
+private:
+
+    bool m_is_video_output_on;
+
+    bool fetchIsVideoOutputOn();
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_PERIPHERAL_H__
diff --git a/src/Systeminfo/SystemInfoProperty.cpp b/src/Systeminfo/SystemInfoProperty.cpp
new file mode 100755 (executable)
index 0000000..92ba276
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SystemInfoProperty.h"
+#include "SystemInfoUtil.h"
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+SystemInfoPropertyId SystemInfoProperty::stringToPropertyId(const std::string& property_id)
+{
+    if ("BATTERY" == property_id) {
+        return SystemInfoPropertyId::BATTERY;
+    }
+    if ("CPU" == property_id) {
+        return SystemInfoPropertyId::CPU;
+    }
+    if ("STORAGE" == property_id) {
+        return SystemInfoPropertyId::STORAGE;
+    }
+    if ("DISPLAY" == property_id) {
+        return SystemInfoPropertyId::DISPLAY;
+    }
+    if ("DEVICE_ORIENTATION" == property_id) {
+        return SystemInfoPropertyId::DEVICE_ORIENTATION;
+    }
+    if ("BUILD" == property_id) {
+        return SystemInfoPropertyId::BUILD;
+    }
+    if ("LOCALE" == property_id) {
+        return SystemInfoPropertyId::LOCALE;
+    }
+    if ("NETWORK" == property_id) {
+        return SystemInfoPropertyId::NETWORK;
+    }
+    if ("WIFI_NETWORK" == property_id) {
+        return SystemInfoPropertyId::WIFI_NETWORK;
+    }
+    if ("CELLULAR_NETWORK" == property_id) {
+        return SystemInfoPropertyId::CELLULAR_NETWORK;
+    }
+    if ("SIM" == property_id) {
+        return SystemInfoPropertyId::SIM;
+    }
+    if ("PERIPHERAL" == property_id) {
+        return SystemInfoPropertyId::PERIPHERAL;
+    }
+    if ("MEMORY" == property_id) {
+        return SystemInfoPropertyId::MEMORY;
+    }
+
+    LOGW("Invalid SystemInfoPropertyId: %s", property_id.c_str());
+    SystemInfoUtil::throwSystemInfoException<Common::TypeMismatchException>(0, "Unsupported SystemInfoPropertyId");
+}
+
+SystemInfoProperty::SystemInfoProperty()
+{
+    LOGD("Entered");
+}
+
+SystemInfoProperty::~SystemInfoProperty()
+{
+    LOGD("Entered");
+}
+
+bool SystemInfoProperty::isReady() const
+{
+    return true;
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoProperty.h b/src/Systeminfo/SystemInfoProperty.h
new file mode 100755 (executable)
index 0000000..1e26d82
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_PROPERTY_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_PROPERTY_H__
+
+#include <string>
+#include <memory>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoProperty;
+typedef std::shared_ptr<SystemInfoProperty> SystemInfoPropertyPtr;
+
+struct SystemInfoPropertyHolder {
+    SystemInfoPropertyPtr ptr;
+};
+
+enum SystemInfoPropertyId {
+    UNDEFINED = 0,
+    BATTERY,
+    CPU,
+    STORAGE,
+    DISPLAY,
+    DEVICE_ORIENTATION,
+    BUILD,
+    LOCALE,
+    NETWORK,
+    WIFI_NETWORK,
+    CELLULAR_NETWORK,
+    SIM,
+    PERIPHERAL,
+    MEMORY
+};
+
+struct CpuInfo {
+    long long usr;
+    long long nice;
+    long long system;
+    long long idle;
+    double load;
+};
+
+struct SystemInfoOptions {
+    unsigned long timeout;
+    double high_threshold;
+    double low_threshold;
+
+    SystemInfoOptions() :
+        timeout(0),
+        high_threshold(0.0),
+        low_threshold(0.0)
+    {
+    }
+};
+
+class SystemInfoProperty {
+public:
+    static SystemInfoPropertyId stringToPropertyId(const std::string& property_id);
+    SystemInfoProperty();
+    virtual ~SystemInfoProperty();
+    /**
+     * Check if property is ready to be used.
+     * Some properties needs to run async tasks, so they are waiting for
+     * callbacks and their values may not be initialized.
+     * By default it returns always true, overwrite this method if your property
+     * need async tasks.
+     * Make sure that your implementation is thread safe.
+     * @return true if property is ready
+     */
+    virtual bool isReady() const;
+};
+
+} // SystemInfo
+} // DeviceAPI
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_PROPERTY_H__
diff --git a/src/Systeminfo/SystemInfoPropertySuccessCallbackData.cpp b/src/Systeminfo/SystemInfoPropertySuccessCallbackData.cpp
new file mode 100755 (executable)
index 0000000..fcb2b81
--- /dev/null
@@ -0,0 +1,165 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "SystemInfoPropertySuccessCallbackData.h"
+#include <JavaScriptCore/JavaScript.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+SystemInfoPropertySuccessCallbackData::SystemInfoPropertySuccessCallbackData(JSContextRef globalCtx) :
+    Common::CallbackUserData(globalCtx),
+    m_is_error(false),
+    m_property_id(UNDEFINED),
+    m_listener_id(0),
+    m_is_array_callback(false)
+{
+    LOGD("Entered");
+    m_native_property_array.clear();
+}
+
+SystemInfoPropertySuccessCallbackData::~SystemInfoPropertySuccessCallbackData()
+{
+    LOGD("Entered");
+}
+
+void SystemInfoPropertySuccessCallbackData::setError(const std::string &err_name,
+        const std::string &err_message)
+{
+    LOGD("Entered");
+
+    m_err_name = err_name;
+    m_err_message = err_message;
+    m_is_error = true;
+}
+
+bool SystemInfoPropertySuccessCallbackData::isError() const
+{
+    return m_is_error;
+}
+
+std::string SystemInfoPropertySuccessCallbackData::getErrorName() const
+{
+    return m_err_name;
+}
+
+std::string SystemInfoPropertySuccessCallbackData::getErrorMessage() const
+{
+    return m_err_message;
+}
+
+void SystemInfoPropertySuccessCallbackData::setPropertyId(SystemInfoPropertyId property_id)
+{
+    LOGD("Entered");
+
+    m_property_id = property_id;
+}
+
+SystemInfoPropertyId SystemInfoPropertySuccessCallbackData::getPropertyId() const
+{
+    return m_property_id;
+}
+
+void SystemInfoPropertySuccessCallbackData::setNativeProperty(SystemInfoPropertyPtr property)
+{
+    LOGD("Entered");
+
+    m_native_property_array.clear();
+
+    SystemInfoPropertyHolder *propertyHolder = new (std::nothrow) SystemInfoPropertyHolder();
+    propertyHolder->ptr = property;
+    m_native_property_array.push_back(propertyHolder);
+}
+
+SystemInfoPropertyPtr SystemInfoPropertySuccessCallbackData::getNativeProperty() const
+{
+    return m_native_property;
+}
+
+bool SystemInfoPropertySuccessCallbackData::isPropertyReady() const
+{
+    LOGD("Entered");
+
+    if (m_native_property_array.empty()) {
+        LOGE("Callback has not property");
+        return false;
+    } else {
+        std::vector<SystemInfoPropertyHolder*>::const_iterator iter;
+
+        for (iter = m_native_property_array.begin(); iter != m_native_property_array.end();
+                ++iter) {
+            if (!(*iter)->ptr->isReady()) {
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+void SystemInfoPropertySuccessCallbackData::setOptions(SystemInfoOptions& options)
+{
+    m_options = options;
+}
+SystemInfoOptions SystemInfoPropertySuccessCallbackData::getOptions() const
+{
+    return m_options;
+}
+
+void SystemInfoPropertySuccessCallbackData::setListenerId(unsigned long id)
+{
+    m_listener_id = id;
+
+}
+
+unsigned long SystemInfoPropertySuccessCallbackData::getListenerId()
+{
+    return m_listener_id;
+}
+
+void SystemInfoPropertySuccessCallbackData::setArrayCallback(bool isArray)
+{
+    m_is_array_callback = isArray;
+}
+
+bool SystemInfoPropertySuccessCallbackData::isArrayCallback()
+{
+    return m_is_array_callback;
+}
+
+void SystemInfoPropertySuccessCallbackData::addNativeProperty(SystemInfoPropertyHolder* holder)
+{
+    m_native_property_array.push_back(holder);
+}
+
+std::vector<SystemInfoPropertyHolder*> SystemInfoPropertySuccessCallbackData::getPropertyArray()
+{
+    return m_native_property_array;
+}
+
+void SystemInfoPropertySuccessCallbackData::clearArray()
+{
+    m_native_property_array.clear();
+}
+
+bool SystemInfoPropertySuccessCallbackData::isArrayEmpty()
+{
+    return m_native_property_array.empty();
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoPropertySuccessCallbackData.h b/src/Systeminfo/SystemInfoPropertySuccessCallbackData.h
new file mode 100755 (executable)
index 0000000..b2c7722
--- /dev/null
@@ -0,0 +1,86 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_PROPERTY_SUCCESSCALLBACK_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_PROPERTY_SUCCESSCALLBACK_H__
+
+#include <CallbackUserData.h>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoPropertySuccessCallbackData;
+typedef SystemInfoPropertySuccessCallbackData PropertyCallbackData;
+typedef std::shared_ptr<PropertyCallbackData> PropertyCallbackDataPtr;
+
+struct PropertyCallbackDataHolder {
+    PropertyCallbackDataPtr ptr;
+};
+
+class SystemInfoPropertySuccessCallbackData: public Common::CallbackUserData {
+public:
+    SystemInfoPropertySuccessCallbackData(JSContextRef globalCtx);
+    virtual ~SystemInfoPropertySuccessCallbackData();
+
+    void setError(const std::string &err_name, const std::string &err_message);
+    bool isError() const;
+    std::string getErrorName() const;
+    std::string getErrorMessage() const;
+
+    void setPropertyId(SystemInfoPropertyId property_id);
+    SystemInfoPropertyId getPropertyId() const;
+
+    void setNativeProperty(SystemInfoPropertyPtr property);
+    SystemInfoPropertyPtr getNativeProperty() const;
+    bool isPropertyReady() const;
+
+    void setOptions(SystemInfoOptions& options);
+    SystemInfoOptions getOptions() const;
+
+    void setListenerId(unsigned long id);
+    unsigned long getListenerId();
+
+    void setArrayCallback(bool isArray);
+    bool isArrayCallback();
+
+    void addNativeProperty(SystemInfoPropertyHolder* property);
+    std::vector<SystemInfoPropertyHolder*> getPropertyArray();
+
+    void clearArray();
+    bool isArrayEmpty();
+
+private:
+    bool m_is_error;
+    bool m_is_array_callback;
+    std::string m_err_name;
+    std::string m_err_message;
+    unsigned long m_listener_id;
+
+    SystemInfoPropertyId m_property_id;
+    SystemInfoPropertyPtr m_native_property;
+    std::vector<SystemInfoPropertyHolder*> m_native_property_array;
+    SystemInfoOptions m_options;
+};
+
+} // SystemInfo
+} // DeviceAPI
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_PROPERTY_SUCCESSCALLBACK_H__
diff --git a/src/Systeminfo/SystemInfoSIM.cpp b/src/Systeminfo/SystemInfoSIM.cpp
new file mode 100755 (executable)
index 0000000..847402f
--- /dev/null
@@ -0,0 +1,329 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <Logger.h>
+#include <PlatformException.h>
+
+#include "SystemInfoUtil.h"
+#include "SystemInfoSIM.h"
+#include "SystemInfo.h"
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+const char* SIM_STATUS_ABSENT = "ABSENT";
+const char* SIM_STATUS_INITIALIZING = "INITIALIZING";
+const char* SIM_STATUS_READY = "READY";
+const char* SIM_STATUS_PIN_REQUIRED = "PIN_REQUIRED";
+const char* SIM_STATUS_PUK_REQUIRED = "PUK_REQUIRED";
+const char* SIM_STATUS_SIM_LOCKED = "SIM_LOCKED";
+const char* SIM_STATUS_NETWORK_LOCKED = "NETWORK_LOCKED";
+const char* SIM_STATUS_UNKNOWN = "UNKNOWN";
+}
+
+SystemInfoSIM::SystemInfoSIM(TapiHandle *tapi_handle) :
+    m_ready(false),
+    m_properties_to_process(0),
+    m_mcc(0),
+    m_mnc(0),
+    m_state(""),
+    m_msisdn(""),
+    m_iccid(""),
+    m_msin(""),
+    m_spn("")
+{
+    LOGD("Entered");
+    if (NULL == tapi_handle) {
+        LOGE("Tapi handle is null");
+        m_ready = true;
+        m_state = SIM_STATUS_UNKNOWN;
+    } else {
+        int card_changed = 0;
+        TelSimCardStatus_t sim_card_state;
+        int ret = tel_get_sim_init_info(tapi_handle, &sim_card_state, &card_changed);
+        if (ret == TAPI_API_SUCCESS) {
+            switch (sim_card_state) {
+                case TAPI_SIM_STATUS_CARD_NOT_PRESENT:
+                case TAPI_SIM_STATUS_CARD_REMOVED:
+                    m_state = SIM_STATUS_ABSENT;
+                    break;
+                case TAPI_SIM_STATUS_SIM_INITIALIZING:
+                    m_state = SIM_STATUS_INITIALIZING;
+                    break;
+                case TAPI_SIM_STATUS_SIM_INIT_COMPLETED:
+                    m_state = SIM_STATUS_READY;
+                    break;
+                case TAPI_SIM_STATUS_SIM_PIN_REQUIRED:
+                    m_state = SIM_STATUS_PIN_REQUIRED;
+                    break;
+                case TAPI_SIM_STATUS_SIM_PUK_REQUIRED:
+                    m_state = SIM_STATUS_PUK_REQUIRED;
+                    break;
+                case TAPI_SIM_STATUS_SIM_LOCK_REQUIRED:
+                case TAPI_SIM_STATUS_CARD_BLOCKED:
+                    m_state = SIM_STATUS_SIM_LOCKED;
+                    break;
+                case TAPI_SIM_STATUS_SIM_NCK_REQUIRED:
+                case TAPI_SIM_STATUS_SIM_NSCK_REQUIRED:
+                    m_state = SIM_STATUS_NETWORK_LOCKED;
+                    break;
+                default:
+                    m_state = SIM_STATUS_UNKNOWN;
+                    break;
+            }
+            LOGD("state : %s", m_state.c_str());
+            if (SIM_STATUS_READY != m_state) {
+                //sim is not ready, we can't get other properties
+                //set property ready
+                m_ready = true;
+            } else {
+                TelSimImsiInfo_t imsi;
+                ret = tel_get_sim_imsi(tapi_handle, &imsi);
+                if (ret == TAPI_API_SUCCESS) {
+                    LOGD("mcc: %s, mnc: %s, msin: %s", imsi.szMcc, imsi.szMnc, imsi.szMsin);
+                    m_mcc = std::stoul(imsi.szMcc);
+                    m_mnc = std::stoul(imsi.szMnc);
+                    m_msin = imsi.szMsin;
+                } else {
+                    std::string log_msg = "Failed to get sim imsi";
+                    LOGE("$s, %d, %s", log_msg.c_str(), ret,
+                            SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+                    SystemInfoUtil::throwTapiException(ret, log_msg);
+                }
+
+                ret = tel_get_sim_msisdn(tapi_handle, msisdnValueCallback, this);
+                if (ret == TAPI_API_SUCCESS) {
+                    ++m_properties_to_process;
+                } else {
+                    std::string log_msg = "Failed to get msisdn info";
+                    LOGE("$s, %d, %s", log_msg.c_str(), ret,
+                            SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+                    SystemInfoUtil::throwTapiException(ret, log_msg);
+                }
+
+                ret = tel_get_sim_iccid(tapi_handle, iccidValueCallback, this);
+                if (ret == TAPI_API_SUCCESS) {
+                    ++m_properties_to_process;
+                } else {
+                    std::string log_msg = "Failed to get iccid info";
+                    LOGE("$s, %d, %s", log_msg.c_str(), ret,
+                            SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+                    SystemInfoUtil::throwTapiException(ret, log_msg);
+                }
+
+                ret = tel_get_sim_spn(tapi_handle, spnValueCallback, this);
+                if (ret == TAPI_API_SUCCESS) {
+                    ++m_properties_to_process;
+                } else {
+                    std::string log_msg = "Failed to get spn info";
+                    LOGE("$s, %d, %s", log_msg.c_str(), ret,
+                            SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+                    SystemInfoUtil::throwTapiException(ret, log_msg);
+                }
+
+                ret = tel_get_sim_cphs_netname(tapi_handle, cphsValueCallback, this);
+                if (ret == TAPI_API_SUCCESS) {
+                    ++m_properties_to_process;
+                } else {
+                    std::string log_msg = "Failed to get cphs info";
+                    LOGE("$s, %d, %s", log_msg.c_str(), ret,
+                            SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+                    SystemInfoUtil::throwTapiException(ret, log_msg);
+                }
+            }
+        } else {
+            std::string log_msg = "Failed to initialize sim info";
+            LOGE("$s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getTapiErrorMessage(ret).c_str());
+            SystemInfoUtil::throwTapiException(ret, log_msg);
+        }
+    }
+
+}
+
+SystemInfoSIM::~SystemInfoSIM()
+{
+    LOGD("Entered");
+}
+
+bool SystemInfoSIM::isReady() const
+{
+    return m_ready;
+}
+
+std::string SystemInfoSIM::getState() const
+{
+    return m_state;
+}
+
+std::string SystemInfoSIM::getOperatorName() const
+{
+    return m_operator_name;
+}
+
+std::string SystemInfoSIM::getMsisdn() const
+{
+    return m_msisdn;
+}
+
+std::string SystemInfoSIM::getIccid() const
+{
+    return m_iccid;
+}
+
+unsigned short SystemInfoSIM::getMcc() const
+{
+    return m_mcc;;
+}
+
+unsigned short SystemInfoSIM::getMnc() const
+{
+    return m_mnc;
+}
+
+std::string SystemInfoSIM::getMsin() const
+{
+    return m_msin;
+}
+
+std::string SystemInfoSIM::getSpn() const
+{
+    return m_spn;
+}
+
+void SystemInfoSIM::checkIfReady()
+{
+    --m_properties_to_process;
+    if (0 == m_properties_to_process) {
+        m_ready = true;
+        SystemInfo::getInstance().notifyGetPropertyValueReady();
+    }
+}
+
+void SystemInfoSIM::cphsValueCallback(TapiHandle *handle, int result, void *data, void *user_data)
+{
+    LOGD("Entered");
+
+    TelSimAccessResult_t access_rt = static_cast<TelSimAccessResult_t>(result);
+    TelSimCphsNetName_t *cphs_info = static_cast<TelSimCphsNetName_t*>(data);
+
+    SystemInfoSIM* property = static_cast<SystemInfoSIM*>(user_data);
+    if (NULL == property) {
+        LOGE("property is NULL");
+        return;
+    }
+
+    if (access_rt == TAPI_SIM_ACCESS_SUCCESS) {
+        std::stringstream s;
+        s << cphs_info->full_name;
+        if (s.str().empty()) {
+            s << cphs_info->short_name;
+        }
+        property->m_operator_name = s.str();
+        LOGD("Operator name: %s", property->m_operator_name.c_str());
+    } else {
+        LOGW("Failed to retrieve cphs_info: %d", access_rt);
+    }
+    property->checkIfReady();
+}
+
+void SystemInfoSIM::msisdnValueCallback(TapiHandle *handle, int result, void *data, void *user_data)
+{
+    LOGD("Entered");
+
+    TelSimAccessResult_t access_rt = static_cast<TelSimAccessResult_t>(result);
+    TelSimMsisdnList_t *msisdn_info = static_cast<TelSimMsisdnList_t*>(data);
+
+    SystemInfoSIM* property = static_cast<SystemInfoSIM*>(user_data);
+    if (NULL == property) {
+        LOGE("property is NULL");
+        return;
+    }
+
+    if (access_rt == TAPI_SIM_ACCESS_SUCCESS) {
+        if (msisdn_info->count > 0) {
+            if ('\0' != msisdn_info->list[0].num[0]) {
+                property->m_msisdn = msisdn_info->list[0].num;
+                LOGD("MSISDN number: %s", property->m_msisdn.c_str());
+            } else {
+                LOGW("MSISDN number empty");
+            }
+        } else {
+            LOGW("msisdn_info list empty");
+        }
+    } else {
+        LOGW("Failed to retrieve msisdn: %d", access_rt);
+    }
+    property->checkIfReady();
+}
+
+void SystemInfoSIM::iccidValueCallback(TapiHandle *handle, int result, void *data, void *user_data)
+{
+    LOGD("Entered");
+
+    TelSimAccessResult_t access_rt = static_cast<TelSimAccessResult_t>(result);
+    TelSimIccIdInfo_t *iccid_info = static_cast<TelSimIccIdInfo_t*>(data);
+
+    SystemInfoSIM* property = static_cast<SystemInfoSIM*>(user_data);
+    if (NULL == property) {
+        LOGE("property is NULL");
+        return;
+    }
+
+    if (access_rt == TAPI_SIM_ACCESS_SUCCESS) {
+        if (iccid_info->icc_length > 0) {
+            property->m_iccid = iccid_info->icc_num;
+            LOGD("iccid value: %s", property->m_iccid.c_str());
+        } else {
+            LOGW("iccid_info is empty");
+        }
+    } else {
+        LOGW("Failed to retrieve iccid: %d", access_rt);
+    }
+    property->checkIfReady();
+}
+
+void SystemInfoSIM::spnValueCallback(TapiHandle *handle, int result, void *data, void *user_data)
+{
+    LOGD("Entered");
+
+    TelSimAccessResult_t access_rt = static_cast<TelSimAccessResult_t>(result);
+    TelSimSpn_t *spn_info = static_cast<TelSimSpn_t*>(data);
+
+    SystemInfoSIM* property = static_cast<SystemInfoSIM*>(user_data);
+    if (NULL == property) {
+        LOGE("property is NULL");
+        return;
+    }
+
+    if (access_rt == TAPI_SIM_ACCESS_SUCCESS) {
+        std::stringstream s;
+        s << spn_info->spn;
+        property->m_spn = s.str();
+        LOGD("spn value: %s", property->m_spn.c_str());
+    } else {
+        LOGW("Failed to retrieve spn: %d", access_rt);
+    }
+    property->checkIfReady();
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoSIM.h b/src/Systeminfo/SystemInfoSIM.h
new file mode 100755 (executable)
index 0000000..34f3a8b
--- /dev/null
@@ -0,0 +1,74 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_SIM_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_SIM_H__
+
+#include <memory>
+#include <string>
+#include <atomic>
+#include <ITapiSim.h>
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoSIM;
+typedef std::shared_ptr<SystemInfoSIM> SystemInfoSIMPtr;
+
+class SystemInfoSIM : public SystemInfoProperty {
+public:
+    SystemInfoSIM(TapiHandle *tapi_handle);
+    virtual ~SystemInfoSIM();
+    virtual bool isReady() const;
+
+    std::string getState() const;
+    std::string getOperatorName() const;
+    std::string getMsisdn() const;
+    std::string getIccid() const;
+    unsigned short getMcc() const;
+    unsigned short getMnc() const;
+    std::string getMsin() const;
+    std::string getSpn() const;
+private:
+    std::atomic_bool m_ready;
+    std::atomic<unsigned short> m_properties_to_process;
+    unsigned short m_mcc;
+    unsigned short m_mnc;
+    std::string m_operator_name;
+    std::string m_msin;
+    std::string m_state;
+    std::string m_msisdn;
+    std::string m_iccid;
+    std::string m_spn;
+
+    /**
+     * Decrement m_properties_to_process and if all properties are set,
+     * notify Systeminfo (in order to call js callback)
+     */
+    void checkIfReady();
+
+    static void cphsValueCallback(TapiHandle *handle, int result, void *data, void *user_data);
+    static void msisdnValueCallback(TapiHandle *handle, int result, void *data, void *user_data);
+    static void iccidValueCallback(TapiHandle *handle, int result, void *data, void *user_data);
+    static void spnValueCallback(TapiHandle *handle, int result, void *data, void *user_data);
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_SIM_H__
diff --git a/src/Systeminfo/SystemInfoStorage.cpp b/src/Systeminfo/SystemInfoStorage.cpp
new file mode 100755 (executable)
index 0000000..3e50920
--- /dev/null
@@ -0,0 +1,118 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <Logger.h>
+#include <vconf.h>
+#include <sys/statfs.h>
+
+#include "SystemInfoStorage.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+    const char* STORAGE_INTERNAL_PATH = "/opt/usr/media";
+    const char* STORAGE_SDCARD_PATH = "/opt/storage/sdcard";
+}
+
+SystemInfoStorage::SystemInfoStorage()
+{
+    LOGD("Entered");
+    fetchUnitsInfo();
+}
+
+SystemInfoStorage::~SystemInfoStorage()
+{
+    LOGD("Entered");
+}
+
+UnitsPtrVector SystemInfoStorage::getUnits() const
+{
+    return m_units;
+}
+
+void SystemInfoStorage::fetchUnitsInfo()
+{
+    LOGD("Entered");
+
+    int sdcardState = 0;
+    struct statfs fs;
+    int ret = 0;
+
+    if (statfs(STORAGE_INTERNAL_PATH, &fs) < 0) {
+        int err = errno;
+        LOGE("There are no storage units detected, %d, %s", err, strerror(errno));
+        return;
+    }
+    SystemInfoStorageUnitPtr internal(new SystemInfoStorageUnit());
+    internal->setType(INTERNAL);
+    internal->setCapacity(
+            static_cast<unsigned long long>(fs.f_bsize)
+                    * static_cast<unsigned long long>(fs.f_blocks));
+    internal->setAvailableCapacity(
+            static_cast<unsigned long long>(fs.f_bsize)
+                    * static_cast<unsigned long long>(fs.f_bavail));
+    internal->setIsRemovable(false);
+    m_units.push_back(internal);
+
+    ret = vconf_get_int(VCONFKEY_SYSMAN_MMC_STATUS, &sdcardState);
+    if (ret == VCONF_OK) {
+        if (sdcardState == VCONFKEY_SYSMAN_MMC_MOUNTED) {
+            if (statfs(STORAGE_SDCARD_PATH, &fs) < 0) {
+                LOGE("MMC mounted, but not accessible");
+                return;
+            }
+            SystemInfoStorageUnitPtr external(new SystemInfoStorageUnit());
+            external->setType(MMC);
+            external->setCapacity(
+                    static_cast<unsigned long long>(fs.f_bsize)
+                            * static_cast<unsigned long long>(fs.f_blocks));
+            external->setAvailableCapacity(
+                    static_cast<unsigned long long>(fs.f_bsize)
+                            * static_cast<unsigned long long>(fs.f_bavail));
+            external->setIsRemovable(true);
+            m_units.push_back(external);
+        }
+    } else {
+        LOGE("Failed to get mmc status");
+    }
+}
+
+bool SystemInfoStorage::operator==(const SystemInfoStorage& other)
+{
+    LOGD("Entered");
+
+    LOGD("m_units.size = %d and other.m_units.size() = %d", m_units.size(), other.m_units.size());
+    if (m_units.size() != other.m_units.size()) {
+        return false;
+    }
+    for (size_t i = 0; i < m_units.size(); ++i) {
+        if (*m_units[i] != *other.m_units[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool SystemInfoStorage::operator!=(const SystemInfoStorage& other)
+{
+    return !(this->operator==(other));
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoStorage.h b/src/Systeminfo/SystemInfoStorage.h
new file mode 100755 (executable)
index 0000000..e83d6e0
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_STORAGE_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_STORAGE_H__
+
+#include <memory>
+
+#include "SystemInfoProperty.h"
+#include "SystemInfoStorageUnit.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoStorage;
+typedef std::shared_ptr<SystemInfoStorage> SystemInfoStoragePtr;
+
+class SystemInfoStorage : public SystemInfoProperty {
+public:
+    SystemInfoStorage();
+    virtual ~SystemInfoStorage();
+
+    UnitsPtrVector getUnits() const;
+    bool operator==(const SystemInfoStorage& other);
+    bool operator!=(const SystemInfoStorage& other);
+
+private:
+    void fetchUnitsInfo();
+
+    UnitsPtrVector m_units;
+
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_STORAGE_H__
diff --git a/src/Systeminfo/SystemInfoStorageUnit.cpp b/src/Systeminfo/SystemInfoStorageUnit.cpp
new file mode 100755 (executable)
index 0000000..7a9d277
--- /dev/null
@@ -0,0 +1,109 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <device.h>
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "SystemInfoStorageUnit.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+SystemInfoStorageUnit::SystemInfoStorageUnit() :
+    m_type(UNKNOWN),
+    m_capacity(0),
+    m_available_capacity(0),
+    m_is_removable(false)
+{
+    LOGD("Entered");
+}
+
+SystemInfoStorageUnit::~SystemInfoStorageUnit()
+{
+    LOGD("Entered");
+}
+
+StorageType SystemInfoStorageUnit::getType() const
+{
+    return m_type;
+}
+
+unsigned long long SystemInfoStorageUnit::getCapacity() const
+{
+    return m_capacity;
+}
+
+unsigned long long SystemInfoStorageUnit::getAvailableCapacity() const
+{
+    return m_available_capacity;
+}
+
+bool SystemInfoStorageUnit::isRemovable() const
+{
+    return m_is_removable;
+}
+
+void SystemInfoStorageUnit::setType(StorageType type)
+{
+    m_type = type;
+}
+void SystemInfoStorageUnit::setCapacity(unsigned long long capacity)
+{
+    m_capacity = capacity;
+}
+void SystemInfoStorageUnit::setAvailableCapacity(unsigned long long av_capacity)
+{
+    m_available_capacity = av_capacity;
+}
+void SystemInfoStorageUnit::setIsRemovable(bool is_removable)
+{
+    m_is_removable = is_removable;
+}
+
+std::string SystemInfoStorageUnit::typeToString(StorageType type)
+{
+    switch (type) {
+        case StorageType::INTERNAL:
+            return TYPE_INTERNAL;
+        case StorageType::USB_HOST:
+            return TYPE_USB_HOST;
+        case StorageType::MMC:
+            return TYPE_MMC;
+        default:
+            return TYPE_UNKNOWN;
+    }
+}
+
+bool SystemInfoStorageUnit::operator==(const SystemInfoStorageUnit& other)
+{
+    if (m_type == other.m_type && m_capacity == other.m_capacity
+            && m_available_capacity == other.m_available_capacity
+            && m_is_removable == other.m_is_removable) {
+        return true;
+    }
+    return false;
+}
+
+bool SystemInfoStorageUnit::operator!=(const SystemInfoStorageUnit& other)
+{
+    return !(this->operator==(other));
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoStorageUnit.h b/src/Systeminfo/SystemInfoStorageUnit.h
new file mode 100755 (executable)
index 0000000..c440dda
--- /dev/null
@@ -0,0 +1,77 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_STORAGE_UNIT_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_STORAGE_UNIT_H__
+
+#include <memory>
+#include <vector>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+const std::string TYPE_UNKNOWN = "UNKNOWN";
+const std::string TYPE_INTERNAL = "INTERNAL";
+const std::string TYPE_USB_HOST = "USB_HOST";
+const std::string TYPE_MMC = "MMC";
+}
+enum StorageType {
+    UNKNOWN,
+    INTERNAL,
+    USB_HOST,
+    MMC
+};
+
+class SystemInfoStorageUnit;
+typedef std::shared_ptr<SystemInfoStorageUnit> SystemInfoStorageUnitPtr;
+typedef std::vector<SystemInfoStorageUnitPtr> UnitsPtrVector;
+
+class SystemInfoStorageUnit: public SystemInfoProperty {
+public:
+    SystemInfoStorageUnit();
+    virtual ~SystemInfoStorageUnit();
+
+    StorageType getType() const;
+    unsigned long long getCapacity() const;
+    unsigned long long getAvailableCapacity() const;
+    bool isRemovable() const;
+
+    void setType(StorageType type);
+    void setCapacity(unsigned long long capacity);
+    void setAvailableCapacity(unsigned long long av_capacity);
+    void setIsRemovable(bool is_removable);
+
+    static std::string typeToString(StorageType type);
+
+    bool operator==(const SystemInfoStorageUnit& other);
+    bool operator!=(const SystemInfoStorageUnit& other);
+
+private:
+    StorageType m_type;
+    unsigned long long m_capacity;
+    unsigned long long m_available_capacity;
+    bool m_is_removable;
+
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_STORAGE_UNIT_H__
diff --git a/src/Systeminfo/SystemInfoUtil.cpp b/src/Systeminfo/SystemInfoUtil.cpp
new file mode 100755 (executable)
index 0000000..18dd0b4
--- /dev/null
@@ -0,0 +1,248 @@
+#include <system_settings.h>
+#include <system_info.h>
+#include <net_connection.h>
+
+#ifdef FEATURE_OPTIONAL_WI_FI
+#include <wifi.h>
+#endif
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+#include <tapi_common.h>
+#endif
+
+#include "SystemInfoUtil.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+std::string SystemInfoUtil::getSystemInfoErrorMessage(const int errorCode)
+{
+    switch (errorCode) {
+        case SYSTEM_INFO_ERROR_NONE:
+            return "";
+        case SYSTEM_INFO_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case SYSTEM_INFO_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case SYSTEM_INFO_ERROR_IO_ERROR:
+            return "IO error";
+        case SYSTEM_INFO_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        default:
+            return "Unknown Error";
+    }
+}
+
+std::string SystemInfoUtil::getConnectionErrorMessage(const int errorCode)
+{
+    switch (errorCode) {
+        case CONNECTION_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case CONNECTION_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case CONNECTION_ERROR_INVALID_OPERATION:
+            return "Invaild operation";
+        case CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
+            return "Address family not supported";
+        case CONNECTION_ERROR_OPERATION_FAILED:
+            return "Operation failed";
+        case CONNECTION_ERROR_ITERATOR_END:
+            return "Iterator end";
+        case CONNECTION_ERROR_NO_CONNECTION:
+            return "No connection";
+        case CONNECTION_ERROR_ALREADY_EXISTS:
+            return "Already exists";
+        case CONNECTION_ERROR_OPERATION_ABORTED:
+            return "Operation aborted";
+        case CONNECTION_ERROR_DHCP_FAILED:
+            return "DHCP failed";
+        case CONNECTION_ERROR_INVALID_KEY:
+            return "Invalid key";
+        case CONNECTION_ERROR_NO_REPLY:
+            return "No reply";
+        case CONNECTION_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case CONNECTION_ERROR_NOT_SUPPORTED:
+            return "Not supported";
+        default:
+            return "Unknown Error";
+    }
+}
+
+#ifdef FEATURE_OPTIONAL_TELEPHONY
+std::string SystemInfoUtil::getTapiErrorMessage(const int errorCode)
+{
+    switch (errorCode) {
+        case TAPI_API_INVALID_INPUT:
+            return "Invaild input";
+        case TAPI_API_INVALID_PTR:
+            return "Invalid pointer";
+        case TAPI_API_NOT_SUPPORTED:
+            return "Not supported";
+        case TAPI_API_DEPRICATED:
+            return "Depricated";
+        case TAPI_API_SYSTEM_OUT_OF_MEM:
+            return "Out of memory";
+        case TAPI_API_SYSTEM_RPC_LINK_DOWN:
+            return "RPC link down";
+        case TAPI_API_SERVICE_NOT_READY:
+            return "Service not ready";
+        case TAPI_API_SERVER_FAILURE:
+            return "Service failure";
+        case TAPI_API_OEM_PLUGIN_FAILURE:
+            return "Plug-in layer failure";
+        case TAPI_API_TRANSPORT_LAYER_FAILURE:
+            return "Trasport layer failure";
+        case TAPI_API_INVALID_DATA_LEN:
+            return "Invalid data length";
+        case TAPI_API_REQUEST_MAX_IN_PROGRESS:
+            return "Maximum number of requests in progress";
+        case TAPI_API_OFFLINE_MODE_ERROR:
+            return "Offline mode error";
+        case TAPI_EVENT_CLASS_UNKNOWN:
+            return "Unknown event class";
+        case TAPI_EVENT_UNKNOWN:
+            return "Unknown event";
+        case TAPI_REGISTRATION_OP_FAILED:
+            return "Callback registration failed";
+        case TAPI_API_OPERATION_FAILED:
+            return "Operation failed";
+        case TAPI_API_INVALID_OPERATION:
+            return "Invalid operation";
+        case TAPI_API_ACCESS_DENIED:
+            return "Access denied";
+        case TAPI_API_SYSTEM_RPC_LINK_NOT_EST:
+            return "RPC link down";
+        case TAPI_API_API_NOT_SUPPORTED:
+            return "API not supported";
+        case TAPI_API_SERVER_LAYER_FAILURE:
+            return "Server layer failure";
+        case TAPI_API_INVALID_CALL_ID:
+            return "Invalid call id";
+        case TAPI_API_CALL_CTXT_OVERFLOW:
+            return "Call context overflow";
+        case TAPI_API_COULD_NOT_GET_CALL_CTXT:
+            return "Could not get the call context";
+        case TAPI_API_CTXT_SEARCH_RET_NON_CALL_CTXT:
+            return "Context search returned the non-call context ";
+        case TAPI_API_COULD_NOT_DESTROY_CTXT:
+            return "Could not destroy the context ";
+        case TAPI_API_INVALID_LINE_ID:
+            return "Invalid line ID";
+        case TAPI_API_INVALID_CALL_HANDLE:
+            return "Invalid call handle";
+        case TAPI_API_INVALID_CALL_STATE:
+            return "Invalid call state";
+        case TAPI_API_CALL_PRE_COND_FAILED:
+            return "Pre condition like MO call cannot be established now ";
+        case TAPI_API_CALL_SAME_REQ_PENDING:
+            return "Cannot accept the same request multiple times ";
+        case TAPI_API_MODEM_POWERED_OFF:
+            return "Modem is powered off ";
+        case TAPI_API_MODEM_ALREADY_ON:
+            return "Modem is already on ";
+        case TAPI_API_MODEM_ALREADY_OFF:
+            return "Modem is already off ";
+        case TAPI_API_NETTEXT_DEVICE_NOT_READY:
+            return "Nettext device is not ready ";
+        case TAPI_API_NETTEXT_SCADDR_NOT_SET:
+            return "Nettext SCA address is not set ";
+        case TAPI_API_NETTEXT_INVALID_DATA_LEN:
+            return "Nettext Invalid data length ";
+        case TAPI_NETTEXT_SCADDRESS_NOT_SET:
+            return "Nettext SCA address is not set ";
+        case TAPI_API_SIM_CARD_ERROR:
+            return "SIM general error";
+        case TAPI_API_SIM_NOT_FOUND:
+            return "SIM is not present";
+        case TAPI_API_SIM_NOT_INITIALIZED:
+            return "SIM has not initialized yet";
+        case TAPI_API_SIM_LOCKED:
+            return "PIN/PUK/NCK/NSCK/SPCK/CCK required state";
+        case TAPI_API_SIM_PERM_BLOCKED:
+            return "SIM Permanently blocked state";
+        case TAPI_API_SIM_SERVICE_IS_DISABLED:
+            return "Service is disabled in EF-SST due to a given operation";
+        case TAPI_API_SAT_INVALID_COMMAND_ID:
+            return "Command Number Invalid";
+        case TAPI_API_SAT_COMMAND_TYPE_MISMATCH:
+            return "Command Type Mismatch";
+        case TAPI_API_SAT_EVENT_NOT_REQUIRED_BY_USIM:
+            return "Event Not Requested by the USIM";
+        case TAPI_API_NETWORK_INVALID_CTXT:
+            return "Network invalid context";
+        case TAPI_API_NETWORK_ROAMING_NOT_ALLOWED:
+            return "3GPP Attache reject cause 11";
+        case TAPI_API_MISC_RETURN_NULL:
+            return "3GPP Attache reject cause 13 MISC return NULL";
+        case TAPI_API_MISC_VALIDITY_ERROR:
+            return "MISC validity error";
+        case TAPI_API_MISC_INPUTPARM_ERROR:
+            return "MISC input parameter error";
+        case TAPI_API_MISC_OUTPARAM_NULL:
+            return "MISC output parameter NULL";
+        default:
+            return "Unknown Error";
+    }
+}
+#endif
+
+std::string SystemInfoUtil::getSettingErrorMessage(const int errorCode)
+{
+    switch (errorCode) {
+        case SYSTEM_SETTINGS_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case SYSTEM_SETTINGS_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case SYSTEM_SETTINGS_ERROR_IO_ERROR:
+            return "IO error";
+        case SYSTEM_SETTINGS_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        case SYSTEM_SETTINGS_ERROR_LOCKSCREEN_APP_PASSWORD_MODE:
+            return "Current lock screen app set password type";
+        default:
+            return "Unknown Error";
+    }
+}
+
+#ifdef FEATURE_OPTIONAL_WI_FI
+std::string SystemInfoUtil::getWIFIErrorMessage(const int errorCode)
+{
+    switch (errorCode) {
+        case WIFI_ERROR_INVALID_PARAMETER:
+            return "Invalid parameter";
+        case WIFI_ERROR_OUT_OF_MEMORY:
+            return "Out of memory";
+        case WIFI_ERROR_INVALID_OPERATION:
+            return "Invalid operation";
+        case WIFI_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED:
+            return "Address family not supported";
+        case WIFI_ERROR_OPERATION_FAILED:
+            return "Operation failed";
+        case WIFI_ERROR_NO_CONNECTION:
+            return "No connection";
+        case WIFI_ERROR_NOW_IN_PROGRESS:
+            return "Now in progress";
+        case WIFI_ERROR_ALREADY_EXISTS:
+            return "Already exists";
+        case WIFI_ERROR_OPERATION_ABORTED:
+            return "Operation aborted";
+        case WIFI_ERROR_DHCP_FAILED:
+            return "DHCP failed";
+        case WIFI_ERROR_INVALID_KEY:
+            return "Invalid key";
+        case WIFI_ERROR_NO_REPLY:
+            return "No reply";
+        case WIFI_ERROR_SECURITY_RESTRICTED:
+            return "Security restricted";
+        case WIFI_ERROR_PERMISSION_DENIED:
+            return "Permission denied";
+        default:
+            return "Unknown Error";
+    }
+}
+#endif
+
+}
+//SystemInfo
+}//DeviceAPI
diff --git a/src/Systeminfo/SystemInfoUtil.h b/src/Systeminfo/SystemInfoUtil.h
new file mode 100755 (executable)
index 0000000..491e7ee
--- /dev/null
@@ -0,0 +1,94 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_UTIL_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_UTIL_H__
+
+#include <sstream>
+#include <string>
+#include <Logger.h>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoUtil {
+public:
+
+    static std::string getSystemInfoErrorMessage(const int errorCode);
+    static std::string getConnectionErrorMessage(const int errorCode);
+    static std::string getTapiErrorMessage(const int errorCode);
+    static std::string getSettingErrorMessage(const int errorCode);
+    static std::string getWIFIErrorMessage(const int errorCode);
+
+
+    template<class T = DeviceAPI::Common::UnknownException>
+    static void throwSystemInfoException(const int errorCode, const std::string& hint)
+    {
+        std::stringstream ss;
+        ss << hint << " : " << getSystemInfoErrorMessage(errorCode);
+        LOGE("%s", ss.str().c_str());
+
+        throw T(ss.str().c_str());
+    }
+
+    template<class T = DeviceAPI::Common::UnknownException>
+    static void throwConnectionException(const int errorCode, const std::string& hint)
+    {
+        std::stringstream ss;
+        ss << hint << " : " << getConnectionErrorMessage(errorCode);
+        LOGE("%s", ss.str().c_str());
+
+        throw T(ss.str().c_str());
+    }
+
+    template<class T = DeviceAPI::Common::UnknownException>
+    static void throwTapiException(const int errorCode, const std::string& hint)
+    {
+        std::stringstream ss;
+        ss << hint << " : " << getTapiErrorMessage(errorCode);
+        LOGE("%s", ss.str().c_str());
+
+        throw T(ss.str().c_str());
+    }
+
+    template<class T = DeviceAPI::Common::UnknownException>
+    static void throwSettingException(const int errorCode, const std::string& hint)
+    {
+        std::stringstream ss;
+        ss << hint << " : " << getSettingErrorMessage(errorCode);
+        LOGE("%s", ss.str().c_str());
+
+        throw T(ss.str().c_str());
+    }
+
+    template<class T = DeviceAPI::Common::UnknownException>
+    static void throwWIFIException(const int errorCode, const std::string& hint)
+    {
+        std::stringstream ss;
+        ss << hint << " : " << getWIFIErrorMessage(errorCode);
+        LOGE("%s", ss.str().c_str());
+
+        throw T(ss.str().c_str());
+    }
+
+};
+
+} //SystemInfo
+} //DeviceAPI
+
+#endif /* __TIZEN_SYSTEMINFO_SYSTEMINFO_UTIL_H__ */
diff --git a/src/Systeminfo/SystemInfoWifiNetwork.cpp b/src/Systeminfo/SystemInfoWifiNetwork.cpp
new file mode 100755 (executable)
index 0000000..c953732
--- /dev/null
@@ -0,0 +1,206 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <Logger.h>
+#include <PlatformException.h>
+#include <net_connection.h>
+#include <wifi.h>
+
+#include "SystemInfoWifiNetwork.h"
+#include "SystemInfoUtil.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+namespace {
+    const std::string WIFI_STATUS_ON = "ON";
+    const std::string WIFI_STATUS_OFF = "OFF";
+    const int WIFI_SIGNAL_STRENGTH_DIVIDE_VALUE = 100;
+}
+
+SystemInfoWifiNetwork::SystemInfoWifiNetwork() :
+    m_status(false),
+    m_ssid(""),
+    m_ip_address(""),
+    m_ipv6_address(""),
+    m_mac_address(""),
+    m_signal_strength(0)
+{
+    LOGD("Entered");
+    fetchWifiNetworkInfo();
+}
+
+SystemInfoWifiNetwork::~SystemInfoWifiNetwork()
+{
+    LOGD("Entered");
+}
+
+std::string SystemInfoWifiNetwork::getStatus() const
+{
+    if (m_status)
+        return WIFI_STATUS_ON;
+    return WIFI_STATUS_OFF;
+}
+
+std::string SystemInfoWifiNetwork::getSsid() const
+{
+    return m_ssid;
+}
+
+std::string SystemInfoWifiNetwork::getIpAddress() const
+{
+    return m_ip_address;
+}
+
+std::string SystemInfoWifiNetwork::getIpv6Address() const
+{
+    return m_ipv6_address;
+}
+
+std::string SystemInfoWifiNetwork::getMacAddress() const
+{
+    return m_mac_address;
+}
+
+double SystemInfoWifiNetwork::getSignalStrength() const
+{
+    return m_signal_strength;
+}
+
+void SystemInfoWifiNetwork::fetchWifiNetworkInfo()
+{
+
+    LOGD("Entered");
+
+    connection_h connection_handle;
+    connection_type_e connection_type;
+    connection_profile_h profile_handle = NULL;
+    char* ip_addr = NULL;
+    char* essid = NULL;
+    char* macAddress = NULL;
+    int rssi = 0;
+
+    int ret = connection_create(&connection_handle);
+    if (ret != CONNECTION_ERROR_NONE) {
+        std::string log_msg = "Failed to create connection";
+        LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+        SystemInfoUtil::throwConnectionException(ret, log_msg);
+    }
+    try {
+        ret = connection_get_type(connection_handle, &connection_type);
+        if (ret != CONNECTION_ERROR_NONE) {
+            std::string log_msg = "Failed to get connection type";
+            LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            SystemInfoUtil::throwConnectionException(ret, log_msg);
+        }
+
+        if (connection_type == CONNECTION_TYPE_WIFI) {
+            LOGD("Connection type = WIFI");
+            m_status = true;
+        } else {
+            LOGE("Connection type = %d. WIFI is disabled", connection_type);
+            connection_destroy(connection_handle);
+            return;
+        }
+
+        ret = connection_get_current_profile(connection_handle, &profile_handle);
+        if (ret != CONNECTION_ERROR_NONE) {
+            std::string log_msg = "Failed to get connection profile";
+            LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            SystemInfoUtil::throwConnectionException(ret, log_msg);
+        }
+
+        ret = connection_profile_get_wifi_essid(profile_handle, &essid);
+        if (ret == CONNECTION_ERROR_NONE) {
+            LOGD("Success to get ssid");
+            m_ssid = essid;
+            free(essid);
+        } else {
+            std::string log_msg = "Failed to get network ssid";
+            LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            SystemInfoUtil::throwConnectionException(ret, log_msg);
+        }
+
+        ret = connection_profile_get_ip_address(profile_handle, CONNECTION_ADDRESS_FAMILY_IPV4,
+                &ip_addr);
+        if (ret == CONNECTION_ERROR_NONE) {
+            LOGD("Success to get ipv4 address");
+            m_ip_address = ip_addr;
+            free(ip_addr);
+        } else {
+            std::string log_msg = "Failed to get ip address";
+            LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            SystemInfoUtil::throwConnectionException(ret, log_msg);
+        }
+
+        ip_addr = NULL;
+        ret = connection_profile_get_ip_address(profile_handle, CONNECTION_ADDRESS_FAMILY_IPV6,
+                &ip_addr);
+        if (ret == CONNECTION_ERROR_NONE) {
+            LOGD("Success to get ipv6 address");
+            m_ipv6_address = ip_addr;
+            free(ip_addr);
+        } else if (CONNECTION_ERROR_ADDRESS_FAMILY_NOT_SUPPORTED != ret) {
+            std::string log_msg = "Failed to get ipv6 address";
+            LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            SystemInfoUtil::throwConnectionException(ret, log_msg);
+        }
+
+        ret = connection_profile_get_wifi_rssi(profile_handle, &rssi);
+        if (ret == CONNECTION_ERROR_NONE) {
+            LOGD("Success to get rssi");
+            m_signal_strength = (double) rssi / WIFI_SIGNAL_STRENGTH_DIVIDE_VALUE;
+        } else {
+            std::string log_msg = "Failed to get signal strength";
+            LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getConnectionErrorMessage(ret).c_str());
+            SystemInfoUtil::throwConnectionException(ret, log_msg);
+        }
+
+        ret = wifi_get_mac_address(&macAddress);
+        if (ret == WIFI_ERROR_NONE) {
+            LOGD("Success to get mac address");
+            m_mac_address = macAddress;
+            free(macAddress);
+        } else {
+            std::string log_msg = "Failed to get mac address";
+            LOGE("%s, %d, %s", log_msg.c_str(), ret,
+                    SystemInfoUtil::getWIFIErrorMessage(ret).c_str());
+            SystemInfoUtil::throwWIFIException(ret, log_msg);
+        }
+    } catch (...) {
+        if (NULL != profile_handle) {
+            connection_profile_destroy(profile_handle);
+        }
+        connection_destroy(connection_handle);
+        throw;
+    }
+    if (NULL != profile_handle) {
+        connection_profile_destroy(profile_handle);
+    }
+    connection_destroy(connection_handle);
+}
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/Systeminfo/SystemInfoWifiNetwork.h b/src/Systeminfo/SystemInfoWifiNetwork.h
new file mode 100755 (executable)
index 0000000..df703d9
--- /dev/null
@@ -0,0 +1,57 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_SYSTEMINFO_SYSTEMINFO_WIFI_NETWORK_H__
+#define __TIZEN_SYSTEMINFO_SYSTEMINFO_WIFI_NETWORK_H__
+
+#include <memory>
+
+#include "SystemInfoProperty.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+class SystemInfoWifiNetwork;
+typedef std::shared_ptr<SystemInfoWifiNetwork> SystemInfoWifiNetworkPtr;
+
+class SystemInfoWifiNetwork : public SystemInfoProperty {
+public:
+    SystemInfoWifiNetwork();
+    virtual ~SystemInfoWifiNetwork();
+
+    std::string getStatus() const;
+    std::string getSsid() const;
+    std::string getIpAddress() const;
+    std::string getIpv6Address() const;
+    std::string getMacAddress() const;
+    double getSignalStrength() const;
+
+private:
+    bool m_status;
+    std::string m_ssid;
+    std::string m_ip_address;
+    std::string m_ipv6_address;
+    std::string m_mac_address;
+    double m_signal_strength;
+
+    void fetchWifiNetworkInfo();
+};
+
+} // SystemInfo
+} // DeviceAPI
+
+#endif //__TIZEN_SYSTEMINFO_SYSTEMINFO_WIFI_NETWORK_H__
diff --git a/src/Systeminfo/SysteminfoDeviceCapabilityKeys.h b/src/Systeminfo/SysteminfoDeviceCapabilityKeys.h
new file mode 100755 (executable)
index 0000000..5588119
--- /dev/null
@@ -0,0 +1,266 @@
+/*
+ * keys.h
+ *
+ *  Created on: 2014. 7. 15.
+ *      Author: shyun.min
+ */
+
+#ifndef KEYS_H_
+#define KEYS_H_
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+/*API feature*/
+const char* TIZEN_FEATURE_ACCOUNT = "http://tizen.org/feature/account";
+const char* TIZEN_FEATURE_ARCHIVE = "http://tizen.org/feature/archive";
+const char* TIZEN_FEATURE_BADGE = "http://tizen.org/feature/badge";
+const char* TIZEN_FEATURE_BOOKMARK = "http://tizen.org/feature/bookmark";
+const char* TIZEN_FEATURE_CALENDAR = "http://tizen.org/feature/calendar";
+const char* TIZEN_FEATURE_CONTACT = "http://tizen.org/feature/contact";
+const char* TIZEN_FEATURE_DATACONTROL = "http://tizen.org/feature/datacontrol";
+const char* TIZEN_FEATURE_DATASYNC = "http://tizen.org/feature/datasync";
+const char* TIZEN_FEATURE_DOWNLOAD = "http://tizen.org/feature/download";
+const char* TIZEN_FEATURE_EXIF = "http://tizen.org/feature/exif";
+const char* TIZEN_FEATURE_SYSTEMSETTING = "http://tizen.org/feature/systemsetting"; //tv: false
+const char* TIZEN_FEATURE_SYSTEMSETTING_HOME_SCREEN =
+        "http://tizen.org/feature/systemsetting.home_screen"; //mobile: true, wearable: true
+const char* TIZEN_FEATURE_SYSTEMSETTING_LOCK_SCREEN =
+        "http://tizen.org/feature/systemsetting.lock_screen"; //mobile: true, wearable: false
+const char* TIZEN_FEATURE_SYSTEMSETTING_INCOMING_CALL =
+        "http://tizen.org/feature/systemsetting.incoming_call"; //mobile:true, wearable: true
+const char* TIZEN_FEATURE_SYSTEMSETTING_NOTIFICATION_EMAIL =
+        "http://tizen.org/feature/systemsetting.notification_email"; //mobile:true, wearable: false
+const char* TIZEN_FEATURE_WEBSETTING = "http://tizen.org/feature/websetting";
+const char* TIZEN_FEATURE_EMAIL = "http://tizen.org/feature/email";
+const char* TIZEN_FEATURE_TELEPHONY = "http://tizen.org/feature/network.telephony";
+const char* TIZEN_FEATURE_TELEPHONY_MMS = "http://tizen.org/feature/network.telephony.mms";
+const char* TIZEN_FEATURE_NOTIFICATION = "http://tizen.org/feature/notification";
+
+/*Battery*/
+const char* TIZEN_FEATURE_BATTERY = "http://tizen.org/feature/battery"; //tv: false
+
+/*Camera feature*/
+const char* TIZEN_FEATURE_CAMERA = "http://tizen.org/feature/camera";
+const char* TIZEN_FEATURE_CAMERABACK = "http://tizen.org/feature/camera.back";
+const char* TIZEN_FEATURE_CAMERABACKFLASH = "http://tizen.org/feature/camera.back.flash";
+const char* TIZEN_FEATURE_CAMERAFRONT = "http://tizen.org/feature/camera.front";
+const char* TIZEN_FEATURE_CAMERAFRONTFLASH = "http://tizen.org/feature/camera.front.flash";
+
+/*Database feature*/
+const char* TIZEN_FEATURE_DATA_ENCRYPTION = "http://tizen.org/feature/database.encryption";
+
+/*FM radio*/
+const char* TIZEN_FEATURE_FMRADIO = "http://tizen.org/feature/fmradio";
+
+/*Graphics feature*/
+const char* TIZEN_FEATURE_GRAPHICS_ACCELERATION = "http://tizen.org/feature/graphics.acceleration";
+
+/*LED feature*/
+const char* TIZEN_FEATURE_LED = "http://tizen.org/feature/led";
+
+/*input feature*/
+const char* TIZEN_FEATURE_INPUTKEYBOARD = "http://tizen.org/feature/input.keyboard";
+const char* TIZEN_FEATURE_INPUTKEYBOARD_LAYOUT = "http://tizen.org/feature/input.keyboard.layout";
+
+/*Location feature*/
+const char* TIZEN_FEATURE_LOCATION = "http://tizen.org/feature/location";
+const char* TIZEN_FEATURE_LOCATIONGPS = "http://tizen.org/feature/location.gps";
+const char* TIZEN_FEATURE_LOCATIONWPS = "http://tizen.org/feature/location.wps";
+const char* TIZEN_FEATURE_LOCATIONBATCH = "http://tizen.org/feature/location.batch";
+
+/*Multimedia transcoder*/
+const char* TIZEN_FEATURE_MULTIMEDIA_TRANSCODER = "http://tizen.org/feature/multimedia.transcoder";
+
+/*Microphone feature*/
+const char* TIZEN_FEATURE_MICROPHONE = "http://tizen.org/feature/microphone";
+
+/*Multi-point touch feature*/
+const char* TIZEN_FEATURE_MULTITOUCH_PINCH_ZOOM =
+        "http://tizen.org/feature/multi_point_touch.pinch_zoom";
+const char* TIZEN_FEATURE_MULTITOUCHCOUNT = "http://tizen.org/feature/multi_point_touch.point_count";
+
+/*Network feature*/
+const char* TIZEN_FEATURE_BLUETOOTH_ALWAYS_ON =
+        "http://tizen.org/capability/network.bluetooth.always_on"; //mobile/wearable: false, tv: true
+const char* TIZEN_FEATURE_BLUETOOTH = "http://tizen.org/feature/network.bluetooth";
+const char* TIZEN_FEATURE_BLUETOOTH_AUDIO_CALL =
+        "http://tizen.org/feature/network.bluetooth.audio.call";
+const char* TIZEN_FEATURE_BLUETOOTH_AUDIO_MEDIA =
+        "http://tizen.org/feature/network.bluetooth.audio.media";
+const char* TIZEN_FEATURE_BLUETOOTH_HEALTH = "http://tizen.org/feature/network.bluetooth.health"; //mobile: true, wearable/tv: false
+const char* TIZEN_FEATURE_BLUETOOTH_HID = "http://tizen.org/feature/network.bluetooth.hid";
+const char* TIZEN_FEATURE_BLUETOOTH_LE = "http://tizen.org/feature/network.bluetooth.le";
+const char* TIZEN_FEATURE_BLUETOOTH_OPP = "http://tizen.org/feature/network.bluetooth.opp";
+const char* TIZEN_FEATURE_NFC = "http://tizen.org/feature/network.nfc";
+const char* TIZEN_FEATURE_NFC_CARD_EMULATION = "http://tizen.org/feature/network.nfc.card_emulation";
+const char* TIZEN_FEATURE_NFC_RESERVED_PUSH = "http://tizen.org/feature/network.nfc.reserved_push";
+const char* TIZEN_FEATURE_PUSH = "http://tizen.org/feature/network.push";
+const char* TIZEN_FEATURE_SECURE_ELEMENT = "http://tizen.org/feature/network.secure_element";
+const char* TIZEN_FEATURE_WIFI = "http://tizen.org/feature/network.wifi";
+const char* TIZEN_FEATURE_WIFIDIRECT = "http://tizen.org/feature/network.wifi.direct";
+
+/*openGL ES feature*/
+const char* TIZEN_FEATURE_OPENGLES = "http://tizen.org/feature/opengles";
+const char* TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT =
+        "http://tizen.org/feature/opengles.texture_format";
+const char* TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_3DC =
+        "http://tizen.org/feature/opengles.texture_format.3dc";
+const char* TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_ATC =
+        "http://tizen.org/feature/opengles.texture_format.atc";
+const char* TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_ETC =
+        "http://tizen.org/feature/opengles.texture_format.etc";
+const char* TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_PTC =
+        "http://tizen.org/feature/opengles.texture_format.ptc";
+const char* TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_PVRTC =
+        "http://tizen.org/feature/opengles.texture_format.pvrtc";
+const char* TIZEN_FEATURE_OPENGLES_TEXTURE_FORMAT_UTC =
+        "http://tizen.org/feature/opengles.texture_format.utc";
+const char* TIZEN_FEATURE_OPENGLESVERSION1_1 = "http://tizen.org/feature/opengles.version.1_1";
+const char* TIZEN_FEATURE_OPENGLESVERSION2_0 = "http://tizen.org/feature/opengles.version.2_0";
+
+/*platform feature*/
+const char* TIZEN_FEATURE_CORE_API_VERSION = "http://tizen.org/feature/platform.core.api.version";
+const char* TIZEN_FEATURE_PLATFORM_CORE_CPU_ARCH = "http://tizen.org/feature/platform.core.cpu.arch";
+const char* TIZEN_FEATURE_PLATFORM_CORE_CPU_ARCH_ARMV6 =
+        "http://tizen.org/feature/platform.core.cpu.arch.armv6";
+const char* TIZEN_FEATURE_PLATFORM_CORE_CPU_ARCH_ARMV7 =
+        "http://tizen.org/feature/platform.core.cpu.arch.armv7";
+const char* TIZEN_FEATURE_PLATFORM_CORE_CPU_ARCH_X86 =
+        "http://tizen.org/feature/platform.core.cpu.arch.x86";
+const char* TIZEN_FEATURE_PLATFORM_CORE_CPU_FREQUENCY =
+        "http://tizen.org/feature/platform.core.cpu.frequency"; //TODO key will be added
+const char* TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH = "http://tizen.org/feature/platform.core.fpu.arch";
+const char* TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_SSE2 =
+        "http://tizen.org/feature/platform.core.fpu.arch.sse2";
+const char* TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_SSE3 =
+        "http://tizen.org/feature/platform.core.fpu.arch.sse3";
+const char* TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_SSSE3 =
+        "http://tizen.org/feature/platform.core.fpu.arch.ssse3";
+const char* TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_VFPV2 =
+        "http://tizen.org/feature/platform.core.fpu.arch.vfpv2";
+const char* TIZEN_FEATURE_PLATFORM_CORE_FPU_ARCH_VFPV3 =
+        "http://tizen.org/feature/platform.core.fpu.arch.vfpv3";
+const char* TIZEN_FEATURE_NATIVE_API_VERSION =
+        "http://tizen.org/feature/platform.native.api.version";
+const char* TIZEN_FEATURE_NATIVE_OSP_COMPATIBLE =
+        "http://tizen.org/feature/platform.native.osp_compatible";
+const char* TIZEN_FEATURE_PLATFORM_VERSION = "http://tizen.org/feature/platform.version";
+const char* TIZEN_FEATURE_PLATFORM_WEB_API_VERSION =
+        "http://tizen.org/feature/platform.web.api.version";
+const char* TIZEN_FETURE_PLATFORM_VERSION_NAME = "http://tizen.org/feature/platform.version.name"; //TODO key will be added
+
+/*profile feature*/
+const char* TIZEN_FEATURE_PROFILE = "http://tizen.org/feature/profile";
+
+/*Screen feature*/
+const char* TIZEN_FEATURE_SCREEN = "http://tizen.org/feature/screen";
+const char* TIZEN_FEATURE_AUTO_ROTATION = "http://tizen.org/feature/screen.auto_rotation";
+const char* TIZEN_FEATURE_SCREEN_BPP = "http://tizen.org/feature/screen.bpp";
+const char* TIZEN_FEATURE_SCREEN_COORDINATE_SYSTEM_SIZE_LARGE =
+        "http://tizen.org/feature/screen.coordinate_system.size.large";
+const char* TIZEN_FEATURE_SCREEN_COORDINATE_SYSTEM_SIZE_NORMAL =
+        "http://tizen.org/feature/screen.coordinate_system.size.normal";
+const char* TIZEN_FEATURE_SCREEN_DPI = "http://tizen.org/feature/screen.dpi";
+const char* TIZEN_FEATURE_SCREEN_HEIGHT = "http://tizen.org/feature/screen.height";
+const char* TIZEN_FEATURE_SCREEN_OUTPUT_HDMI = "http://tizen.org/feature/screen.output.hdmi";
+const char* TIZEN_FEATURE_SCREEN_OUTPUT_RCA = "http://tizen.org/feature/screen.output.rca";
+const char* TIZEN_FEATURE_SCREEN_SIZE_ALL = "http://tizen.org/feature/screen.size.all";
+const char* TIZEN_FEATURE_SCREEN_SIZE_LARGE = "http://tizen.org/feature/screen.size.large";
+const char* TIZEN_FEATURE_SCREENSIZE_NORMAL = "http://tizen.org/feature/screen.size.normal";
+const char* TIZEN_FEATURE_SCREENSIZE_240_400 = "http://tizen.org/feature/screen.size.normal.240.400";
+const char* TIZEN_FEATURE_SCREENSIZE_320_320 = "http://tizen.org/feature/screen.size.normal.320.320";
+const char* TIZEN_FEATURE_SCREENSIZE_320_480 = "http://tizen.org/feature/screen.size.normal.320.480";
+const char* TIZEN_FEATURE_SCREENSIZE_360_480 = "http://tizen.org/feature/screen.size.normal.360.480";
+const char* TIZEN_FEATURE_SCREENSIZE_480_800 = "http://tizen.org/feature/screen.size.normal.480.800";
+const char* TIZEN_FEATURE_SCREENSIZE_540_960 = "http://tizen.org/feature/screen.size.normal.540.960";
+const char* TIZEN_FEATURE_SCREENSIZE_600_1024 =
+        "http://tizen.org/feature/screen.size.normal.600.1024";
+const char* TIZEN_FEATURE_SCREENSIZE_720_1280 =
+        "http://tizen.org/feature/screen.size.normal.720.1280";
+const char* TIZEN_FEATURE_SCREENSIZE_1080_1920 =
+        "http://tizen.org/feature/screen.size.normal.1080.1920";
+const char* TIZEN_FEATURE_SCREEN_WIDTH = "http://tizen.org/feature/screen.width";
+
+/*Sensor faeture*/
+const char* TIZEN_FEATURE_ACCELEROMETER = "http://tizen.org/feature/sensor.accelerometer";
+const char* TIZEN_FEATURE_ACCELEROMETER_WAKEUP =
+        "http://tizen.org/feature/sensor.accelerometer.wakeup";
+const char* TIZEN_FEATURE_ACTIVITY_RECOGNITION =
+        "http://tizen.org/feature/sensor.activity_recognition";
+const char* TIZEN_FEATURE_BAROMETER = "http://tizen.org/feature/sensor.barometer";
+const char* TIZEN_FEATURE_BAROMETER_WAKEUP = "http://tizen.org/feature/sensor.barometer.wakeup";
+const char* TIZEN_FEATURE_GESTURE_RECOGNITION =
+        "http://tizen.org/feature/sensor.gesture_recognition";
+const char* TIZEN_FEATURE_GRAVITY = "http://tizen.org/feature/sensor.gravity";
+const char* TIZEN_FEATURE_GYROSCOPE = "http://tizen.org/feature/sensor.gyroscope";
+const char* TIZEN_FEATURE_GYROSCOPE_WAKEUP = "http://tizen.org/feature/sensor.gyroscope.wakeup";
+const char* TIZEN_FEATURE_HRM = "http://tizen.org/feature/sensor.heart_rate_monitor"; // true
+const char* TIZEN_FEATURE_HUMIDITY = "http://tizen.org/feature/sensor.humidity";
+const char* TIZEN_FEATURE_LINEAR_ACCELERATION =
+        "http://tizen.org/feature/sensor.linear_acceleration";
+const char* TIZEN_FEATURE_MAGNETOMETER = "http://tizen.org/feature/sensor.magnetometer";
+const char* TIZEN_FEATURE_MAGNETOMETER_WAKEUP =
+        "http://tizen.org/feature/sensor.magnetometer.wakeup";
+const char* TIZEN_FEATURE_PEDOMETER = "http://tizen.org/feature/sensor.pedometer";
+const char* TIZEN_FEATURE_PHOTOMETER = "http://tizen.org/feature/sensor.photometer";
+const char* TIZEN_FEATURE_PHOTOMETER_WAKEUP = "http://tizen.org/feature/sensor.photometer.wakeup";
+const char* TIZEN_FEATURE_PROXIMITY = "http://tizen.org/feature/sensor.proximity";
+const char* TIZEN_FEATURE_PROXIMITY_WAKEUP = "http://tizen.org/feature/sensor.proximity.wakeup";
+const char* TIZEN_FEATURE_ROTATION_VECTOR = "http://tizen.org/feature/sensor.rotation_vector";
+const char* TIZEN_FEATURE_TEMPERATURE = "http://tizen.org/feature/sensor.temperature";
+const char* TIZEN_FEATURE_TILTMETER = "http://tizen.org/feature/sensor.tiltmeter";
+const char* TIZEN_FEATURE_TILTMETER_WAKEUP = "http://tizen.org/feature/sensor.tiltmeter.wakeup";
+const char* TIZEN_FEATURE_ULTRAVIOLET = "http://tizen.org/feature/sensor.ultraviolet";
+const char* TIZEN_FEATURE_WRIST_UP = "http://tizen.org/feature/sensor.wrist_up";
+const char* TIZEN_FEATURE_HUMAN_ACTIVITY_MONITOR = "http://tizen.org/feature/humanactivitymonitor";
+
+/*Shell feature*/
+const char* TIZEN_FEATURE_SHELL_APP_WIDGET = "http://tizen.org/feature/shell.appwidget";
+
+/*Sip feature*/
+const char* TIZEN_FEATURE_SIPVOIP = "http://tizen.org/feature/sip.voip";
+
+/*speech feature*/
+const char* TIZEN_FEATURE_SPEECH_RECOGNITION = "http://tizen.org/feature/speech.recognition";
+const char* TIZEN_FEATURE_SPEECH_SYNTHESIS = "http://tizen.org/feature/speech.synthesis";
+
+/*USB feature*/
+const char* TIZEN_FEATURE_USBACCESSORY = "http://tizen.org/feature/usb.accessory";
+const char* TIZEN_FEATURE_USBHOST = "http://tizen.org/feature/usb.host";
+
+/*Web Service*/
+const char* TIZEN_FEATURE_WEB_SERVICE = "http://tizen.org/feature/web.service";
+
+/*vision*/
+const char* TIZEN_FEATURE_VISION_FACE_RECOGNITION =
+        "http://tizen.org/feature/vision.face_recognition";
+const char* TIZEN_FEATURE_VISION_IMAGE_RECOGNITION =
+        "http://tizen.org/feature/vision.image_recognition";
+const char* TIZEN_FEATURE_VISION_QRCODE_GENERATION =
+        "http://tizen.org/feature/vision.qrcode_generation";
+const char* TIZEN_FEATURE_VISION_QRCODE_RECOGNITION =
+        "http://tizen.org/feature/vision.qrcode_recognition";
+
+/*build information*/
+const char* TIZEN_SYSTEM_BUILD_DATE = "http://tizen.org/system/build.date";
+const char* TIZEN_SYSTEM_BUILD_STRING = "http://tizen.org/system/build.string";
+const char* TIZEN_SYSTEM_BUILD_TIME = "http://tizen.org/system/build.time";
+const char* TIZEN_SYSTEM_BUILD_MANUFACTURER = "http://tizen.org/system/manufacturer";
+
+/*duid*/
+const char* TIZEN_SYSTEM_TIZEN_ID = "http://tizen.org/system/tizenid";
+
+/*model name*/
+const char* TIZEN_SYSTEM_MODEL_NAME = "http://tizen.org/system/model_name";
+
+/*platform*/
+const char* TIZEN_SYSTEM_PLATFORM_NAME = "http://tizen.org/system/platform.name";
+const char* TIZEN_SYSTEM_PLATFORM_COMMUNICATION_PROCESSOR =
+        "http://tizen.org/system/platform.communication_processor";
+const char* TIZEN_SYSTEM_PLATFORM_PROCESSOR = "http://tizen.org/system/platform.processor";
+
+} //Systeminfo
+} //DeviceAPI
+
+#endif /* KEYS_H_ */
diff --git a/src/Systeminfo/config.xml b/src/Systeminfo/config.xml
new file mode 100755 (executable)
index 0000000..0fa65cb
--- /dev/null
@@ -0,0 +1,23 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-systeminfo.so</library-name>
+    <feature-install-uri>systeminfo.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/systeminfo</name>
+        <device-capability>system.info</device-capability>
+        <device-capability>systemmanager.info</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/system</name>
+        <device-capability>system.info</device-capability>
+    </api-feature>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/systemmanager</name>
+        <device-capability>systemmanager.info</device-capability>
+    </api-feature>
+</plugin-properties>
+
diff --git a/src/Systeminfo/plugin_config.cpp b/src/Systeminfo/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..46b1941
--- /dev/null
@@ -0,0 +1,121 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <map>
+#include <utility>
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <Export.h>
+#include "plugin_config.h"
+#include "plugin_config_impl.h"
+
+#define SYSTEMINFO_FEATURE_API_MASTER           "http://tizen.org/privilege/systeminfo"
+#define SYSTEMINFO_FEATURE_API_SYSTEMINFO       "http://tizen.org/privilege/system"
+#define SYSTEMINFO_FEATURE_API_SYSTEMMANAGER    "http://tizen.org/privilege/systemmanager"
+
+#define SYSTEMINFO_DEVICE_CAP_SYSTEMINFO        "system.info"
+#define SYSTEMINFO_DEVICE_CAP_SYSTEMMANAGER     "system.manager"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+static WrtDeviceApis::Commons::FunctionMapping createSystemInfoFunctions();
+
+static WrtDeviceApis::Commons::FunctionMapping SystemInfoFunctions =
+    createSystemInfoFunctions();
+
+DEFINE_FUNCTION_GETTER(SystemInfo, SystemInfoFunctions);
+
+WrtDeviceApis::Commons::AceSecurityStatus DLL_EXPORT systemInfoAceCheckAccessFunction(const char* functionName)
+{
+       return WrtDeviceApis::Commons::aceCheckAccess<AceFunctionGetter,
+                       WrtDeviceApis::Commons::DefaultArgsVerifier<> >(
+                       getSystemInfoFunctionData, functionName);
+}
+
+static WrtDeviceApis::Commons::FunctionMapping createSystemInfoFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    using namespace WrtDeviceApis::Commons;
+
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_SYSTEMINFO, SYSTEMINFO_DEVICE_CAP_SYSTEMINFO);
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_SYSTEMMANAGER, SYSTEMINFO_DEVICE_CAP_SYSTEMMANAGER);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_SYSTEMINFO);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_SYSTEMINFO, DEVICE_CAP_SYSTEMINFO);
+
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_SYSTEMMANAGER);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_SYSTEMMANAGER, DEVICE_CAP_SYSTEMMANAGER);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_MASTER, SYSTEMINFO_FEATURE_API_MASTER);
+    ACE_CREATE_FEATURE(FEATURE_SYSTEMINFO, SYSTEMINFO_FEATURE_API_SYSTEMINFO);
+    ACE_CREATE_FEATURE(FEATURE_SYSTEMMANAGER, SYSTEMINFO_FEATURE_API_SYSTEMMANAGER);
+
+    ACE_CREATE_FEATURE_LIST(SYSTEMINFO_FEATURES_SYSTEMINFO);
+    ACE_ADD_API_FEATURE(SYSTEMINFO_FEATURES_SYSTEMINFO, FEATURE_MASTER);
+    ACE_ADD_API_FEATURE(SYSTEMINFO_FEATURES_SYSTEMINFO, FEATURE_SYSTEMINFO);
+
+    ACE_CREATE_FEATURE_LIST(SYSTEMINFO_FEATURES_SYSTEMMANAGER);
+    ACE_ADD_API_FEATURE(SYSTEMINFO_FEATURES_SYSTEMMANAGER, FEATURE_MASTER);
+    ACE_ADD_API_FEATURE(SYSTEMINFO_FEATURES_SYSTEMMANAGER, FEATURE_SYSTEMMANAGER);
+
+    /**
+     * Functions
+     */
+    FunctionMapping SystemInfoMapping;
+
+    AceFunction getCapabilitiesFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_GET_CAPABILITIES,
+        SYSTEMINFO_FUNCTION_API_GET_CAPABILITIES,
+        SYSTEMINFO_FEATURES_SYSTEMINFO,
+        DEVICE_LIST_SYSTEMINFO);
+    SystemInfoMapping.insert(
+            std::make_pair(SYSTEMINFO_FUNCTION_API_GET_CAPABILITIES,
+                    getCapabilitiesFunc));
+
+    AceFunction getPropertyPartnerValueFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_GET_PROPERTY_PARTNER_VALUE,
+        SYSTEMINFO_FUNCTION_API_GET_PROPERTY_PARTNER_VALUE,
+        SYSTEMINFO_FEATURES_SYSTEMMANAGER,
+        DEVICE_LIST_SYSTEMINFO);
+    SystemInfoMapping.insert(
+            std::make_pair(SYSTEMINFO_FUNCTION_API_GET_PROPERTY_PARTNER_VALUE,
+                    getPropertyPartnerValueFunc));
+
+    AceFunction getPropertySimValueFunc = ACE_CREATE_FUNCTION(
+        FUNCTION_GET_PROPERTY_SIM_VALUE,
+        SYSTEMINFO_FUNCTION_API_GET_PROPERTY_SIM_VALUE,
+        SYSTEMINFO_FEATURES_SYSTEMINFO,
+        DEVICE_LIST_SYSTEMINFO);
+    SystemInfoMapping.insert(
+            std::make_pair(SYSTEMINFO_FUNCTION_API_GET_PROPERTY_SIM_VALUE,
+                    getPropertySimValueFunc));
+
+    return SystemInfoMapping;
+}
+}
+}
+
+#undef SYSTEMINFO_FEATURE_API
diff --git a/src/Systeminfo/plugin_config.h b/src/Systeminfo/plugin_config.h
new file mode 100755 (executable)
index 0000000..7cfe650
--- /dev/null
@@ -0,0 +1,35 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _SYSTEMINFO_PLUGIN_CONFIG_H_
+#define _SYSTEMINFO_PLUGIN_CONFIG_H_
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+WrtDeviceApis::Commons::AceSecurityStatus systemInfoAceCheckAccessFunction(const char* functionName);
+
+#define SYSTEMINFO_CHECK_ACCESS(functionName)               \
+               DeviceAPI::SystemInfo::systemInfoAceCheckAccessFunction(functionName)
+}
+}
+
+#endif
diff --git a/src/Systeminfo/plugin_config_impl.h b/src/Systeminfo/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..ac7c426
--- /dev/null
@@ -0,0 +1,27 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _SYSTEMINFO_PLUGIN_CONFIG_IMPL_H_
+#define _SYSTEMINFO_PLUGIN_CONFIG_IMPL_H_
+
+#define TIZEN_SYSTEMINFO_SYSTEMINFO_CLASS "systeminfo"
+
+#define SYSTEMINFO_FUNCTION_API_GET_CAPABILITIES "getCapabilities"
+#define SYSTEMINFO_FUNCTION_API_GET_PROPERTY_PARTNER_VALUE "getPropertyPartnerValue"
+#define SYSTEMINFO_FUNCTION_API_GET_PROPERTY_SIM_VALUE "getPropertySimValue"
+
+#endif //_SYSTEMINFO_PLUGIN_CONFIG_IMPL_H_
diff --git a/src/Systeminfo/plugin_initializer.cpp b/src/Systeminfo/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..448b42c
--- /dev/null
@@ -0,0 +1,90 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+#include <Logger.h>
+#include <TimeTracer.h>
+
+#include "JSSystemInfo.h"
+#include "plugin_config.h"
+
+namespace DeviceAPI {
+namespace SystemInfo {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[Tizen\\systeminfo ] on_widget_start_callback (%d)", widgetId);
+    TIME_TRACER_INIT();
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    }
+    catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[Tizen\\systeminfo ] on_widget_stop_callback (%d)", widgetId);
+    std::string name = "SystemInfo";
+    TIME_TRACER_EXPORT_REPORT_TO(TIME_TRACER_EXPORT_FILE, const_cast<char*>(name.c_str()));
+    TIME_TRACER_RELEASE();
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    }
+    catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\systeminfo] on_frame_load_callback (%p)", context);
+
+    Common::GlobalContextManager::getInstance()->addGlobalContext(
+            static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\systeminfo] on_frame_unload_callback (%p)", context);
+
+    Common::GlobalContextManager::getInstance()->removeGlobalContext(
+            static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_SYSTEMINFO_SYSTEMINFO_CLASS,
+        (js_class_template_getter)SystemInfo::JSSystemInfo::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_END
+
+} // SystemInfo
+} // DeviceAPI
diff --git a/src/TimeUtil/CMakeLists.txt b/src/TimeUtil/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..6a489d6
--- /dev/null
@@ -0,0 +1,54 @@
+SET(TARGET_NAME ${timeutil_target})
+SET(DESTINATION_NAME ${timeutil_dest})
+SET(TARGET_IMPL_NAME ${timeutil_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_time REQUIRED icu-i18n icu-io icu-le icu-lx icu-uc )
+
+#This module should be public by default since it is being used directly
+#by other modules for example Calendar.
+#Therefore ADD_DEFINITIONS("-fvisibility=hidden") is not present here.
+#
+
+INCLUDE_DIRECTORIES(
+    ${INCLUDE_COMMON}
+    ${platform_pkgs_time_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSTimeUtil.cpp
+    JSTZDate.cpp
+    JSTimeDuration.cpp
+    TimeDuration.cpp
+    TimeUtil.cpp
+    TZDate.cpp
+    TimeUtilTools.cpp
+    TimeUtilConverter.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+)
+
+SET(SRCS
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/timeutil
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/TimeUtil/DurationProperties.h b/src/TimeUtil/DurationProperties.h
new file mode 100755 (executable)
index 0000000..b2d7268
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License. 
+ */
+
+
+
+#ifndef WRTPLUGINS_API_TIMEUTIL_DURATION_PROPERTIES_H_
+#define WRTPLUGINS_API_TIMEUTIL_DURATION_PROPERTIES_H_
+
+#include <memory>
+#include <string>
+
+using namespace std;
+
+namespace DeviceAPI {
+namespace Time {
+
+namespace {
+    const short MSECS_UNIT = 0;
+    const short SECONDS_UNIT = 1;
+    const short MINUTES_UNIT = 2;
+    const short HOURS_UNIT = 3;
+    const short DAYS_UNIT = 4;
+}
+
+struct DurationProperties {
+    long long length;
+    short unit;
+    DurationProperties()
+        : length(0),
+        unit(MSECS_UNIT) {
+    }
+};
+
+typedef std::shared_ptr<DurationProperties> DurationPropertiesPtr;
+
+} // Time
+} // DeviceAPI
+
+#endif //WRTPLUGINS_API_TIMEUTIL_DURATION_PROPERTIES_H_
\ No newline at end of file
diff --git a/src/TimeUtil/JSTZDate.cpp b/src/TimeUtil/JSTZDate.cpp
new file mode 100755 (executable)
index 0000000..000d224
--- /dev/null
@@ -0,0 +1,1776 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <ctime>
+#include <string>
+#include <Logger.h>
+#include <ArgumentValidator.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+#include <string>
+
+#include "JSTZDate.h"
+#include "JSTimeDuration.h"
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+#include "TimeUtilTools.h"
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Time {
+
+// It is moved to JSTZDate.h file.
+/*
+struct TZDateHolder {
+    TZDatePtr ptr;
+};
+*/
+
+namespace {
+const char* CLASS_NAME = "TZDate";
+
+const char* TZDATE_FUNCTION_API_GET_DATE = "getDate";
+const char* TZDATE_FUNCTION_API_SET_DATE = "setDate";
+const char* TZDATE_FUNCTION_API_GET_DAY = "getDay";
+const char* TZDATE_FUNCTION_API_GET_FULL_YEAR = "getFullYear";
+const char* TZDATE_FUNCTION_API_SET_FULL_YEAR = "setFullYear";
+const char* TZDATE_FUNCTION_API_GET_HOURS = "getHours";
+const char* TZDATE_FUNCTION_API_SET_HOURS = "setHours";
+const char* TZDATE_FUNCTION_API_GET_MILLISECONDS = "getMilliseconds";
+const char* TZDATE_FUNCTION_API_SET_MILLISECONDS = "setMilliseconds";
+const char* TZDATE_FUNCTION_API_GET_MINUTES = "getMinutes";
+const char* TZDATE_FUNCTION_API_SET_MINUTES = "setMinutes";
+const char* TZDATE_FUNCTION_API_GET_MONTH = "getMonth";
+const char* TZDATE_FUNCTION_API_SET_MONTH = "setMonth";
+const char* TZDATE_FUNCTION_API_GET_SECONDS = "getSeconds";
+const char* TZDATE_FUNCTION_API_SET_SECONDS = "setSeconds";
+const char* TZDATE_FUNCTION_API_GET_UTC_DATE = "getUTCDate";
+const char* TZDATE_FUNCTION_API_SET_UTC_DATE = "setUTCDate";
+const char* TZDATE_FUNCTION_API_GET_UTC_DAY = "getUTCDay";
+const char* TZDATE_FUNCTION_API_GET_UTC_FULL_YEAR = "getUTCFullYear";
+const char* TZDATE_FUNCTION_API_SET_UTC_FULL_YEAR = "setUTCFullYear";
+const char* TZDATE_FUNCTION_API_GET_UTC_HOURS = "getUTCHours";
+const char* TZDATE_FUNCTION_API_SET_UTC_HOURS = "setUTCHours";
+const char* TZDATE_FUNCTION_API_GET_UTC_MILLISECONDS = "getUTCMilliseconds";
+const char* TZDATE_FUNCTION_API_SET_UTC_MILLISECONDS = "setUTCMilliseconds";
+const char* TZDATE_FUNCTION_API_GET_UTC_MINUTES = "getUTCMinutes";
+const char* TZDATE_FUNCTION_API_SET_UTC_MINUTES = "setUTCMinutes";
+const char* TZDATE_FUNCTION_API_GET_UTC_MONTH = "getUTCMonth";
+const char* TZDATE_FUNCTION_API_SET_UTC_MONTH = "setUTCMonth";
+const char* TZDATE_FUNCTION_API_GET_UTC_SECONDS = "getUTCSeconds";
+const char* TZDATE_FUNCTION_API_SET_UTC_SECONDS = "setUTCSeconds";
+const char* TZDATE_FUNCTION_API_GET_TIMEZONE = "getTimezone";
+const char* TZDATE_FUNCTION_API_TO_TIMEZONE = "toTimezone";
+const char* TZDATE_FUNCTION_API_TO_LOCAL_TIMEZONE = "toLocalTimezone";
+const char* TZDATE_FUNCTION_API_TO_UTC = "toUTC";
+const char* TZDATE_FUNCTION_API_DIFFERENCE = "difference";
+const char* TZDATE_FUNCTION_API_EQUALS_TO = "equalsTo";
+const char* TZDATE_FUNCTION_API_EARLIER_THAN = "earlierThan";
+const char* TZDATE_FUNCTION_API_LATER_THAN = "laterThan";
+const char* TZDATE_FUNCTION_API_ADD_DURATION = "addDuration";
+const char* TZDATE_FUNCTION_API_TO_LOCALE_DATE_STRING = "toLocaleDateString";
+const char* TZDATE_FUNCTION_API_TO_LOCALE_TIME_STRING = "toLocaleTimeString";
+const char* TZDATE_FUNCTION_API_TO_LOCALE_STRING = "toLocaleString";
+const char* TZDATE_FUNCTION_API_TO_DATE_STRING = "toDateString";
+const char* TZDATE_FUNCTION_API_TO_TIME_STRING = "toTimeString";
+const char* TZDATE_FUNCTION_API_TO_STRING = "toString";
+const char* TZDATE_FUNCTION_API_GET_TIMEZONE_ABBREVIATION = "getTimezoneAbbreviation";
+const char* TZDATE_FUNCTION_API_SECONDS_FROM_UTC = "secondsFromUTC";
+const char* TZDATE_FUNCTION_API_IS_DST = "isDST";
+const char* TZDATE_FUNCTION_API_GET_PREVIOUS_DST_TRANSITION = "getPreviousDSTTransition";
+const char* TZDATE_FUNCTION_API_GET_NEXT_DST_TRANSITION = "getNextDSTTransition";
+}
+
+JSClassDefinition JSTZDate::m_classInfo = {
+    0,
+    kJSClassAttributeNone,
+    CLASS_NAME,
+    0,
+    NULL,//property,
+    m_function,
+    initialize,
+    finalize,
+    NULL, //hasProperty,
+    NULL, //getProperty,
+    NULL, //setProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL  //ConvertToType
+};
+
+JSStaticFunction JSTZDate::m_function[] = {
+    {TZDATE_FUNCTION_API_GET_DATE, JSTZDate::getDate, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_DATE, JSTZDate::setDate, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_DAY, JSTZDate::getDay, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_FULL_YEAR, JSTZDate::getFullYear, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_FULL_YEAR, JSTZDate::setFullYear, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_HOURS, JSTZDate::getHours, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_HOURS, JSTZDate::setHours, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_MILLISECONDS, JSTZDate::getMilliseconds, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_MILLISECONDS, JSTZDate::setMilliseconds, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_MINUTES, JSTZDate::getMinutes, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_MINUTES, JSTZDate::setMinutes, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_MONTH, JSTZDate::getMonth, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_MONTH, JSTZDate::setMonth, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_SECONDS, JSTZDate::getSeconds, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_SECONDS, JSTZDate::setSeconds, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_UTC_DATE, JSTZDate::getUTCDate, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_UTC_DATE, JSTZDate::setUTCDate, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_UTC_DAY, JSTZDate::getUTCDay, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_UTC_FULL_YEAR, JSTZDate::getUTCFullYear, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_UTC_FULL_YEAR, JSTZDate::setUTCFullYear, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_UTC_HOURS, JSTZDate::getUTCHours, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_UTC_HOURS, JSTZDate::setUTCHours, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_UTC_MILLISECONDS, JSTZDate::getUTCMilliseconds, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_UTC_MILLISECONDS, JSTZDate::setUTCMilliseconds, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_UTC_MINUTES, JSTZDate::getUTCMinutes, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_UTC_MINUTES, JSTZDate::setUTCMinutes, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_UTC_MONTH, JSTZDate::getUTCMonth, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_UTC_MONTH, JSTZDate::setUTCMonth, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_UTC_SECONDS, JSTZDate::getUTCSeconds, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SET_UTC_SECONDS, JSTZDate::setUTCSeconds, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_TIMEZONE, JSTZDate::getTimezone, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_TO_TIMEZONE, JSTZDate::toTimezone, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_TO_LOCAL_TIMEZONE, JSTZDate::toLocalTimezone, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_TO_UTC, JSTZDate::toUTC, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_DIFFERENCE, JSTZDate::difference, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_EQUALS_TO, JSTZDate::equalsTo, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_EARLIER_THAN, JSTZDate::earlierThan, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_LATER_THAN, JSTZDate::laterThan, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_ADD_DURATION, JSTZDate::addDuration, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_TO_LOCALE_DATE_STRING, JSTZDate::toLocaleDateString, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_TO_LOCALE_TIME_STRING, JSTZDate::toLocaleTimeString, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_TO_LOCALE_STRING, JSTZDate::toLocaleString, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_TO_DATE_STRING, JSTZDate::toDateString, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_TO_TIME_STRING, JSTZDate::toTimeString, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_TO_STRING, JSTZDate::toString, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_TIMEZONE_ABBREVIATION, JSTZDate::getTimezoneAbbreviation, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_SECONDS_FROM_UTC, JSTZDate::secondsFromUTC, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_IS_DST, JSTZDate::isDST, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_PREVIOUS_DST_TRANSITION, JSTZDate::getPreviousDSTTransition, kJSPropertyAttributeNone},
+    {TZDATE_FUNCTION_API_GET_NEXT_DST_TRANSITION, JSTZDate::getNextDSTTransition, kJSPropertyAttributeNone},
+    { 0, 0, 0}
+};
+
+const JSClassRef JSTZDate::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSTZDate::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSTZDate::m_jsClassRef = JSClassCreate(JSTZDate::getClassInfo());
+
+void JSTZDate::initialize(JSContextRef context, JSObjectRef object)
+{
+
+}
+
+void JSTZDate::finalize(JSObjectRef object)
+{
+    TZDateHolder *priv = static_cast<TZDateHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+JSObjectRef JSTZDate::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered constructor()");
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, obj, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    TZDatePtr priv;
+    std::map <const std::string, int> month_map = {
+            {"Jan", 0},
+            {"Feb", 1},
+            {"Mar", 2},
+            {"Apr", 3},
+            {"May", 4},
+            {"Jun", 5},
+            {"Jul", 6},
+            {"Aug", 7},
+            {"Sep", 8},
+            {"Oct", 9},
+            {"Nov", 10},
+            {"Dec", 11}
+    };
+    try {
+        std::string timezone = "";
+        time_t datetime = time(NULL);
+        if (0 == argumentCount) {
+            priv = TZDatePtr(new (std::nothrow) TZDate(datetime, ""));
+        }
+        if (argumentCount >= 3) {
+            try {
+                priv = TZDatePtr(new (std::nothrow) TZDate(
+                        validator.toLong(0), validator.toLong(1), validator.toLong(2),
+                        validator.toLong(3, true, 0), validator.toLong(4, true, 0),
+                        validator.toLong(5, true, 0), validator.toLong(6, true, 0),
+                        validator.toString(7, true, "")));
+            } catch (const BasePlatformException& err) {
+                LOGW("TZDate creation failed. %s", err.getMessage().c_str());
+            }
+        }
+        if (1 == argumentCount) {
+            try {
+                if (!validator.isNull(0) and !validator.isUndefined(0)) {
+                    long long milliseconds = 0;
+                    JSObjectRef o = validator.toObject(0);
+                    datetime = validator.toTimeT(0, true, datetime);
+                    milliseconds = TimeUtilTools::getMilliseconds(context, o);
+                    if (INT_MAX != ((int)datetime) && INT_MIN != ((int) datetime)) {
+                        priv = TZDatePtr(new (std::nothrow) TZDate(datetime));
+                        priv->setMilliseconds(milliseconds % 1000);
+                    } else {
+                        std::string ts = validator.toString(0,true,std::to_string(datetime));
+                        int d=0, y=0, h=0, m=0, s=0;
+                        std::string mon="", tstr="", D="";
+                        std::istringstream iss(ts);
+                        iss >> D >> mon >> d >> y >> tstr;
+                        sscanf(tstr.c_str(), "%d:%d:%d", &h, &m, &s);
+                        priv = TZDatePtr(new (std::nothrow) TZDate(y, month_map[mon], d, h, m, milliseconds%1000>=0?s:s+1, milliseconds%1000, timezone));
+                    }
+                }
+                else {
+                    priv = TZDatePtr(new (std::nothrow) TZDate(datetime, ""));
+                }
+            } catch (const BasePlatformException& err) {
+                LOGW("Date conversion is failed. %s", err.getMessage().c_str());
+            }
+        }
+        if (2 == argumentCount) { //if 1 exist returns true
+            long long milliseconds = 0;
+            if (!validator.isNull(1) and !validator.isUndefined(1)) {
+                timezone = validator.toString(1, true, "");
+            }
+            if (!validator.isNull(0) and !validator.isUndefined(0)) {
+                datetime = validator.toTimeT(0, true, datetime);
+                milliseconds = TimeUtilTools::getMilliseconds(context, validator.toObject(0));
+            }
+            if (INT_MAX != ((int)datetime) && INT_MIN != ((int) datetime)) {
+                priv = TZDatePtr(new (std::nothrow) TZDate(datetime, timezone));
+                priv->setMilliseconds(milliseconds % 1000);
+            } else {
+                std::string ts = validator.toString(0,true,std::to_string(datetime));
+                int d=0, y=0, h=0, m=0, s=0;
+                std::string mon="", tstr="", D="";
+                std::istringstream iss(ts);
+                iss >> D >> mon >> d >> y >> tstr;
+                sscanf(tstr.c_str(), "%d:%d:%d", &h, &m, &s);
+                priv = TZDatePtr(new (std::nothrow) TZDate(y, month_map[mon], d, h, m, milliseconds%1000>=0?s:s+1, milliseconds%1000, timezone));
+            }
+        }
+        obj = JSTZDate::makeJSObject(context, priv);
+    } catch (const BasePlatformException& err) {
+        LOGE("Date conversion is failed. %s", err.getMessage().c_str());
+    } catch (...) {
+        LOGE("An error occured");
+    }
+
+    return obj;
+}
+
+TZDatePtr JSTZDate::getPrivateObject(JSContextRef context, JSValueRef value) {
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    TZDateHolder* priv = static_cast<TZDateHolder*>(JSObjectGetPrivate(object));
+    if (!priv or !priv->ptr) {
+        LOGE("Priv is null");
+        throw InvalidValuesException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSTZDate::setPrivateObject(JSObjectRef object, TZDatePtr native) {
+    LOGD("Entered");
+    TZDateHolder* priv = static_cast<TZDateHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSTZDate::makeJSObject(JSContextRef context, TZDatePtr native) {
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    TZDateHolder* priv = new (std::nothrow) TZDateHolder();
+    if (!priv) {
+        LOGE("Memory allocation for priv failed");
+        throw UnknownException("Memory allocation for priv failed");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+JSValueRef JSTZDate::getDate(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getDate()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getDate();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getDate().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setDate(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setDate()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setDate(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setDate().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getDay(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getDay()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getDay();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getDay().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getFullYear(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getFullYear()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getFullYear();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getFullYear().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setFullYear(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setFullYear()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setFullYear(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setFullYear().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getHours(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getHours()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getHours();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getHours().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setHours(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setHours()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setHours(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setHours().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getMilliseconds(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getMilliseconds()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getMilliseconds();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getMilliseconds().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setMilliseconds(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setMilliseconds()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setMilliseconds(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+           err("Unknown Error in tizen.TZDate.setMilliseconds().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getMinutes(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getMinutes()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getMinutes();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getMinutes().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setMinutes(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setMinutes()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setMinutes(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setMinutes().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getMonth(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getMonth()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getMonth();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getMonth().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setMonth(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setMonth()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setMonth(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setMonth().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getSeconds(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getSeconds()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getSeconds();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getSeconds().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setSeconds(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setSeconds()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setSeconds(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setSeconds().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getUTCDate(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getUTCDate()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getUTCDate();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getUTCDate().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setUTCDate(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setUTCDate()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setUTCDate(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setUTCDate().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getUTCDay(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getUTCDay()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getUTCDay();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getUTCDay().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getUTCFullYear(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getUTCFullYear()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getUTCFullYear();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getUTCFullYear().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setUTCFullYear(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setUTCFullYear()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setUTCFullYear(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setUTCFullYear().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getUTCHours(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getUTCHours()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getUTCHours();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getUTCHours().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setUTCHours(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setUTCHours()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setUTCHours(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setUTCHours().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getUTCMilliseconds(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getUTCMilliseconds()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getUTCMilliseconds();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getUTCMilliseconds().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setUTCMilliseconds(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setUTCMilliseconds()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setUTCMilliseconds(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setUTCMilliseconds().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getUTCMinutes(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getUTCMinutes()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getUTCMinutes();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getUTCMinutes().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setUTCMinutes(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setUTCMinutes()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setUTCMinutes(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setUTCMinutes().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getUTCMonth(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getUTCMonth()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getUTCMonth();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getUTCMonth().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setUTCMonth(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setUTCMonth()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setUTCMonth(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setUTCMonth().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getUTCSeconds(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getUTCSeconds()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long date = priv->getUTCSeconds();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getUTCSeconds().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::setUTCSeconds(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered setUTCSeconds()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        priv->setUTCSeconds(validator.toLong(0));
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.setUTCSeconds().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getTimezone(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getTimezone()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        std::string date = priv->getTimezone();
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getTimezone().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::toTimezone(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered toTimezone()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        TZDatePtr diff = priv->toTimezone(validator.toString(0));
+        JSObjectRef obj = JSTZDate::makeJSObject(context, diff);
+        return obj;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.toTimezone().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::toLocalTimezone(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered toLocalTimezone()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        TZDatePtr diff = priv->toLocalTimezone();
+        JSObjectRef obj = JSTZDate::makeJSObject(context, diff);
+        return obj;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.toLocalTimezone().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::toUTC(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered toUTC");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        TZDatePtr diff = priv->toUTC();
+        JSObjectRef obj = JSTZDate::makeJSObject(context, diff);
+        return obj;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.toUTC().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::difference(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered difference()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef otherObj = validator.toObject(0, JSTZDate::getClassRef());
+        TZDatePtr other = JSTZDate::getPrivateObject(context, otherObj);
+        TimeDurationPtr diff = priv->difference(other);
+        JSObjectRef obj = JSTimeDuration::makeJSObject(context, diff);
+        return obj;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.difference().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::equalsTo(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered equalsTo()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef otherObj = validator.toObject(0, JSTZDate::getClassRef());
+        TZDatePtr other = JSTZDate::getPrivateObject(context, otherObj);
+        bool isDst = priv->equalsTo(other);
+        return JSUtil::toJSValueRef(context, isDst);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.equalsTo().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::earlierThan(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered earlierThan()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef otherObj = validator.toObject(0, JSTZDate::getClassRef());
+        TZDatePtr other = JSTZDate::getPrivateObject(context, otherObj);
+        bool isDst = priv->earlierThan(other);
+        return JSUtil::toJSValueRef(context, isDst);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.earlierThan().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::laterThan(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered laterThan()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef otherObj = validator.toObject(0, JSTZDate::getClassRef());
+        TZDatePtr other = JSTZDate::getPrivateObject(context, otherObj);
+        bool isDst = priv->laterThan(other);
+        return JSUtil::toJSValueRef(context, isDst);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.laterThan().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::addDuration(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered addDuration");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        JSObjectRef otherObj = validator.toObject(0, JSTimeDuration::getClassRef());
+        TimeDurationPtr other = JSTimeDuration::getPrivateObject(context, otherObj);
+        TZDatePtr diff = priv->addDuration(other);
+        JSObjectRef obj = JSTZDate::makeJSObject(context, diff);
+        return obj;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.addDuration().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::toLocaleDateString(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered toLocaleDateString()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        std::string abbr = priv->toLocaleDateString();
+        return JSUtil::toJSValueRef(context, abbr);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.toLocaleDateString().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::toLocaleTimeString(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered toLocaleTimeString()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        std::string abbr = priv->toLocaleTimeString();
+        return JSUtil::toJSValueRef(context, abbr);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.toLocaleTimeString().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::toLocaleString(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered toLocaleString()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        std::string abbr = priv->toLocaleString();
+        return JSUtil::toJSValueRef(context, abbr);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.toLocaleString().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::toDateString(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered toDateString()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        std::string abbr = priv->toDateString();
+        return JSUtil::toJSValueRef(context, abbr);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.toDateString().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::toTimeString(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered toTimeString()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        std::string abbr = priv->toTimeString();
+        return JSUtil::toJSValueRef(context, abbr);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.toTimeString().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::toString(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered toString()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        std::string str = priv->toString();
+        return JSUtil::toJSValueRef(context, str);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.toString().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getTimezoneAbbreviation(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getTimezoneAbbreviation()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        std::string abbr = priv->getTimezoneAbbreviation();
+        return JSUtil::toJSValueRef(context, abbr);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getTimezoneAbbreviation().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::secondsFromUTC(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered secondsFromUTC()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        long sec = priv->secondsFromUTC();
+        return JSUtil::toJSValueRef(context, sec);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.secondsFromUTC().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::isDST(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered isDST()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        bool isDst = priv->isDST();
+        return JSUtil::toJSValueRef(context, isDst);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.isDST().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getPreviousDSTTransition(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getPreviousDSTTransition()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        return JSTZDate::makeJSObject(context, priv->getDSTTransition(PREVDST));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getPreviousDSTTransition().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTZDate::getNextDSTTransition(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered getNextDSTTransition()");
+
+    try {
+        TZDatePtr priv = getPrivateObject(context, thisObject);
+        return JSTZDate::makeJSObject(context, priv->getDSTTransition(NEXTDST));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TZDate.getNextDSTTransition().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+
+JSObjectRef JSTZDate::createJSObject(JSContextRef context, TZDatePtr tzDate)
+{
+    LOGD("Entered");
+    if (!tzDate) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    TZDateHolder* priv = new (std::nothrow) TZDateHolder();
+    if (!priv) {
+        LOGE("Memory allocation for priv failed");
+        throw UnknownException("Memory allocation for priv failed");
+    }
+    priv->ptr = tzDate;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+
+}
+
+JSObjectRef JSTZDate::createJSObject(JSContextRef context, const bool isNotNull) {
+    LOGD("entered");
+    TZDatePtr tzDate(new TZDate(isNotNull));
+    return createJSObject(context, tzDate);
+}
+
+JSObjectRef JSTZDate::createJSObject(JSContextRef context, const std::string &timezone)
+{
+    LOGD("entered");
+    if (timezone == "")
+        return createJSObject(context);
+
+    TZDatePtr tzDate(new TZDate(timezone));
+    return createJSObject(context, tzDate);
+}
+
+JSObjectRef JSTZDate::createJSObject(JSContextRef context, const double milliseconds, const std::string &timezone)
+{
+    LOGD("entered");
+    TZDatePtr tzDate;
+    if (timezone == "")
+        tzDate = TZDatePtr(new TZDate());
+    else
+        tzDate = TZDatePtr(new TZDate(timezone));
+
+    if (!tzDate->setTime(milliseconds)) {
+        ThrowMsg(WrtDeviceApis::Commons::UnknownException, "Can not set UTC Time");
+    }
+
+    return createJSObject(context, tzDate);
+}
+
+JSObjectRef JSTZDate::createJSObject(JSContextRef context, const std::string &dateString, const double milliseconds, const std::string &timezone)
+{
+    LOGD("entered");
+    TZDatePtr tzDate = TZDatePtr(new TZDate(dateString, milliseconds, timezone));
+
+    return createJSObject(context, tzDate);
+}
+
+JSObjectRef JSTZDate::createJSObject(JSContextRef context, const TZDateProperties &properties)
+{
+    LOGD("entered");
+    TZDatePtr tzDate(new TZDate(properties));
+
+    return createJSObject(context, tzDate);
+}
+
+JSObjectRef JSTZDate::createJSObject(JSContextRef context, const long year, const long month,  const long day, const long hours, const long minutes, const long seconds, const long milliseconds, const std::string &timezone)
+{
+    LOGD("entered");
+
+    TZDateProperties props;
+    props.year = year;
+    props.month = month;
+    props.day = day;
+    props.hours = hours;
+    props.minutes = minutes;
+    props.seconds = seconds;
+    props.milliseconds = milliseconds;
+    props.timezone = timezone;
+
+    return createJSObject(context, props);
+
+}
+
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+} //Time
+} //DeviceAPI
diff --git a/src/TimeUtil/JSTZDate.h b/src/TimeUtil/JSTZDate.h
new file mode 100755 (executable)
index 0000000..aaa84a3
--- /dev/null
@@ -0,0 +1,444 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_TZDATE_H_
+#define __TIZEN_JS_TZDATE_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "TZDate.h"
+
+namespace DeviceAPI {
+namespace Time {
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+struct TZDateHolder {
+    TZDatePtr ptr;
+};
+#endif //IMPL_BACKWARD_COMPATIBLE
+
+class JSTZDate {
+public:
+
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static TZDatePtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, TZDatePtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, TZDatePtr native);
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+
+    static JSObjectRef createJSObject(JSContextRef context, TZDatePtr tzDate);
+    static JSObjectRef createJSObject(JSContextRef context, const bool isNotNull = true);
+    static JSObjectRef createJSObject(JSContextRef context, const std::string &timezone);
+    static JSObjectRef createJSObject(JSContextRef context, const double milliseconds, const std::string &timezone);
+    static JSObjectRef createJSObject(JSContextRef context, const TZDateProperties &properties);
+    static JSObjectRef createJSObject(JSContextRef context, const long year, const long month,  const long day, const long hours, const long minutes, const long seconds, const long milliseconds, const std::string &timezone);
+    static JSObjectRef createJSObject(JSContextRef context, const std::string &dateString, const double milliseconds, const std::string &timezone);
+
+#endif //IMPL_BACKWARD_COMPATIBLE
+
+private:
+    /**
+     * This member variable contains the values which has to be passed when
+     * the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Functions declaration for the JSTZDate interface.
+     */
+    static JSValueRef getDate(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setDate(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getDay(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getFullYear(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setFullYear(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getHours(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setHours(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getMilliseconds(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setMilliseconds(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getMinutes(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setMinutes(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getMonth(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setMonth(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getSeconds(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setSeconds(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getUTCDate(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setUTCDate(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getUTCDay(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getUTCFullYear(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setUTCFullYear(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getUTCHours(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setUTCHours(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getUTCMilliseconds(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setUTCMilliseconds(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getUTCMinutes(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setUTCMinutes(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getUTCMonth(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setUTCMonth(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getUTCSeconds(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setUTCSeconds(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getTimezone(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef toTimezone(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef toLocalTimezone(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef toUTC(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef difference(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef equalsTo(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef earlierThan(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef laterThan(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef addDuration(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef toLocaleDateString(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef toLocaleTimeString(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef toLocaleString(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef toDateString(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef toTimeString(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef toString(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getTimezoneAbbreviation(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef secondsFromUTC(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef isDST(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getPreviousDSTTransition(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef getNextDSTTransition(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+};
+
+}
+}
+
+#endif // __TIZEN_JS_TZDATE_H_
diff --git a/src/TimeUtil/JSTimeDuration.cpp b/src/TimeUtil/JSTimeDuration.cpp
new file mode 100755 (executable)
index 0000000..d8dc507
--- /dev/null
@@ -0,0 +1,427 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <memory>
+#include <cmath>
+#include <JavaScriptCore/JavaScript.h>
+#include "JSTimeDuration.h"
+#include "TimeDuration.h"
+#include <ArgumentValidator.h>
+#include <Logger.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <PlatformException.h>
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+#include <CommonsJavaScript/Validator.h>
+#include <Commons/Exception.h>
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Time {
+
+struct TimeDurationHolder {
+    TimeDurationPtr ptr;
+};
+
+namespace {
+const char* CLASS_NAME = "TimeDuration";
+
+const char* TIMEDURATION_ATTRIBUTE_API_LENGTH = "length";
+const char* TIMEDURATION_ATTRIBUTE_API_UNIT = "unit";
+
+const char* TIMEDURATION_FUNCTION_API_DIFFERENCE = "difference";
+const char* TIMEDURATION_FUNCTION_API_EQUALS_TO = "equalsTo";
+const char* TIMEDURATION_FUNCTION_API_LESS_THAN = "lessThan";
+const char* TIMEDURATION_FUNCTION_API_GREATER_THAN = "greaterThan";
+}
+
+JSClassDefinition JSTimeDuration::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CLASS_NAME,
+        0,
+        JSTimeDuration::m_property,
+        JSTimeDuration::m_function,
+        JSTimeDuration::initialize,
+        JSTimeDuration::finalize,
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL,
+        NULL, //ConvertToType
+};
+
+JSStaticValue JSTimeDuration::m_property[] = {
+        { TIMEDURATION_ATTRIBUTE_API_LENGTH, getLength, setLength,
+                kJSPropertyAttributeDontDelete },
+        { TIMEDURATION_ATTRIBUTE_API_UNIT, getUnit, setUnit,
+                kJSPropertyAttributeDontDelete },
+        { 0, 0, 0, 0 }
+};
+
+JSStaticFunction JSTimeDuration::m_function[] = {
+        {TIMEDURATION_FUNCTION_API_DIFFERENCE, difference, kJSPropertyAttributeNone },
+        {TIMEDURATION_FUNCTION_API_EQUALS_TO, equalsTo, kJSPropertyAttributeNone },
+        {TIMEDURATION_FUNCTION_API_LESS_THAN, lessThan, kJSPropertyAttributeNone },
+        {TIMEDURATION_FUNCTION_API_GREATER_THAN, greaterThan, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSTimeDuration::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSTimeDuration::m_jsClassRef = JSClassCreate(JSTimeDuration::getClassInfo());
+
+const JSClassRef JSTimeDuration::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSTimeDuration::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered initialize");
+}
+
+void JSTimeDuration::finalize(JSObjectRef object)
+{
+    LOGD("Entered finalize");
+    TimeDurationHolder *priv = static_cast<TimeDurationHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+    }
+}
+
+TimeDurationPtr JSTimeDuration::getPrivateObject(JSContextRef context, JSValueRef value) {
+    LOGD("Entered");
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    TimeDurationHolder* priv = static_cast<TimeDurationHolder*>(JSObjectGetPrivate(object));
+    if (!priv or !priv->ptr) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSTimeDuration::setPrivateObject(JSObjectRef object, TimeDurationPtr native) {
+    LOGD("Entered");
+    TimeDurationHolder* priv = static_cast<TimeDurationHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSTimeDuration::makeJSObject(JSContextRef context, TimeDurationPtr native) {
+    LOGD("Entered");
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    TimeDurationHolder* priv = new(std::nothrow) TimeDurationHolder();
+    if (!priv) {
+        LOGE("Memory allocation for priv failed");
+        throw UnknownException("Memory allocation for priv failed");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+JSValueRef JSTimeDuration::getLength(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered getLength()");
+    try {
+        TimeDurationPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getLength());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to get time duration length. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+JSValueRef JSTimeDuration::getUnit(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        TimeDurationPtr priv = getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getUnit());
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to get time duration unit. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSTimeDuration::setLength(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered setLength()");
+    try {
+        TimeDurationPtr priv = getPrivateObject(context, object);
+        long long val = JSUtil::JSValueToLongLong(context, value);
+        priv->setLength(val);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to set time duration length. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    return true;
+}
+
+bool JSTimeDuration::setUnit(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        TimeDurationPtr priv = getPrivateObject(context, object);
+        if (!JSValueIsNull(context, value)) {
+            std::string unit = JSUtil::JSValueToString(context, value);
+            if (unit != MSECS && unit != SECS && unit != MINS &&
+                    unit != HOURS && unit != DAYS) {
+                LOGE("Invalid unit");
+                throw TypeMismatchException("Invalid unit");
+            }
+            priv->setUnit(unit);
+        }
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("Failed to set time duration unit. %s : %s", err.getName().c_str(),
+                err.getMessage().c_str());
+    }
+    return true;
+}
+
+JSObjectRef JSTimeDuration::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered constructor()");
+    ArgumentValidator validator(context, argumentCount, arguments);
+    JSObjectRef obj = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef ctorName = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, obj, ctorName, constructor, kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(ctorName);
+
+    try {
+        TimeDurationPtr priv = TimeDurationPtr(new (std::nothrow) TimeDuration());
+        if (!priv) {
+            LOGW("Failed to create TimeDurationPtr object.");
+            throw UnknownException("Failed to create TimeDurationPtr object.");
+        }
+        priv->setLength(validator.toLongLong(0, false, 0));
+        priv->setUnit(validator.toString(1, true, MSECS));
+
+        TimeDurationHolder *holder = new (std::nothrow) TimeDurationHolder();
+        if (!holder) {
+            LOGW("Failed to create TimeDurationHolder object.");
+            throw UnknownException("Failed to create TimeDurationHolder object.");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(obj, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("%s : %s", error.getName().c_str(), error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("An error occured");
+    }
+    return obj;
+}
+
+JSValueRef JSTimeDuration::difference(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered difference()");
+
+    TimeDurationPtr diff;
+    try {
+        TimeDurationPtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        // TimeDuration other
+        JSObjectRef otherObj = validator.toObject(0, JSTimeDuration::getClassRef());
+        TimeDurationPtr other = getPrivateObject(context, otherObj);
+
+        return JSTimeDuration::makeJSObject(context,priv->difference(other));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException err("Unknown Error in tizen."
+                "TimeDuration.difference().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeDuration::equalsTo(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered equalsTo()");
+
+    try {
+        TimeDurationPtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        // TimeDuration other
+        JSObjectRef otherObj = validator.toObject(0, JSTimeDuration::getClassRef());
+        TimeDurationPtr other = getPrivateObject(context, otherObj);
+
+        return JSUtil::toJSValueRef(context, priv->equalsTo(other));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException err("Unknown Error in tizen.download.start().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeDuration::lessThan(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered lessThan()");
+
+    try {
+        TimeDurationPtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        // TimeDuration other
+        JSObjectRef otherObj = validator.toObject(0, JSTimeDuration::getClassRef());
+        TimeDurationPtr other = getPrivateObject(context, otherObj);
+
+        return JSUtil::toJSValueRef(context, priv->lessThan(other));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException err("Unknown Error in tizen.download.start().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeDuration::greaterThan(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered greaterThan()");
+
+    try {
+        TimeDurationPtr priv = getPrivateObject(context, thisObject);
+        ArgumentValidator validator(context, argumentCount, arguments);
+        // TimeDuration other
+        JSObjectRef otherObj = validator.toObject(0, JSTimeDuration::getClassRef());
+        TimeDurationPtr other = getPrivateObject(context, otherObj);
+
+        return JSUtil::toJSValueRef(context, priv->greaterThan(other));
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException err("Unknown Error in tizen.download.start().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+JSObjectRef JSTimeDuration::createJSObject(JSContextRef context,
+        const DurationProperties &durations)
+{
+    DurationPropertiesPtr durationProps(new DurationProperties(durations));
+    TimeDurationPrivObject *priv = new TimeDurationPrivObject(context, durationProps);
+
+    if (!priv) {
+        ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Can not new an object");
+    }
+    return JSObjectMake(context, getClassRef(), priv);
+}
+
+JSObjectRef JSTimeDuration::createJSObject(JSContextRef context,
+        const DurationPropertiesPtr duration)
+{
+    TimeDurationPrivObject *priv = new TimeDurationPrivObject(context, duration);
+    if (!priv) {
+        ThrowMsg(WrtDeviceApis::Commons::NullPointerException, "Private object is null.");
+    }
+    return JSObjectMake(context, getClassRef(), priv);
+}
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+} //Time
+} //DeviceAPI
diff --git a/src/TimeUtil/JSTimeDuration.h b/src/TimeUtil/JSTimeDuration.h
new file mode 100755 (executable)
index 0000000..0ad853f
--- /dev/null
@@ -0,0 +1,167 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_TIMEDURATION_H_
+#define __TIZEN_JS_TIMEDURATION_H_
+
+#include "TimeDuration.h"
+#include <PlatformException.h>
+#include <Logger.h>
+#include <JSUtil.h>
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+#include <CommonsJavaScript/PrivateObject.h>
+#include "DurationProperties.h"
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+namespace DeviceAPI {
+namespace Time {
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObjectT<
+             DurationPropertiesPtr>::
+    Type TimeDurationPrivObject;
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+/**
+ * @class JSTimeDuration
+ * @brief This class is javascript extension
+ *
+ */
+class JSTimeDuration {
+public:
+    /**
+     * Gets object's class description.
+     */
+    static const JSClassDefinition* getClassInfo();
+
+    /**
+     * Gets class definition reference.
+     * @remarks New instance of JSClassRef is created (only once) if none was
+     * @remarks set before.
+     * @return Class reference.
+     */
+    static const JSClassRef getClassRef();
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static TimeDurationPtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, TimeDurationPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, TimeDurationPtr native);
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+    static JSObjectRef createJSObject(JSContextRef context, const DurationProperties &durations);
+    static JSObjectRef createJSObject(JSContextRef context, const DurationPropertiesPtr duration);
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+private:
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static properties
+     * of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    /**
+     * Getters for properties
+     */
+    static JSValueRef getLength(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static JSValueRef getUnit(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setLength(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static bool setUnit(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    /**
+     * Functions declaration for the JSTimeDuration interface.
+     */
+    static JSValueRef difference(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef equalsTo(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef lessThan(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef greaterThan(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+};
+
+}
+}
+
+#endif // __TIZEN_JS_TIMEDURATION_H_
diff --git a/src/TimeUtil/JSTimeUtil.cpp b/src/TimeUtil/JSTimeUtil.cpp
new file mode 100755 (executable)
index 0000000..ddc753f
--- /dev/null
@@ -0,0 +1,454 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <string>
+#include <ctime>
+
+#include "JSTimeUtil.h"
+#include "TimeUtil.h"
+#include "JSTZDate.h"
+#include "ArgumentValidator.h"
+#include <Logger.h>
+#include <PlatformException.h>
+#include <JSUtil.h>
+#include <JSWebAPIErrorFactory.h>
+#include <SecurityExceptions.h>
+#include <JSWebAPIError.h>
+#include <GlobalContextManager.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Time {
+
+namespace {
+const char* CLASS_NAME = "TimeUtil";
+
+const char* TIMEUTIL_FUNCTION_API_GET_CURRENT_DATE_TIME = "getCurrentDateTime";
+const char* TIMEUTIL_FUNCTION_API_GET_LOCAL_TIMEZONE = "getLocalTimezone";
+const char* TIMEUTIL_FUNCTION_API_GET_AVAILABLE_TIMEZONES = "getAvailableTimezones";
+const char* TIMEUTIL_FUNCTION_API_GET_DATE_FORMAT = "getDateFormat";
+const char* TIMEUTIL_FUNCTION_API_GET_TIME_FORMAT = "getTimeFormat";
+const char* TIMEUTIL_FUNCTION_API_IS_LEAP_YEAR = "isLeapYear";
+const char* TIMEUTIL_FUNCTION_API_SET_DATE_TIME_CHANGE_LISTENER = "setDateTimeChangeListener";
+const char* TIMEUTIL_FUNCTION_API_UNSET_DATE_TIME_CHANGE_LISTENER = "unsetDateTimeChangeListener";
+const char* TIMEUTIL_FUNCTION_API_SET_TIME_ZONE_CHANGE_LISTENER = "setTimezoneChangeListener";
+const char* TIMEUTIL_FUNCTION_API_UNSET_TIME_ZONE_CHANGE_LISTENER = "unsetTimezoneChangeListener";
+}
+
+JSClassDefinition JSTimeUtil::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        CLASS_NAME,
+        0,
+        NULL,
+        m_function,
+        initialize,
+        finalize,
+        NULL, //HasProperty,
+        NULL, //GetProperty,
+        NULL, //SetProperty,
+        NULL, //DeleteProperty,
+        NULL, //GetPropertyNames,
+        NULL, //CallAsFunction,
+        NULL, //CallAsConstructor,
+        NULL, //hasInstance
+        NULL, //ConvertToType
+};
+
+JSStaticFunction JSTimeUtil::m_function[] = {
+        {TIMEUTIL_FUNCTION_API_GET_CURRENT_DATE_TIME, JSTimeUtil::getCurrentDateTime, kJSPropertyAttributeNone },
+        {TIMEUTIL_FUNCTION_API_GET_LOCAL_TIMEZONE, JSTimeUtil::getLocalTimezone, kJSPropertyAttributeNone },
+        {TIMEUTIL_FUNCTION_API_GET_AVAILABLE_TIMEZONES, JSTimeUtil::getAvailableTimezones, kJSPropertyAttributeNone },
+        {TIMEUTIL_FUNCTION_API_GET_DATE_FORMAT, JSTimeUtil::getDateFormat, kJSPropertyAttributeNone },
+        {TIMEUTIL_FUNCTION_API_GET_TIME_FORMAT, JSTimeUtil::getTimeFormat, kJSPropertyAttributeNone },
+        {TIMEUTIL_FUNCTION_API_IS_LEAP_YEAR, JSTimeUtil::isLeapYear, kJSPropertyAttributeNone },
+        {TIMEUTIL_FUNCTION_API_SET_DATE_TIME_CHANGE_LISTENER, JSTimeUtil::setDateTimeChangeListener, kJSPropertyAttributeNone },
+        {TIMEUTIL_FUNCTION_API_UNSET_DATE_TIME_CHANGE_LISTENER, JSTimeUtil::unsetDateTimeChangeListener, kJSPropertyAttributeNone },
+        {TIMEUTIL_FUNCTION_API_SET_TIME_ZONE_CHANGE_LISTENER, JSTimeUtil::setTimeZoneChangeListener, kJSPropertyAttributeNone },
+        {TIMEUTIL_FUNCTION_API_UNSET_TIME_ZONE_CHANGE_LISTENER, JSTimeUtil::unsetTimeZoneChangeListener, kJSPropertyAttributeNone },
+        { 0, 0, 0 }
+};
+
+const JSClassDefinition* JSTimeUtil::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSTimeUtil::m_jsClassRef = JSClassCreate(JSTimeUtil::getClassInfo());
+
+const JSClassRef JSTimeUtil::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSTimeUtil::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("TimeUtil::initialize ");
+    TimeUtil* priv = static_cast<TimeUtil*>(JSObjectGetPrivate(object));
+
+        if (priv != NULL) {
+            LOGD("TimeUtil::initialize already");
+            return;
+        }
+
+        priv = new (std::nothrow) TimeUtil();
+        if (!priv) {
+            LOGE("TimeUtil creation failed");
+            return;
+        }
+
+        if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+            LOGE("Object can't store private data.");
+            delete priv;
+            priv = NULL;
+        }
+        return;
+}
+
+TimeUtil *JSTimeUtil::getPrivateObject(JSContextRef context, JSObjectRef thisObject)
+{
+    if (!JSValueIsObjectOfClass(context, thisObject, getClassRef())) {
+        LOGE("Type mismatch");
+        throw Common::TypeMismatchException("Type mismatch");
+    }
+
+    TimeUtil* priv = static_cast<TimeUtil*>(JSObjectGetPrivate(thisObject));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw Common::UnknownException("Priv is null");
+    }
+
+    return priv;
+}
+
+void JSTimeUtil::finalize(JSObjectRef object)
+{
+    TimeUtil* privateObject = static_cast<TimeUtil*>(JSObjectGetPrivate(object));
+        if (privateObject) {
+            JSObjectSetPrivate(object, NULL);
+            delete privateObject;
+        }
+}
+
+JSValueRef JSTimeUtil::getCurrentDateTime(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered getCurrentDateTime()");
+
+    try {
+        TZDatePtr diff = TZDatePtr(new (std::nothrow) TZDate());
+        if (!diff) {
+            LOGE("Object is NULL.");
+            throw UnknownException("Object is NULL.");
+        }
+        return JSTZDate::makeJSObject(context, diff);;
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TimeDuration.difference().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeUtil::getLocalTimezone(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered getLocalTimezone()");
+
+    try {
+
+        TimeUtil *priv = JSTimeUtil::getPrivateObject(context, thisObject);
+
+        std::string localTimezone = priv->getLocalTimezone();
+        return JSUtil::toJSValueRef(context, localTimezone);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TimeDuration.difference().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeUtil::getAvailableTimezones(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered getAvailableTimezones()");
+
+    try {
+        TimeUtil *priv = JSTimeUtil::getPrivateObject(context, thisObject);
+
+        std::vector<std::string> vec = priv->getAvailableTimezones();
+        return JSUtil::toJSValueRef(context, vec);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TimeDuration.difference().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeUtil::getDateFormat(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered getDateFormat()");
+
+    try {
+        TimeUtil *priv = JSTimeUtil::getPrivateObject(context, thisObject);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+
+        bool shortformat = validator.toBool(0, true);
+
+        std::string date = priv->getDateFormat(shortformat);
+        return JSUtil::toJSValueRef(context, date);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return Common::JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException err("Unknown Error in tizen.TimeUtil.getTimeFormat().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return Common::JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeUtil::getTimeFormat(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered getTimeFormat()");
+
+    try {
+        TimeUtil *priv = JSTimeUtil::getPrivateObject(context, thisObject);
+
+        std::string time = priv->getTimeFormat();
+        return JSUtil::toJSValueRef(context, time);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return Common::JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException err("Unknown Error in tizen.TimeUtil.getTimeFormat().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return Common::JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeUtil::isLeapYear(JSContextRef context,
+        JSObjectRef function,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef * exception)
+{
+    LOGD("Entered isLeapYear()");
+
+    try {
+        ArgumentValidator validator(context, argumentCount, arguments);
+        long year = validator.toLong(0);
+
+        if (year % 4 != 0)
+            return JSUtil::toJSValueRef(context, false);
+        if (year % 400 == 0)
+            return JSUtil::toJSValueRef(context, true);
+        if (year % 100 == 0)
+            return JSUtil::toJSValueRef(context, false);
+
+        return JSUtil::toJSValueRef(context, true);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TimeUtil.isLeapYear().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeUtil::setDateTimeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered setDateTimeChangeListener()");
+
+    try {
+        TimeUtil *priv = JSTimeUtil::getPrivateObject(context, thisObject);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        MultiCallbackUserData* callback = new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        // successCallback
+        JSObjectRef callbackObj = validator.toFunction(0, false);
+        if (callbackObj)
+        {
+            callback->setCallback("onsuccess", callbackObj);
+        }
+
+        priv->setDateTimeChangeListener(callback);
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TimeUtil.setTimeZoneChangeListener().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeUtil::unsetDateTimeChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered unsetDateTimeChangeListener()");
+
+    try {
+        TimeUtil *priv = JSTimeUtil::getPrivateObject(context, thisObject);
+
+        priv->unsetDateTimeChangeListener();
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TimeUtil.setTimeZoneChangeListener().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeUtil::setTimeZoneChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered setTimeZoneChangeListener()");
+
+    try {
+        TimeUtil *priv = JSTimeUtil::getPrivateObject(context, thisObject);
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        MultiCallbackUserData* callback = new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        // successCallback
+        JSObjectRef callbackObj = validator.toFunction(0, false);
+        if (callbackObj)
+        {
+            callback->setCallback("onsuccess", callbackObj);
+        }
+
+        priv->setTimeZoneChangeListener(callback);
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TimeUtil.setTimeZoneChangeListener().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSTimeUtil::unsetTimeZoneChangeListener(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered unsetTimeZoneChangeListener()");
+
+    try {
+        TimeUtil *priv = JSTimeUtil::getPrivateObject(context, thisObject);
+
+        priv->unsetTimeZoneChangeListener();
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err) {
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...) {
+        UnknownException
+            err("Unknown Error in tizen.TimeUtil.setTimeZoneChangeListener().");
+        LOGE("%s : %s", err.getName().c_str(), err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+} //TimeUtil
+} //DeviceAPI
diff --git a/src/TimeUtil/JSTimeUtil.h b/src/TimeUtil/JSTimeUtil.h
new file mode 100755 (executable)
index 0000000..3c59207
--- /dev/null
@@ -0,0 +1,153 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_TIMEUTIL_H_
+#define __TIZEN_JS_TIMEUTIL_H_
+
+#include <JavaScriptCore/JavaScript.h>
+#include "TimeUtil.h"
+
+namespace DeviceAPI {
+namespace Time {
+
+/**
+ * @class JSTimeUtil
+ * @brief This class is javascript extension
+ *
+ */
+class JSTimeUtil {
+public:
+    /**
+     * Gets object's class description.
+     */
+    static const JSClassDefinition* getClassInfo();
+
+    /**
+     * Gets class definition reference.
+     * @remarks New instance of JSClassRef is created (only once) if none was
+     * @remarks set before.
+     * @return Class reference.
+     */
+    static const JSClassRef getClassRef();
+
+    static TimeUtil *getPrivateObject(JSContextRef context, JSObjectRef thisObject);
+
+private:
+    /**
+     * This structure contains properties and callbacks that define a type of object.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSObjectRef createJSObject(JSContextRef context,
+            void *priv);
+
+    /**
+     * Functions declaration for the JSTimeDuration interface.
+     */
+    static JSValueRef getCurrentDateTime(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+
+            JSValueRef* exception);
+
+    static JSValueRef getLocalTimezone(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getAvailableTimezones(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getDateFormat(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef getTimeFormat(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef isLeapYear(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setDateTimeChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetDateTimeChangeListener(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+
+    static JSValueRef setTimeZoneChangeListener(JSContextRef context,
+            JSObjectRef object,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+    static JSValueRef unsetTimeZoneChangeListener(JSContextRef context,
+            JSObjectRef function,
+            JSObjectRef thisObject,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef * exception);
+};
+
+}
+}
+
+#endif // __TIZEN_JS_TIMEUTIL_H_
diff --git a/src/TimeUtil/TZDate.cpp b/src/TimeUtil/TZDate.cpp
new file mode 100755 (executable)
index 0000000..7768a4b
--- /dev/null
@@ -0,0 +1,1046 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        TZDate.cpp
+ */
+
+#include "TZDate.h"
+#include "TimeUtilTools.h"
+#include <unicode/unistr.h>
+#include <unicode/timezone.h>
+#include <unicode/calendar.h>
+#include <unicode/ucal.h>
+#include <unicode/vtzone.h>
+#include <unicode/smpdtfmt.h>
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+#include <Commons/Exception.h>
+
+using namespace WrtDeviceApis;
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+namespace DeviceAPI {
+namespace Time {
+
+TZDate::TZDate()
+{
+    UErrorCode ec = U_ZERO_ERROR;
+    TimeUtilTools util;
+    m_calendar = Calendar::createInstance(ec);
+
+    if (U_SUCCESS(ec)) {
+        LOGD("Calendar created successfully");
+    } else {
+        LOGE("Failed to create calendar: %d, %s", ec, u_errorName(ec));
+    }
+}
+
+TZDate::TZDate(time_t datetime, std::string timezone)
+{
+    UErrorCode ec = U_ZERO_ERROR;
+    long local_offset = 0;
+    std::string local_timezone = TimeUtilTools::getLocalTimeZone();
+    UnicodeString* usTimezone = TimeUtilTools::toUnicodeString(local_timezone);
+    TimeZone* tz = TimeZone::createTimeZone(*usTimezone);
+    delete usTimezone;
+    local_offset = tz->getRawOffset();
+    if (timezone.empty() || !TimeUtilTools::isInTimezonesArray(timezone)) {
+        timezone = TimeUtilTools::getLocalTimeZone();
+    }
+
+    usTimezone = TimeUtilTools::toUnicodeString(timezone);
+    tz = TimeZone::createTimeZone(*usTimezone);
+    delete usTimezone;
+
+    if (!datetime) {
+        datetime = time(NULL);
+    }
+    datetime += local_offset / 1000;
+    timeval tp;
+    gettimeofday(&tp, NULL);
+    struct tm *date = gmtime(&datetime);
+    m_calendar = Calendar::createInstance(*tz, ec);
+
+    if (U_SUCCESS(ec)) {
+        m_calendar->set(TimeUtilTools::toint32_t(date->tm_year + 1900),
+                TimeUtilTools::toint32_t(date->tm_mon),
+                TimeUtilTools::toint32_t(date->tm_mday), TimeUtilTools::toint32_t(date->tm_hour),
+                TimeUtilTools::toint32_t(date->tm_min), TimeUtilTools::toint32_t(date->tm_sec));
+        m_calendar->set(UCAL_MILLISECOND, TimeUtilTools::toint32_t(tp.tv_usec / 1000));
+    }
+    else {
+        m_calendar = NULL;
+        LOGE("Calendar doesn't created: %d, %s", ec, u_errorName(ec));
+    }
+
+}
+
+TZDate::TZDate(long year,
+        long month,
+        long day,
+        long hours,
+        long minutes,
+        long seconds,
+        long milliseconds,
+        std::string timezone)
+{
+    UErrorCode ec = U_ZERO_ERROR;
+    if (timezone.empty() || !TimeUtilTools::isInTimezonesArray(timezone)) {
+        timezone = TimeUtilTools::getLocalTimeZone();
+    }
+    std::shared_ptr<UnicodeString> usTimezone(TimeUtilTools::toUnicodeString(timezone));
+    TimeZone* tz = TimeZone::createTimeZone(*usTimezone);
+    m_calendar = Calendar::createInstance(*tz, ec);
+
+    if (U_SUCCESS(ec)) {
+        m_calendar->set(TimeUtilTools::toint32_t(year), TimeUtilTools::toint32_t(month),
+                TimeUtilTools::toint32_t(day), TimeUtilTools::toint32_t(hours),
+                TimeUtilTools::toint32_t(minutes), TimeUtilTools::toint32_t(seconds));
+        m_calendar->set(UCAL_MILLISECOND, TimeUtilTools::toint32_t(milliseconds));
+    }
+    else {
+        m_calendar = NULL;
+        LOGE("Calendar doesn't created: %d, %s", ec, u_errorName(ec));
+    }
+}
+
+TZDate::TZDate(const TZDate& tzdate) {
+    m_calendar = tzdate.m_calendar->clone();
+}
+
+TZDate::TZDate(Calendar* cal) {
+    m_calendar = cal;
+}
+
+TZDate& TZDate::operator =( const TZDate& tzdate)
+{
+    if (this != &tzdate) {
+        delete m_calendar;
+        m_calendar = tzdate.m_calendar->clone();
+    }
+    return *this;
+}
+
+TZDate::~TZDate()
+{
+    if (m_calendar) {
+        delete m_calendar;
+        m_calendar = NULL;
+    }
+
+}
+
+long TZDate::getDate() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    return TimeUtilTools::tolong(m_calendar->get(UCAL_DATE, ec));
+}
+
+void TZDate::setDate(long date) {
+    m_calendar->set(UCAL_DATE, TimeUtilTools::toint32_t(date));
+}
+
+long TZDate::getDay() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    return TimeUtilTools::tolong(m_calendar->get(UCAL_DAY_OF_WEEK, ec)) - 1; // -1 because enums values begins from 1
+}
+
+long TZDate::getFullYear() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    return TimeUtilTools::tolong(m_calendar->get(UCAL_YEAR, ec));
+}
+
+void TZDate::setFullYear(long year) {
+    if (year <= 0) {
+        year = 1;
+    }
+    m_calendar->set(UCAL_YEAR, TimeUtilTools::toint32_t(year));
+}
+
+long TZDate::getHours() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    return TimeUtilTools::tolong(m_calendar->get(UCAL_HOUR_OF_DAY, ec));
+}
+
+void TZDate::setHours(long hours) {
+    m_calendar->set(UCAL_HOUR_OF_DAY, TimeUtilTools::toint32_t(hours));
+}
+
+long TZDate::getMilliseconds() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    return TimeUtilTools::tolong(m_calendar->get(UCAL_MILLISECOND, ec));
+}
+
+void TZDate::setMilliseconds(long ms) {
+    m_calendar->set(UCAL_MILLISECOND, TimeUtilTools::toint32_t(ms));
+}
+
+long TZDate::getMinutes() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    return TimeUtilTools::tolong(m_calendar->get(UCAL_MINUTE, ec));
+}
+
+void TZDate::setMinutes(long minutes) {
+    m_calendar->set(UCAL_MINUTE, TimeUtilTools::toint32_t(minutes));
+}
+
+long TZDate::getMonth() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    return TimeUtilTools::tolong(m_calendar->get(UCAL_MONTH, ec));
+}
+
+void TZDate::setMonth(long month) {
+    m_calendar->set(UCAL_MONTH, TimeUtilTools::toint32_t(month));
+}
+
+long TZDate::getSeconds() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    return m_calendar->get(UCAL_SECOND, ec);
+}
+
+void TZDate::setSeconds(long seconds) {
+    m_calendar->set(UCAL_SECOND, TimeUtilTools::toint32_t(seconds));
+}
+
+long TZDate::getUTCDate() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    Calendar* cal = getUTCCalendar();
+    int32_t value = cal->get(UCAL_DATE, ec);
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't get date from cal: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't get date from cal");
+    }
+
+    delete cal;
+    cal = NULL;
+
+    return TimeUtilTools::tolong(value);
+}
+
+void TZDate::setUTCDate(long date) {
+    long val = getUTCDate();
+    setDate(getDate() + date - val);
+}
+
+long TZDate::getUTCDay() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    Calendar* cal = getUTCCalendar();
+    int32_t value = cal->get(UCAL_DAY_OF_WEEK, ec);
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't get day from cal: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't get day from cal");
+    }
+
+    delete cal;
+    cal = NULL;
+
+    return TimeUtilTools::tolong(value-1); // -1 because enums values begins from 1
+}
+
+long TZDate::getUTCFullYear() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    Calendar* cal = getUTCCalendar();
+    int32_t value = cal->get(UCAL_YEAR, ec);
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't get year from cal: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't get year from cal");
+    }
+
+    delete cal;
+    cal = NULL;
+
+    return TimeUtilTools::tolong(value);
+}
+
+void TZDate::setUTCFullYear(long year) {
+    long val = getUTCFullYear();
+    setFullYear(getFullYear() + year - val);
+}
+
+long TZDate::getUTCHours() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    Calendar* cal = getUTCCalendar();
+    int32_t value = cal->get(UCAL_HOUR_OF_DAY, ec);
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't get hours from cal: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't get hours from cal");
+    }
+
+    delete cal;
+    cal = NULL;
+
+    return TimeUtilTools::tolong(value);
+}
+
+void TZDate::setUTCHours(long hours) {
+    long val = getUTCHours();
+    setHours(getHours() + hours - val);
+}
+
+long TZDate::getUTCMilliseconds() const {
+    return getMilliseconds();
+}
+
+void TZDate::setUTCMilliseconds(long ms) {
+    setMilliseconds(ms);
+}
+
+long TZDate::getUTCMinutes() const {
+    return getMinutes();
+}
+
+void TZDate::setUTCMinutes(long minutes) {
+    setMinutes(minutes);
+}
+
+long TZDate::getUTCMonth() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    Calendar* cal = getUTCCalendar();
+    int32_t value = cal->get(UCAL_MONTH, ec);
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't get month from cal: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't get month from cal");
+    }
+
+    delete cal;
+    cal = NULL;
+
+    return TimeUtilTools::tolong(value);
+}
+
+void TZDate::setUTCMonth(long month) {
+    long val = getUTCMonth();
+    setMonth(getMonth() + month - val);
+}
+
+long TZDate::getUTCSeconds() const {
+    return getSeconds();
+}
+
+void TZDate::setUTCSeconds(long seconds) {
+    setSeconds(seconds);
+}
+
+std::string TZDate::getTimezone() const {
+    UnicodeString id;
+
+    m_calendar->getTimeZone().getID(id);
+    return TimeUtilTools::toUTF8String(id);
+}
+
+TZDatePtr TZDate::toTimezone(const std::string& tzid) const {
+    TZDatePtr newObj;
+    if (TimeUtilTools::isInTimezonesArray(tzid)) {
+        newObj = TZDatePtr(new (std::nothrow) TZDate(getCalendar(tzid)));
+        if (!newObj) {
+            LOGE("Object not created");
+            throw Common::UnknownException("Object not created");
+        }
+    } else {
+        LOGE("Invalid timezone");
+        throw Common::InvalidValuesException("Invalid timezone");
+    }
+    return newObj;
+}
+
+TZDatePtr TZDate::toLocalTimezone() const {
+    std::string localTimezone = TimeUtilTools::getLocalTimeZone();
+    return toTimezone(localTimezone);
+}
+
+TZDatePtr TZDate::toUTC() const {
+    TZDatePtr newObj = TZDatePtr(new (std::nothrow) TZDate(getUTCCalendar()));
+    if (!newObj) {
+        LOGE("Object not created");
+        throw Common::UnknownException("Object not created");
+    }
+    return newObj;
+}
+
+TimeDurationPtr TZDate::difference(TZDatePtr other) const {
+    TimeDurationPtr dur = TimeDurationPtr(new (std::nothrow) TimeDuration());
+    UDate thisTime, otherTime, diffTime;
+    long long len = 0;
+    UErrorCode ec = U_ZERO_ERROR;
+    TZDatePtr newObj = other;
+
+    diffTime = m_calendar->getTime(ec) - newObj->m_calendar->getTime(ec);
+
+    if (fabs(diffTime) > LLONG_MAX) {
+        LOGE("limit value reached");
+        throw Common::UnknownException("limit value reached");
+    }
+    len = static_cast<long long>(diffTime);
+
+    if (len % TIME_DAYS_UNIT == 0) {
+        len = len / TIME_DAYS_UNIT;
+        dur->setUnit(DAYS);
+    }
+    dur->setLength(len);
+
+    return dur;
+}
+
+bool TZDate::equalsTo(TZDatePtr other) const {
+    TimeDurationPtr dur = difference(other);
+    return !dur->getLength();
+}
+
+bool TZDate::earlierThan(TZDatePtr other) const {
+    TimeDurationPtr dur = difference(other);
+    return dur->getLength() < 0;
+}
+
+bool TZDate::laterThan(TZDatePtr other) const {
+    TimeDurationPtr dur = difference(other);
+    return dur->getLength() > 0;
+}
+
+TZDatePtr TZDate::addDuration(TimeDurationPtr duration) const {
+    TZDatePtr newObj = TZDatePtr(new (std::nothrow) TZDate());
+    TimeDuration::findTheBiggestPossibleUnit(duration);
+    long long len = duration->getLength();
+    std::string unit = duration->getUnit();
+
+    UErrorCode ec = U_ZERO_ERROR;
+    newObj->m_calendar = m_calendar->clone();
+
+    if (MSECS == unit) {
+        newObj->m_calendar->add(UCAL_MILLISECOND,
+                TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
+    } else if (SECS == unit) {
+        newObj->m_calendar->add(UCAL_SECOND,
+                TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
+    } else if (MINS == unit) {
+        newObj->m_calendar->add(UCAL_MINUTE,
+                TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
+    } else if (HOURS == unit) {
+        newObj->m_calendar->add(UCAL_HOUR_OF_DAY,
+                TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
+    } else if (DAYS == unit) {
+        newObj->m_calendar->add(UCAL_DATE,
+                TimeUtilTools::toint32_t(static_cast<long>(len)), ec);
+    }
+    return newObj;
+}
+
+std::string TZDate::toLocaleDateString() const {
+    return toString(true, TimeUtilTools::DATE_FORMAT);
+}
+
+std::string TZDate::toLocaleTimeString() const {
+    return toString(true, TimeUtilTools::TIME_FORMAT);
+}
+
+std::string TZDate::toLocaleString() const {
+    return toString(true);
+}
+
+std::string TZDate::toDateString() const {
+    return toString(false, TimeUtilTools::DATE_FORMAT);
+}
+
+std::string TZDate::toTimeString() const {
+    return toString(false, TimeUtilTools::TIME_FORMAT);
+}
+
+std::string TZDate::toString(bool bLocale,
+        TimeUtilTools::DateTimeFormatType type) const {
+    UErrorCode ec = U_ZERO_ERROR;
+    UnicodeString str;
+
+    Locale* defaultLocale = TimeUtilTools::getDefaultLocale();
+    DateFormat* fmt = new SimpleDateFormat(TimeUtilTools::getDateTimeFormat(type, bLocale),
+            ((bLocale && defaultLocale != NULL) ? *defaultLocale : Locale::getEnglish()), ec);
+    if (U_SUCCESS(ec)) {
+        fmt->setCalendar(*m_calendar);
+        fmt->format(m_calendar->getTime(ec), str);
+        delete fmt;
+        fmt = NULL;
+        if (U_SUCCESS(ec)) {
+            std::string result = TimeUtilTools::toUTF8String(str);
+            str.remove();
+            return result;
+        } else {
+            LOGE("Failed to get time: %d, %s", ec, u_errorName(ec));
+        }
+
+    }
+    LOGE("can't make SimpleDateFormat or can't get time: %d, %s", ec, u_errorName(ec));
+    throw Common::UnknownException("can't make SimpleDateFormat or can't get time");
+}
+
+std::string TZDate::getTimezoneAbbreviation() const {
+    LOGD("entered");
+    if (m_calendar == NULL) {
+         throw Common::UnknownException("can't make SimpleDateFormat or can't get time");
+    }
+
+    UnicodeString str;
+
+    m_calendar->getTimeZone().getDisplayName(isDST(), TimeZone::SHORT, Locale::getEnglish(), str);
+    if ((str != "GMT") && (str.length() > 3) && !str.compare(0, 3, "GMT")) {
+        m_calendar->getTimeZone().getDisplayName(isDST(), TimeZone::LONG_GMT, Locale::getEnglish(), str);
+    }
+    std::string result = TimeUtilTools::toUTF8String(str);
+    str.remove();
+    LOGD ("%s", result.c_str());
+    return result;
+}
+
+long TZDate::secondsFromUTC() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    return (m_calendar->get(UCAL_ZONE_OFFSET, ec) + m_calendar->get(UCAL_DST_OFFSET, ec)) * (-1) / 1000;
+}
+
+bool TZDate::isDST() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    UBool result = m_calendar->inDaylightTime(ec);
+    return static_cast<bool>(result);
+}
+
+TZDatePtr TZDate::getPreviousDSTTransition() const {
+    return getDSTTransition(PREVDST);
+}
+
+TZDatePtr TZDate::getNextDSTTransition() const {
+    return getDSTTransition(NEXTDST);
+}
+
+TZDatePtr TZDate::getDSTTransition(DSTTransition tr_type) const
+{
+    UErrorCode ec = U_ZERO_ERROR;
+    UBool result = false;
+    UDate dstTransitionDate = m_calendar->getTime(ec);
+    if (U_SUCCESS(ec)) {
+        UnicodeString *id = TimeUtilTools::toUnicodeString(getTimezone());
+        VTimeZone *vtz = VTimeZone::createVTimeZoneByID(*id);
+        delete id;
+        id = NULL;
+
+        TimeZoneTransition tzTrans;
+        if (vtz->useDaylightTime()) {
+            if (NEXTDST == tr_type) {
+                result = vtz->getNextTransition(dstTransitionDate, FALSE, tzTrans);
+            }
+            else if (PREVDST == tr_type) {
+                result = vtz->getPreviousTransition(dstTransitionDate, FALSE, tzTrans);
+            }
+            else {
+                LOGD("invalid comparison value");
+                result = false;
+            }
+            if (result) {
+                dstTransitionDate = tzTrans.getTime();
+            }
+        }
+        delete vtz;
+        vtz = NULL;
+
+        TZDatePtr newObj = TZDatePtr(new (std::nothrow) TZDate(*this));
+        if (!result) {
+            return newObj;
+        }
+        newObj->m_calendar->setTime(dstTransitionDate, ec);
+        if (U_SUCCESS(ec)) {
+            return newObj;
+        } else {
+            LOGE("Failed to set time: %d, %s", ec, u_errorName(ec));
+        }
+    }
+    LOGE("can't getDSTTransition value from ICU: %d, %s", ec, u_errorName(ec));
+    throw Common::UnknownException("can't getDSTTransition value from ICU");
+}
+
+icu::Calendar* TZDate::getCalendar(const std::string& timezone) const {
+    UErrorCode ec = U_ZERO_ERROR;
+    std::shared_ptr<UnicodeString> usTimezone (TimeUtilTools::toUnicodeString(timezone));
+    icu::Calendar *cal = Calendar::createInstance(*(TimeZone::createTimeZone(*usTimezone)), ec);
+
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't create cal: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't create cal");
+    }
+    UDate date = m_calendar->getTime(ec);
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't get time of m_calendar: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't get time of m_calendar");
+    }
+    cal->setTime(date, ec);
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't get time of cal: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't get time of cal");
+    }
+    return cal;
+}
+
+icu::Calendar* TZDate::getUTCCalendar() const {
+    UErrorCode ec = U_ZERO_ERROR;
+    icu::Calendar *cal = Calendar::createInstance(*(TimeZone::getGMT()), ec);
+
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't create cal: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't create cal");
+    }
+    UDate date = m_calendar->getTime(ec);
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't get time of m_calendar: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't get time of m_calendar");
+    }
+    cal->setTime(date, ec);
+    if (!U_SUCCESS(ec)) {
+        LOGE("Can't get time of cal: %d, %s", ec, u_errorName(ec));
+        throw Common::UnknownException("Can't get time of cal");
+    }
+    return cal;
+}
+
+void TZDate::setTimezone(const std::string& timezone, bool timezone_is_certain) {
+    if (!timezone_is_certain) {
+        timezone_is_certain = TimeUtilTools::isInTimezonesArray(timezone);
+    }
+
+    if (timezone_is_certain) {
+        std::shared_ptr<UnicodeString> usTimezone(TimeUtilTools::toUnicodeString(timezone));
+        TimeZone* tz = TimeZone::createTimeZone(*usTimezone);
+        m_calendar->adoptTimeZone(tz);
+    }
+    else {
+        LOGD("Invalid timezone");
+    }
+}
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+TZDate::TZDate(const std::string &timezone)
+{
+    LOGD("entered");
+
+    UErrorCode ec = U_ZERO_ERROR;
+    TimeUtilTools util;
+    TimeZone *tz = util.makeTimeZone(timezone);
+    if (isAvailableTimezone(tz)) {
+        m_calendar= Calendar::createInstance(tz ,ec);
+    } else {
+        if (tz) {
+            delete tz;
+        }
+        m_calendar = Calendar::createInstance(ec);
+    }
+
+    if (U_SUCCESS(ec)) {
+        util.printDate(m_calendar);
+    } else {
+        LOGE("Failed to create calendar: %d, %s", ec, u_errorName(ec));
+        m_calendar = NULL;
+    }
+
+}
+
+TZDate::TZDate(const TZDateProperties &properties)
+{
+    LOGD("entered");
+
+    TimeUtilTools util;
+    m_calendar= _makeCalendar(properties);
+}
+
+TZDate::TZDate(const std::string &dateString, const double milliseconds, const std::string &timezone)
+{
+    m_calendar = NULL;
+
+    UErrorCode ec = U_ZERO_ERROR;
+    Calendar *dateCalender = Calendar::createInstance(ec);
+    DateFormat *df = NULL;
+    try {
+        if (dateCalender == NULL || U_FAILURE(ec)) {
+            ThrowMsg(Commons::UnknownException, "Can't make calendar");
+        }
+        df = new SimpleDateFormat("EEE MMM d uuuuuu HH:mm:ss", Locale::getEnglish(), ec);
+
+        if (df == NULL || U_FAILURE(ec)) {
+            ThrowMsg(Commons::UnknownException, "Can't make DateFormat");
+        }
+        ParsePosition pos;
+        pos.setIndex(0);
+        TimeUtilTools util;
+        UnicodeString text(dateString.c_str());
+        UDate date = df->parse(text, ec);
+
+        if (U_FAILURE(ec)) {
+            ThrowMsg(Commons::UnknownException, "parse fail");
+        }
+
+        dateCalender->setTime(date, ec);
+
+        if (U_FAILURE(ec)) {
+            ThrowMsg(Commons::UnknownException, "setTime fail");
+        }
+
+        util.printDate(dateCalender);
+        TZDateProperties properties;
+        properties.year = _get(TZDATE_YEAR, dateCalender);
+        properties.month = _get(TZDATE_MONTH, dateCalender);
+        properties.day = _get(TZDATE_DATE, dateCalender);
+        properties.hours = _get(TZDATE_HOUR_OF_DAY, dateCalender);
+        properties.minutes = _get(TZDATE_MINUTE, dateCalender);
+        properties.seconds = _get(TZDATE_SECOND, dateCalender);
+        properties.milliseconds = milliseconds;
+        properties.timezone = timezone;
+        m_calendar = _makeCalendar(properties);
+    } catch (const WrtDeviceApis::Commons::Exception& err) {
+        LOGE("%s : %s", err.GetClassName().c_str(), err.GetMessage().c_str());
+        if (m_calendar) {
+            delete m_calendar;
+        }
+        m_calendar = NULL;
+    }
+
+    if (dateCalender) {
+        delete dateCalender;
+    }
+    if (df) {
+        delete df;
+    }
+}
+
+
+bool TZDate::isAvailableTimezone(const std::string &timezone)
+{
+    TimeUtilTools util;
+    TimeZone *tz = util.makeTimeZone(timezone);
+
+    bool result = isAvailableTimezone(tz);
+    
+    if (tz) {
+        delete tz;
+    }
+    return result;
+}
+
+bool TZDate::isAvailableTimezone(TimeZone *tz) {
+    TimeUtilTools util;
+    bool result = true;
+    UnicodeString id;
+    tz->getID(id);
+
+    if (util.toString(id) == "Etc/Unknown") {
+        result = false;
+    }
+
+    return result;
+}
+
+std::string TZDate::_getTimezoneName(Calendar *cal)
+{
+    if (cal == NULL) {
+        ThrowMsg(Commons::UnknownException, "Invalid Date");
+    }
+
+    UnicodeString id;
+    TimeUtilTools util;
+
+    cal->getTimeZone().getID(id);
+    std::string s_result = util.toString(id);
+    LOGD("%s", s_result.c_str());
+    return s_result;
+}
+
+double TZDate::getTime() {
+    LOGD("entered");
+    if (m_calendar== NULL) {
+        LOGE("calendar is NULL");
+        ThrowMsg(Commons::UnknownException, "Invalid Date");
+    }
+
+    UErrorCode ec = U_ZERO_ERROR;
+
+    UDate date = m_calendar->getTime(ec);
+    if (U_SUCCESS(ec)) {
+        return static_cast<double>(date);
+    } else {
+        LOGE("Failed to get time: %d, %s", ec, u_errorName(ec));
+    }
+
+    ThrowMsg(Commons::PlatformException, "can't get time");
+}
+
+bool TZDate::setTime(const double time) {
+    LOGD("entered");
+    if (m_calendar == NULL)
+        ThrowMsg(Commons::UnknownException, "Invalid Date");
+
+    UErrorCode ec = U_ZERO_ERROR;
+
+    m_calendar->setTime(static_cast<UDate>(time), ec);
+    if (U_SUCCESS(ec)) {
+        return true;
+    } else {
+        LOGE("Failed to set time: %d, %s", ec, u_errorName(ec));
+    }
+
+    return false;
+}
+
+Calendar *TZDate::_makeCalendar(const TZDateProperties &properties)
+{
+    LOGD("entered");
+    UErrorCode ec = U_ZERO_ERROR;
+    TimeUtilTools util;
+
+    Calendar *cal = NULL;
+    if ((properties.timezone == "") || !isAvailableTimezone(properties.timezone)) {
+        cal = Calendar::createInstance(ec);
+    } else {
+        cal = Calendar::createInstance(util.makeTimeZone(properties.timezone) ,ec);
+    }
+
+    if ((cal != NULL) && U_SUCCESS(ec)) {
+        try {
+            cal->set(UCAL_DATE, 10); //set specific date because first date(1) or last date(31) can make changing of month because of timezone
+    
+            _set(TZDATE_YEAR, properties.year, cal);
+            _set(TZDATE_MONTH, properties.month, cal);
+            _set(TZDATE_DATE, properties.day, cal);
+            _set(TZDATE_HOUR_OF_DAY, properties.hours, cal);
+            _set(TZDATE_MINUTE, properties.minutes, cal);
+            _set(TZDATE_SECOND, properties.seconds, cal);
+            _set(TZDATE_MILLISECOND, properties.milliseconds, cal);
+        } catch (const WrtDeviceApis::Commons::Exception& err) {
+            LOGE("%s : %s ", err.GetClassName().c_str(), err.GetMessage().c_str());
+            if (cal) {
+                delete cal;
+            }
+            cal = NULL;
+        }
+        return cal;
+    } else {
+        LOGE("Failed to create calendar: %d, %s", ec, u_errorName(ec));
+    }
+
+    if (cal) {
+        delete cal;
+    }
+    return NULL;
+}
+
+
+long TZDate::_get(const TZDateFields field, Calendar *cal)
+{
+    LOGD("<<<");
+
+    if (cal == NULL) {
+        ThrowMsg(Commons::UnknownException, "Invalid Date");
+    }
+
+    if (_convertDateField(field) == UCAL_FIELD_COUNT) {
+        LOGD(">>> UCAL_FIELD_COUNT");
+        return -1;
+    }
+
+    UErrorCode ec = U_ZERO_ERROR;
+    TimeUtilTools util;
+    int32_t value = cal->get(_convertDateField(field), ec);
+    if (U_SUCCESS(ec)) {
+        long result = util.tolong(value);
+
+        LOGD(">>> result: %ld", result);
+        return result;
+    }
+    LOGE("Failed to get calendar: %d, %s", ec, u_errorName(ec));
+    ThrowMsg(Commons::PlatformException, "Can't get Calendar value");
+}
+
+long TZDate::get(const TZDateFields field)
+{
+    LOGD("<<<");
+
+    long result = _get(field, m_calendar);
+    if (field == TZDATE_DAY_OF_WEEK)
+        result--;
+    return result;
+}
+
+
+void TZDate::_set(const TZDateFields field, const long value, Calendar *cal)
+{
+    if (_convertDateField(field) == UCAL_FIELD_COUNT) {
+        return;
+    }
+
+    if (cal == NULL) {
+        ThrowMsg(Commons::UnknownException, "Invalid Date");
+    }
+
+    TimeUtilTools util;
+    Calendar *originCal = cal->clone();
+    cal->set(_convertDateField(field), util.toint32_t(value));
+    
+    LOGD("Field : %d, value : %ld, result: %d", field, value, _get(field, cal));
+    try {
+        if (field == TZDATE_YEAR) {
+            if (value != _get(field, cal))
+                ThrowMsg(Commons::PlatformException, "Out of range");
+        } else if (field == TZDATE_MONTH) {
+            long yearDiff = value / 12;
+            long month = value % 12;
+            if (value < 0) {
+                yearDiff--;
+                month += 12;
+            }
+            
+            long originYear = _get(TZDATE_YEAR, originCal);
+            if (((originYear + yearDiff) != _get(TZDATE_YEAR, cal))
+                || (month != _get(TZDATE_MONTH, cal))) {
+                LOGD("originYear: %ld, yearDiff: %ld, TZDATE_YEAR: %ld", originYear, yearDiff, _get(TZDATE_YEAR, cal));
+                LOGD(" month: %ld, TZDATE_MONTH: %ld", month, _get(TZDATE_MONTH, cal));
+                ThrowMsg(Commons::PlatformException, "Out of range");
+            }
+        } else {
+            UErrorCode ec = U_ZERO_ERROR;
+            double diff = value - _get(field, originCal);
+            if (field == TZDATE_DATE)
+                diff *= U_MILLIS_PER_DAY;
+            else if (field == TZDATE_HOUR_OF_DAY)
+                diff *= U_MILLIS_PER_HOUR;
+            else if (field == TZDATE_MINUTE)
+                diff *= U_MILLIS_PER_MINUTE;
+            else if (field == TZDATE_SECOND)
+                diff *= U_MILLIS_PER_SECOND;
+        
+            UDate originUDate = originCal->getTime(ec);
+            if (!U_SUCCESS(ec)) {
+                LOGE("Failed to get time: %d, %s", ec, u_errorName(ec));
+                ThrowMsg(Commons::PlatformException, "ICU Error");
+            }
+
+            LOGD("originUDate : %f, diff : %ld", (double)originUDate, diff);
+
+            if ((U_DATE_MAX - originUDate) < diff)
+                ThrowMsg(Commons::PlatformException, "Out of range");
+        }
+    } catch (Commons::PlatformException& err) {
+        LOGE("%s", err.GetMessage().c_str());
+        if (originCal)
+            delete originCal;
+        throw(err);
+    }
+    if (originCal) {
+        delete originCal;
+    }
+}
+
+void TZDate::set(const TZDateFields field, const long value)
+{
+    try {
+        _set(field, value, m_calendar);
+    } catch (Commons::PlatformException& err) {
+        LOGE("%s", err.GetMessage().c_str());
+        if (m_calendar) {
+            delete m_calendar;
+        }
+        m_calendar = NULL;
+    }
+}
+
+TZDateProperties TZDate::_makeProperties(Calendar *cal)
+{
+    TZDateProperties result;
+    TimeUtilTools util;
+
+    result.year = _get(TZDATE_YEAR, cal);
+    result.month = _get(TZDATE_MONTH,cal);
+    result.day = _get(TZDATE_DATE, cal);
+    result.hours = _get(TZDATE_HOUR_OF_DAY, cal);
+    result.minutes = _get(TZDATE_MINUTE, cal);
+    result.seconds = _get(TZDATE_SECOND, cal);
+    result.milliseconds = _get(TZDATE_MILLISECOND, cal);
+    result.timezone=  _getTimezoneName(cal);
+
+    return result;
+}
+
+TZDateProperties TZDate::makeProperties()
+{
+    return _makeProperties(m_calendar);
+}
+
+
+
+const UCalendarDateFields TZDate::_convertDateField(const TZDateFields field)
+{
+    switch (field) {
+    case TZDATE_ERA:
+        return UCAL_ERA;
+        break;
+    case TZDATE_YEAR:
+        return UCAL_EXTENDED_YEAR;
+        break;
+    case TZDATE_MONTH:
+        return UCAL_MONTH;
+        break;
+    case TZDATE_WEEK_OF_YEAR:
+        return UCAL_WEEK_OF_YEAR;
+        break;
+    case TZDATE_WEEK_OF_MONTH:
+        return UCAL_WEEK_OF_MONTH;
+        break;
+    case TZDATE_DATE:
+        return UCAL_DATE;
+        break;
+    case TZDATE_DAY_OF_YEAR:
+        return UCAL_DAY_OF_YEAR;
+        break;
+    case TZDATE_DAY_OF_WEEK:
+        return UCAL_DAY_OF_WEEK;
+        break;
+    case TZDATE_DAY_OF_WEEK_IN_MONTH:
+        return UCAL_DAY_OF_WEEK_IN_MONTH;
+        break;
+    case TZDATE_AM_PM:
+        return UCAL_AM_PM;
+        break;
+    case TZDATE_HOUR:
+        return UCAL_HOUR;
+        break;
+    case TZDATE_HOUR_OF_DAY:
+        return UCAL_HOUR_OF_DAY;
+        break;
+    case TZDATE_MINUTE:
+        return UCAL_MINUTE;
+        break;
+    case TZDATE_SECOND:
+        return UCAL_SECOND;
+        break;
+    case TZDATE_MILLISECOND:
+        return UCAL_MILLISECOND;
+        break;
+    case TZDATE_ZONE_OFFSET:
+        return UCAL_ZONE_OFFSET;
+        break;
+    case TZDATE_DST_OFFSET:
+        return UCAL_DST_OFFSET;
+        break;
+    default:
+        return UCAL_FIELD_COUNT;
+    }
+}
+
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+
+} // Time
+} // DeviceAPI
diff --git a/src/TimeUtil/TZDate.h b/src/TimeUtil/TZDate.h
new file mode 100755 (executable)
index 0000000..7d4fd1a
--- /dev/null
@@ -0,0 +1,191 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        TZDate.h
+*/
+
+#ifndef __TIZEN_TZDATE_H_
+#define __TIZEN_TZDATE_H_
+
+#include <ctime>
+#include <tgmath.h>
+#include <map>
+#include <string>
+#include <memory>
+#include <Logger.h>
+#include <unicode/calendar.h>
+#include <sys/time.h>
+#include <PlatformException.h>
+
+#include "ArgumentValidator.h"
+#include "TimeDuration.h"
+#include "TimeUtilTools.h"
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+#include "TZDateProperties.h"
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+namespace DeviceAPI {
+namespace Time {
+
+enum DSTTransition {
+    PREVDST,
+    NEXTDST
+};
+
+class TZDate;
+typedef std::shared_ptr< TZDate > TZDatePtr;
+
+/**
+ * The TZDate object represents information regarding a given date / time in
+ * a predefined timezone.
+ */
+class TZDate {
+public:
+    TZDate();
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+
+    TZDate(const std::string &timezone);
+    TZDate(const TZDateProperties &properties);
+    TZDate(const std::string &dateString, const double milliseconds, const std::string &timezone);
+
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+    TZDate(time_t datetime, std::string timezone = "");
+    TZDate(long year, long month, long day, long hours = 0, long minutes = 0,
+           long seconds = 0, long milliseconds = 0, std::string timezone = "");
+    TZDate(const TZDate& tzdate);
+    TZDate(icu::Calendar* cal);
+    TZDate& operator =( const TZDate& tzdate);
+    virtual ~TZDate();
+
+    long getDate() const;
+    void setDate(long date);
+    long getDay() const;
+    long getFullYear() const;
+    void setFullYear(long year);
+    long getHours() const;
+    void setHours(long hours);
+    long getMilliseconds() const;
+    void setMilliseconds(long ms);
+    long getMinutes() const;
+    void setMinutes(long minutes);
+    long getMonth() const;
+    void setMonth(long month);
+    long getSeconds() const;
+    void setSeconds(long seconds);
+    long getUTCDate() const;
+    void setUTCDate(long date);
+    long getUTCDay() const;
+    long getUTCFullYear() const;
+    void setUTCFullYear(long year);
+    long getUTCHours() const;
+    void setUTCHours(long hours);
+    long getUTCMilliseconds() const;
+    void setUTCMilliseconds(long ms);
+    long getUTCMinutes() const;
+    void setUTCMinutes(long minutes);
+    long getUTCMonth() const;
+    void setUTCMonth(long month);
+    long getUTCSeconds() const;
+    void setUTCSeconds(long seconds);
+    std::string getTimezone() const;
+    TZDatePtr toTimezone(const std::string& tzid) const;
+    TZDatePtr toLocalTimezone() const;
+    TZDatePtr toUTC() const;
+    TimeDurationPtr difference(TZDatePtr other) const;
+    bool equalsTo(TZDatePtr other) const;
+    bool earlierThan(TZDatePtr other) const;
+    bool laterThan(TZDatePtr other) const;
+    TZDatePtr addDuration(TimeDurationPtr duration) const;
+    std::string toLocaleDateString() const;
+    std::string toLocaleTimeString() const;
+    std::string toLocaleString() const;
+    std::string toDateString() const;
+    std::string toTimeString() const;
+    std::string toString(bool bLocale = false,
+            TimeUtilTools::DateTimeFormatType type = TimeUtilTools::DATETIME_FORMAT) const;
+    std::string getTimezoneAbbreviation() const;
+    long secondsFromUTC() const;
+    bool isDST() const; /**< indicates if Daylight Saving Time(DST) is active for the TZDate */
+    TZDatePtr getPreviousDSTTransition() const;
+    TZDatePtr getNextDSTTransition() const;
+
+    TZDatePtr getDSTTransition(DSTTransition tr) const;
+    icu::Calendar* getCalendar(const std::string& timezone) const;
+    icu::Calendar* getUTCCalendar() const;
+    void setTimezone(const std::string& timezone, bool timezone_is_certain = false);
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+
+    enum TZDateFields {
+        TZDATE_ERA,
+        TZDATE_YEAR,
+        TZDATE_MONTH,
+        TZDATE_WEEK_OF_YEAR,
+        TZDATE_WEEK_OF_MONTH,
+        TZDATE_DATE,
+        TZDATE_DAY_OF_YEAR,
+        TZDATE_DAY_OF_WEEK,
+        TZDATE_DAY_OF_WEEK_IN_MONTH,
+        TZDATE_AM_PM,
+        TZDATE_HOUR,
+        TZDATE_HOUR_OF_DAY,
+        TZDATE_MINUTE,
+        TZDATE_SECOND,
+        TZDATE_MILLISECOND,
+        TZDATE_ZONE_OFFSET,
+        TZDATE_DST_OFFSET,
+
+        TZDATE_FIELDS_COUNT,
+    };
+
+    TZDateProperties makeProperties();
+
+    double getTime();
+    bool setTime(const double time);
+
+    long get(const TZDateFields field);
+    void set(const TZDateFields field, const long value);
+
+    bool isAvailableTimezone(const std::string &timezone);
+    bool isAvailableTimezone(icu::TimeZone *tz);
+
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+private:
+    icu::Calendar* m_calendar;
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+    long _get(const TZDateFields field, icu::Calendar *cal);
+    void _set(const TZDateFields field, const long value, icu::Calendar *cal);
+
+    std::string _getTimezoneName(icu::Calendar *cal);
+    const UCalendarDateFields _convertDateField(const TZDateFields field);
+
+    icu::Calendar * _makeCalendar(const TZDateProperties &properties);
+    TZDateProperties _makeProperties(icu::Calendar *cal);
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+};
+
+} // Time
+} // DeviceAPI
+
+#endif //__TIZEN_TZDATE_H_
diff --git a/src/TimeUtil/TZDateProperties.h b/src/TimeUtil/TZDateProperties.h
new file mode 100755 (executable)
index 0000000..5dde2ba
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+#ifndef WRTPLUGINS_API_TIMEUTIL_TZDATE_PROPERTIES_H_
+#define WRTPLUGINS_API_TIMEUTIL_TZDATE_PROPERTIES_H_
+
+#include <ctime>
+#include <string>
+#include <memory>
+
+namespace DeviceAPI {
+namespace Time {
+
+struct TZDateProperties {
+    long year;
+    long month;
+    long day;
+    long hours;
+    long minutes;
+    long seconds;
+    long milliseconds;
+    std::string timezone;
+    TZDateProperties()
+        : year(0), month(0), day(0), hours(0), minutes(0), seconds(0), milliseconds(0),
+        timezone("") {
+    }
+};
+
+
+typedef std::shared_ptr<TZDateProperties> TZDatePropertiesPtr;
+
+} // Time
+} // DeviceAPI
+
+#endif //WRTPLUGINS_API_TIMEUTIL_TZDATE_PROPERTIES_H_
\ No newline at end of file
diff --git a/src/TimeUtil/TimeDuration.cpp b/src/TimeUtil/TimeDuration.cpp
new file mode 100755 (executable)
index 0000000..4270102
--- /dev/null
@@ -0,0 +1,221 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        TimeDuration.cpp
+*/
+
+#include "TimeDuration.h"
+
+namespace DeviceAPI {
+namespace Time {
+
+std::map <const std::string, long long> TimeDuration::units = {
+    {MSECS, TIME_MSECS_UNIT},
+    {SECS, TIME_SECS_UNIT},
+    {MINS, TIME_MINS_UNIT},
+    {HOURS, TIME_HOURS_UNIT},
+    {DAYS, TIME_DAYS_UNIT}
+};
+
+TimeDuration::TimeDuration()
+{
+    m_length = 0;
+    m_unit = MSECS;
+}
+
+TimeDuration::TimeDuration(long long length, std::string unit)
+{
+    m_length = length;
+    if (unit == MSECS or unit == SECS or unit == MINS or unit == HOURS or unit == DAYS) {
+        m_unit = unit;
+    }
+    else {
+        m_unit = MSECS;
+    }
+}
+
+TimeDuration::~TimeDuration()
+{
+}
+
+long long TimeDuration::getLength() const
+{
+    return m_length;
+}
+
+void TimeDuration::setLength(long long length)
+{
+    m_length = length;
+}
+
+std::string TimeDuration::getUnit() const
+{
+    return m_unit;
+}
+
+void TimeDuration::setUnit(std::string unit)
+{
+    if (unit == MSECS or unit == SECS or unit == MINS or unit == HOURS or unit == DAYS) {
+        m_unit = unit;
+    }
+    else {
+        LOGE("Invalid unit value");
+        m_unit = MSECS;
+    }
+}
+
+TimeDurationPtr TimeDuration::difference(TimeDurationPtr other)
+{
+    long long len1 = this->m_length;
+    long long len2 = other->m_length;
+    long long unit1 = this->units[this->m_unit];
+    long long unit2 = other->units[other->m_unit];
+    std::string unit = "";
+    long long div = 0;
+    long long length = 0;
+
+    if (unit1 > unit2) {
+        div = unit1 / unit2;
+        if (validateLongLongRange(len1, div)) {
+            length = len1 * div - len2;
+            unit = other->m_unit;
+        }
+    }
+    else if (unit1 < unit2) {
+        div = unit2 / unit1;
+        if (validateLongLongRange(len2, div)) {
+            length = len1 - len2 * div;
+            unit = this->m_unit;
+        }
+    }
+    else {
+        length = len1 - len2;
+        unit = this->m_unit;
+        if (0 == length)
+            unit = DAYS;
+    }
+
+    TimeDurationPtr ret = TimeDurationPtr(new (std::nothrow) TimeDuration(length, unit));
+
+    findTheBiggestPossibleUnit(ret);
+    if (!isInRange(ret->getLength())) {
+        LOGE("limit value reached");
+        throw Common::UnknownException("limit value reached");
+    }
+    return ret;
+}
+
+bool TimeDuration::equalsTo(TimeDurationPtr other)
+{
+    try {
+        TimeDurationPtr ret = this->difference(other);
+        long long i = ret->getLength();
+
+        if (i == 0) {
+            return true;
+        }
+    }
+    catch (Common::BasePlatformException &error) {
+        LOGE("%s : %s", error.getName().c_str(), error.getMessage().c_str());
+        throw error;
+    }
+    return false;
+}
+
+bool TimeDuration::lessThan(TimeDurationPtr other)
+{
+    try {
+        TimeDurationPtr ret = this->difference(other);
+        long long i = ret->getLength();
+
+        if (i < 0) {
+            return true;
+        }
+    }
+    catch (Common::BasePlatformException &error) {
+        LOGE("%s : %s", error.getName().c_str(), error.getMessage().c_str());
+        throw error;
+    }
+    return false;
+}
+
+bool TimeDuration::greaterThan(TimeDurationPtr other)
+{
+    try {
+        TimeDurationPtr ret = this->difference(other);
+        long long i = ret->getLength();
+
+        if (i > 0) {
+            return true;
+        }
+    }
+    catch (Common::BasePlatformException &error) {
+        LOGE("%s : %s", error.getName().c_str(), error.getMessage().c_str());
+        throw error;
+    }
+    return false;
+}
+
+bool TimeDuration::isInRange(long long len)
+{
+    long long max = 9007199254740992; // max number value in javascript
+    if (len > max or len < -max) {
+        return false;
+    }
+    return true;
+}
+
+bool TimeDuration::validateLongLongRange(long long arg1, long long arg2)
+{
+    if (llabs(arg1) > LLONG_MAX / llabs(arg2)) {
+        LOGE("limit value reached");
+        throw Common::UnknownException("limit value reached");
+    }
+    else {
+        return true;
+    }
+}
+
+void TimeDuration::findTheBiggestPossibleUnit(TimeDurationPtr td)
+{
+    long long len = td->m_length;
+    long long minUnit = td->units[td->m_unit];
+    std::string unit = td->m_unit;
+
+    if (len * minUnit % TIME_DAYS_UNIT == 0) {
+        len = len * minUnit / TIME_DAYS_UNIT;
+        unit = DAYS;
+    }
+    else if (len * minUnit % TIME_HOURS_UNIT == 0) {
+        len = len * minUnit / TIME_HOURS_UNIT;
+        unit = HOURS;
+    }
+    else if (len * minUnit % TIME_MINS_UNIT == 0) {
+        len = len * minUnit / TIME_MINS_UNIT;
+        unit = MINS;
+    }
+    else if (len * minUnit % TIME_SECS_UNIT == 0) {
+        len = len * minUnit / TIME_SECS_UNIT;
+        unit = SECS;
+    }
+    td->m_length = len;
+    td->m_unit = unit;
+}
+
+} // Time
+} // DeviceAPI
diff --git a/src/TimeUtil/TimeDuration.h b/src/TimeUtil/TimeDuration.h
new file mode 100755 (executable)
index 0000000..eafa0ad
--- /dev/null
@@ -0,0 +1,83 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        TimeDuration.h
+*/
+
+#ifndef __TIZEN_TIMEDURATION_H__
+#define __TIZEN_TIMEDURATION_H__
+
+#include <string>
+#include <map>
+#include <limits.h>
+#include <cmath>
+#include <Logger.h>
+#include <memory>
+#include <PlatformException.h>
+
+namespace DeviceAPI {
+namespace Time {
+
+class TimeDuration;
+typedef std::shared_ptr< TimeDuration > TimeDurationPtr;
+
+const long long TIME_MSECS_UNIT = 1;
+const long long TIME_SECS_UNIT = 1000;
+const long long TIME_MINS_UNIT = 1000 * 60;
+const long long TIME_HOURS_UNIT = 1000 * 60 * 60;
+const long long TIME_DAYS_UNIT = 1000 * 60 * 60 * 24;
+
+const std::string MSECS = "MSECS";
+const std::string SECS = "SECS";
+const std::string MINS = "MINS";
+const std::string HOURS = "HOURS";
+const std::string DAYS = "DAYS";
+
+/**
+ * The TimeDuration object that contains the length and its associated time unit.
+ */
+class TimeDuration {
+public:
+    TimeDuration();
+    TimeDuration(long long length, std::string unit = MSECS);
+    virtual ~TimeDuration();
+
+    long long getLength() const;
+    void setLength(long long length);
+
+    std::string getUnit() const;
+    void setUnit(std::string unit);
+
+    TimeDurationPtr difference(TimeDurationPtr other);
+    bool equalsTo(TimeDurationPtr other);
+    bool lessThan(TimeDurationPtr other);
+    bool greaterThan(TimeDurationPtr other);
+    static std::map <const std::string, long long> units;
+    static void findTheBiggestPossibleUnit(TimeDurationPtr td);
+    static bool isInRange(long long len);
+
+private:
+    long long m_length;
+    std::string m_unit;
+    bool validateLongLongRange(long long arg1, long long arg2);
+};
+
+} // Time
+} // DeviceAPI
+
+#endif // __TIZEN_TIMEDURATION_H__
diff --git a/src/TimeUtil/TimeUtil.cpp b/src/TimeUtil/TimeUtil.cpp
new file mode 100755 (executable)
index 0000000..f13e050
--- /dev/null
@@ -0,0 +1,161 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        TimeUtil.cpp
+*/
+
+#include <string>
+#include <vconf.h>
+
+#include "TimeUtil.h"
+
+namespace DeviceAPI {
+namespace Time {
+
+namespace {
+static void changedTimeCallback(keynode_t* node, void* user_data) {
+    LOGD("entered KeyName: %s", vconf_keynode_get_name(node));
+    MultiCallbackUserData* callback = NULL;
+
+    if (user_data && !strcmp(vconf_keynode_get_name(node), VCONFKEY_SYSTEM_TIME_CHANGED)) {
+        LOGD("Time changed");
+        ((TimeUtil*)user_data)->changeDefaultTimezone();
+    }
+}
+}//private namespace
+
+TimeUtil::TimeUtil()
+{
+    LOGD("Enter");
+    bRegisteredDateTimeChanged = false;
+    m_timezoneChangeCallback = NULL;
+    m_timeChangeCallback = NULL;
+
+    TimeUtilTools util;
+    m_timezone = util.getDefaultTimezone();
+
+    if (vconf_notify_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, changedTimeCallback, (void*)this) == 0) {
+        LOGD("Success to register changedDateTimeCallback");
+        bRegisteredDateTimeChanged = true;
+    }
+}
+
+TimeUtil::~TimeUtil()
+{
+    LOGD("Enter");
+    unsetTimeZoneChangeListener();
+
+    if (bRegisteredDateTimeChanged) {
+        vconf_ignore_key_changed(VCONFKEY_SYSTEM_TIME_CHANGED, changedTimeCallback);
+        bRegisteredDateTimeChanged = false;
+    }
+}
+
+TZDatePtr TimeUtil::getCurrentDateTime()
+{
+    TZDatePtr tz = TZDatePtr(new (std::nothrow) TZDate());
+    return tz;
+}
+
+std::string TimeUtil::getLocalTimezone()
+{
+    return TimeUtilTools::getLocalTimeZone();
+
+}
+std::vector<std::string> TimeUtil::getAvailableTimezones()
+{
+    std::vector<std::string> vec = TimeUtilTools::getTimezonesArray();
+    return vec;
+}
+std::string TimeUtil::getDateFormat(bool shortformat)
+{
+    return TimeUtilTools::getDateFormat(shortformat);
+}
+std::string TimeUtil::getTimeFormat()
+{
+    return TimeUtilTools::getTimeFormat();
+}
+bool TimeUtil::isLeapYear(long year)
+{
+    return TimeUtilTools::isLeapyear(year);
+}
+
+void TimeUtil::changeDefaultTimezone()
+{
+    LOGD("Enter");
+
+    std::string s_result;
+    TimeUtilTools util;
+    std::string defaultTimezone = util.getDefaultTimezone();
+
+    if (m_timezone != defaultTimezone) {
+        m_timezone = defaultTimezone;
+        UnicodeString *timezoneId = util.toUnicodeString(defaultTimezone);
+        if (timezoneId) {
+            TimeZone* zone = TimeZone::createTimeZone(*timezoneId);
+            if (zone) {
+                TimeZone::setDefault(*zone);
+                delete zone;
+            }
+            delete timezoneId;
+        }
+        if (m_timezoneChangeCallback) {
+            LOGD("Timezone changed");
+            m_timezoneChangeCallback->invokeCallback("onsuccess");
+        }
+    }
+    if (m_timeChangeCallback) {
+        LOGD("Time changed");
+        m_timeChangeCallback->invokeCallback("onsuccess");
+    }
+}
+
+void TimeUtil::setDateTimeChangeListener(MultiCallbackUserData* callback)
+{
+    LOGD("Enter");
+    m_timeChangeCallback = callback;
+}
+
+void TimeUtil::unsetDateTimeChangeListener()
+{
+    LOGD("Enter");
+
+    if (m_timeChangeCallback) {
+        delete m_timeChangeCallback;
+    }
+    m_timeChangeCallback = NULL;
+}
+
+void TimeUtil::setTimeZoneChangeListener(MultiCallbackUserData* callback)
+{
+    LOGD("Enter");
+    m_timezoneChangeCallback = callback;
+}
+
+void TimeUtil::unsetTimeZoneChangeListener()
+{
+    LOGD("Enter");
+
+    if (m_timezoneChangeCallback) {
+        delete m_timezoneChangeCallback;
+    }
+    m_timezoneChangeCallback = NULL;
+}
+
+} // Time
+} // DeviceAPI
diff --git a/src/TimeUtil/TimeUtil.h b/src/TimeUtil/TimeUtil.h
new file mode 100755 (executable)
index 0000000..50d2481
--- /dev/null
@@ -0,0 +1,72 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        TimeUtil.h
+*/
+
+#ifndef __TIZEN_TIMEUTIL_H__
+#define __TIZEN_TIMEUTIL_H__
+
+#include <string>
+#include <vector>
+#include <PlatformException.h>
+#include <MultiCallbackUserData.h>
+
+#include "TZDate.h"
+#include "TimeUtilTools.h"
+#include "ArgumentValidator.h"
+
+namespace DeviceAPI {
+namespace Time {
+
+using namespace DeviceAPI::Common;
+/**
+ * The TimeUtil class that provides access to the time API.
+ */
+class TimeUtil {
+public:
+    TimeUtil();
+    virtual ~TimeUtil();
+
+    TZDatePtr getCurrentDateTime();
+    std::string getLocalTimezone();
+    std::vector<std::string> getAvailableTimezones();
+    std::string getDateFormat(bool shortformat);
+    std::string getTimeFormat();
+    bool isLeapYear(long year);
+    MultiCallbackUserData* getDateTimeChangeCallback();
+    MultiCallbackUserData* getTimeZoneChangeCallback();
+    void invokeTimeZoneChangeCallback();
+    void setDateTimeChangeListener(MultiCallbackUserData* callback);
+    void unsetDateTimeChangeListener();
+    void setTimeZoneChangeListener(MultiCallbackUserData* callback);
+    void unsetTimeZoneChangeListener();
+    void changeDefaultTimezone();
+
+private:
+    std::string m_timezone;
+    std::vector<std::string> availableTimezones;
+    bool bRegisteredDateTimeChanged;
+    MultiCallbackUserData* m_timezoneChangeCallback;
+    MultiCallbackUserData* m_timeChangeCallback;
+};
+
+} // Time
+} // DeviceAPI
+
+#endif // __TIZEN_TIMEUTIL_H__
diff --git a/src/TimeUtil/TimeUtilConverter.cpp b/src/TimeUtil/TimeUtilConverter.cpp
new file mode 100755 (executable)
index 0000000..ef8b810
--- /dev/null
@@ -0,0 +1,335 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/Exception.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include <CommonsJavaScript/Validator.h>
+#include <CommonsJavaScript/JSUtils.h>
+#include <Commons/RegexUtils.h>
+
+#include "TimeUtilConverter.h"
+#include "JSTZDate.h"
+#include "JSTimeDuration.h"
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+
+namespace DeviceAPI {
+namespace Time {
+
+TimeUtilConverter::TimeUtilConverter(JSContextRef context)
+: WrtDeviceApis::CommonsJavaScript::Converter(context) {
+}
+
+TimeUtilConverter::~TimeUtilConverter() {
+}
+
+short TimeUtilConverter::toShort(const JSValueRef& arg)
+{
+    double tmp = toNumber_(arg);
+    return (isNan(tmp) ? 0 : static_cast<short>(tmp));
+}
+
+TZDateProperties TimeUtilConverter::getPropertiesInTZDate(JSValueRef arg) {
+    if (JSValueIsNull(m_context, arg) || JSValueIsUndefined(m_context, arg) || !JSValueIsObjectOfClass(m_context, arg, JSTZDate::getClassRef())) {
+        ThrowMsg(Commons::ConversionException,
+                 "Wrong Input Type");
+    }
+    JSObjectRef obj = toJSObjectRef(arg);
+    return getPropertiesInTZDate(obj);
+}
+
+TZDateProperties TimeUtilConverter::getPropertiesInTZDate(JSObjectRef arg) {
+    if (!arg) {
+        LOGE("Object is null");
+        ThrowMsg(Commons::ConversionException, "Private object not initialized");
+    }
+    TZDateHolder* privateObject = static_cast<TZDateHolder*>(JSObjectGetPrivate(arg));
+    if (!privateObject) {
+        LOGE("Private object is not set.");
+        ThrowMsg(Commons::ConversionException, "Private object not initialized");
+    }
+    
+    TZDatePtr tzDate = privateObject->ptr;
+    TZDateProperties result;
+
+    result.timezone = tzDate->getTimezone();
+    result.year = tzDate->get(TZDate::TZDATE_YEAR);
+    result.month = tzDate->get(TZDate::TZDATE_MONTH);
+    result.day= tzDate->get(TZDate::TZDATE_DATE);
+    result.hours= tzDate->get(TZDate::TZDATE_HOUR_OF_DAY);
+    result.minutes= tzDate->get(TZDate::TZDATE_MINUTE);
+    result.seconds= tzDate->get(TZDate::TZDATE_SECOND);
+    result.milliseconds = tzDate->get(TZDate::TZDATE_MILLISECOND);
+    return result;
+}
+
+JSObjectRef TimeUtilConverter::makeDurationObject(const DurationProperties &duration) {
+    return JSTimeDuration::createJSObject(m_context, duration);
+}
+
+JSObjectRef TimeUtilConverter::makeMillisecondDurationObject(const long long length) {
+    DurationProperties duration;
+    duration.length = length;
+    duration.unit = MSECS_UNIT;
+    const long long dayToMsecs = 1000 * 60 * 60 * 24;
+    if ((length % dayToMsecs) == 0) {
+        duration.length = length / dayToMsecs;
+        duration.unit = DAYS_UNIT;
+    }
+
+    return makeDurationObject(duration);
+}
+
+DurationPropertiesPtr TimeUtilConverter::getDuration(JSValueRef value) {
+    if (!JSValueIsObjectOfClass(m_context, value, JSTimeDuration::getClassRef())) {
+        ThrowMsg(Commons::ConversionException, "Wrong input type");
+    }
+
+    TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(toJSObjectRef(value)));
+    DurationPropertiesPtr duration = privateObject->getObject();
+    return duration;
+}
+
+DurationProperties TimeUtilConverter::getDurationProperties(JSValueRef value) {
+    DurationProperties duration;
+    duration.length = getDurationLength(value);
+    duration.unit = getDurationUnit(value);
+    return duration;
+}
+
+long long TimeUtilConverter::getDurationLength(JSValueRef value) {
+    if (JSValueIsNull(m_context, value) || JSValueIsUndefined(m_context, value) || !JSValueIsObjectOfClass(m_context, value, JSTimeDuration::getClassRef())) {
+        ThrowMsg(Commons::ConversionException,
+                 "Wrong input type");
+    }
+    JSObjectRef obj = toJSObjectRef(value);
+    return getDurationLength(obj);
+}
+
+long long TimeUtilConverter::getDurationLength(JSObjectRef object) {
+    TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
+    if (!privateObject) {
+        LOGE("Private object is not set.");
+        ThrowMsg(Commons::ConversionException, "Private object not initialized");
+    }
+
+    DurationPropertiesPtr duration = privateObject->getObject();
+
+    return duration->length;
+}
+
+short TimeUtilConverter::getDurationUnit(JSValueRef value) {
+    if (JSValueIsNull(m_context, value) || JSValueIsUndefined(m_context, value) || !JSValueIsObjectOfClass(m_context, value, JSTimeDuration::getClassRef())) {
+        ThrowMsg(Commons::ConversionException,
+                 "Wrong input type");
+    }
+    JSObjectRef obj = toJSObjectRef(value);
+    return getDurationUnit(obj);
+}
+
+short TimeUtilConverter::getDurationUnit(JSObjectRef object) {
+    TimeDurationPrivObject* privateObject = static_cast<TimeDurationPrivObject*>(JSObjectGetPrivate(object));
+    if (!privateObject) {
+        LOGE("Private object is not set.");
+        ThrowMsg(Commons::ConversionException, "Private object not initialized");
+    }
+
+    DurationPropertiesPtr duration = privateObject->getObject();
+
+    return duration->unit;
+
+}
+
+short TimeUtilConverter::toDurationUnit(std::string strUnit) {
+    if (!strUnit.compare("DAYS"))
+        return DAYS_UNIT;
+    else if (!strUnit.compare("SECS"))
+        return SECONDS_UNIT;
+    else if (!strUnit.compare("MINS"))
+        return MINUTES_UNIT;
+    else if (!strUnit.compare("HOURS"))
+        return HOURS_UNIT;
+    else
+        return MSECS_UNIT;
+}
+
+std::string TimeUtilConverter::toDurationUnitString(short unit) {
+    switch (unit) {
+        case DAYS_UNIT:
+            return "DAYS";
+        case SECONDS_UNIT:
+            return "SECS";
+        case MINUTES_UNIT:
+            return "MINS";
+        case HOURS_UNIT:
+            return "HOURS";
+        case MSECS_UNIT:
+        default:
+            return "MSECS";
+    }
+}
+
+long long TimeUtilConverter::convertDurationLength(DurationProperties duration, short unit) {
+    if (duration.unit < unit)
+        ThrowMsg(Commons::ConversionException, "Unit is larger than duration's unit");
+
+    if (duration.unit == unit)
+        return duration.length;
+
+    long long result = duration.length;
+
+    switch(unit) {
+        case MSECS_UNIT:
+            result = result * 1000;
+            if (duration.unit == SECONDS_UNIT)
+                return result;
+            // intentional fall-through
+
+        case SECONDS_UNIT:
+            result = result * 60;
+            if (duration.unit == MINUTES_UNIT)
+                return result;
+            // intentional fall-through
+
+        case MINUTES_UNIT:
+            result = result * 60;
+            if (duration.unit == HOURS_UNIT)
+                return result;
+            // intentional fall-through
+
+        case HOURS_UNIT:
+            result = result * 24;
+            return result;
+            // intentional fall-through
+    }
+    return result;
+}
+
+DurationProperties TimeUtilConverter::optimizedTimeDuration(DurationProperties origin) {
+    DurationProperties result;
+    result.unit = origin.unit;
+    result.length = origin.length;
+
+    switch(origin.unit) {
+        case MSECS_UNIT:
+            if (result.length % 1000)
+                return result;
+            result.unit = SECONDS_UNIT;
+            result.length /= 1000;
+            // intentional fall-through
+
+        case SECONDS_UNIT:
+            if (result.length % 60)
+                return result;
+            result.unit = MINUTES_UNIT;
+            result.length /= 60;
+            // intentional fall-through
+
+        case MINUTES_UNIT:
+            if (result.length % 60)
+                return result;
+            result.unit = HOURS_UNIT;
+            result.length /= 60;
+            // intentional fall-through
+
+        case HOURS_UNIT:
+            if (result.length % 24)
+                return result;
+            result.unit = DAYS_UNIT;
+            result.length /= 24;
+            // intentional fall-through
+    }    
+    return result;
+}
+
+double TimeUtilConverter::getTimeInMilliseconds(JSValueRef arg) {
+    if (JSValueIsNull(m_context, arg) || JSValueIsUndefined(m_context, arg) || !JSValueIsObjectOfClass(m_context, arg, JSTZDate::getClassRef())) {
+        ThrowMsg(Commons::ConversionException,
+                 "Wrong input type");
+    }
+    JSObjectRef obj = toJSObjectRef(arg);
+
+    return getTimeInMilliseconds(obj);
+}
+
+double TimeUtilConverter::getTimeInMilliseconds(JSObjectRef arg) {
+    if (!arg) {
+        LOGE("Object is null");
+        ThrowMsg(Commons::ConversionException, "Object is null");
+    }
+
+    TZDateHolder* privateObject = static_cast<TZDateHolder*>(JSObjectGetPrivate(arg));
+    if (!privateObject) {
+        LOGE("Private object is not set.");
+        ThrowMsg(Commons::ConversionException, "Private object not initialized");
+    }
+
+    TZDatePtr tzDate = privateObject->ptr;
+
+    return static_cast<double>(tzDate->getDate());
+}
+
+tm TimeUtilConverter::toTZDateTime(JSValueRef arg) {
+    if (JSValueIsNull(m_context, arg) || JSValueIsUndefined(m_context, arg) || !JSValueIsObjectOfClass(m_context, arg, JSTZDate::getClassRef())) {
+        ThrowMsg(Commons::ConversionException,
+                 "Wrong input type");
+    }
+    JSObjectRef obj = toJSObjectRef(arg);
+
+    return toTZDateTime(obj);
+}
+
+tm TimeUtilConverter::toTZDateTime(JSObjectRef arg) {
+    if (!arg) {
+        LOGE("Object is null");
+        ThrowMsg(Commons::ConversionException, "Object is null");
+    }
+
+    //TZDatePrivObject* privateObject = static_cast<TZDatePrivObject*>(JSObjectGetPrivate(arg));
+    TZDateHolder* privateObject = static_cast<TZDateHolder*>(JSObjectGetPrivate(arg));
+    if (!privateObject) {
+        LOGE("Private object is not set.");
+        ThrowMsg(Commons::ConversionException, "Private object not initialized");
+    }
+
+    TZDatePtr tzDate = privateObject->ptr;
+    TZDatePtr utcTzDate(new TZDate(tzDate->getDate(), tzDate->getTimezone()));
+//    if (!utcTzDate->setDate(tzDate->getDate()))
+//        ThrowMsg(Commons::ConversionException, "Can not set Time");
+
+    TZDateProperties utcProperties = utcTzDate->makeProperties();
+    struct tm  utcTm;
+    memset(&utcTm, 0, sizeof(utcTm));
+
+    utcTm.tm_year = utcProperties.year - 1900;
+    utcTm.tm_mon = utcProperties.month;
+    utcTm.tm_mday= utcProperties.day;
+    utcTm.tm_hour= utcProperties.hours;
+    utcTm.tm_min=utcProperties.minutes;
+    utcTm.tm_sec= utcProperties.seconds;
+    utcTm.tm_isdst = 0;
+    return utcTm;
+}
+
+JSObjectRef TimeUtilConverter::toJSValueRefTZDate(const double milliseconds, const std::string &timezone) {
+    return JSTZDate::createJSObject(m_context, milliseconds, timezone);
+}
+
+}
+}
diff --git a/src/TimeUtil/TimeUtilConverter.h b/src/TimeUtil/TimeUtilConverter.h
new file mode 100755 (executable)
index 0000000..dc88978
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+
+
+#ifndef _JS_TIZEN_TIMEUTIL_CONVERTER_H_
+#define _JS_TIZEN_TIMEUTIL_CONVERTER_H_
+
+#include <vector>
+#include <string>
+
+#include <CommonsJavaScript/Converter.h>
+#include <CommonsJavaScript/ScopedJSStringRef.h>
+
+#include "TZDate.h"
+#include "DurationProperties.h"
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+#include "TZDateProperties.h"
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+using namespace WrtDeviceApis::CommonsJavaScript;
+
+namespace DeviceAPI {
+namespace Time {
+
+
+class TimeUtilConverter : public Converter {
+public:
+    using Converter::toJSValueRef;
+
+public:
+    explicit TimeUtilConverter(JSContextRef context);
+    virtual  ~TimeUtilConverter();
+    short toShort(const JSValueRef& arg);
+
+    TZDateProperties getPropertiesInTZDate(JSValueRef arg);
+    TZDateProperties getPropertiesInTZDate(JSObjectRef arg);
+    JSObjectRef makeDurationObject(const DurationProperties &duration);
+    JSObjectRef makeMillisecondDurationObject(const long long length);
+    DurationPropertiesPtr getDuration(JSValueRef value);
+    DurationProperties getDurationProperties(JSValueRef value);
+    long long getDurationLength(JSValueRef value);
+    long long getDurationLength(JSObjectRef object);
+    short getDurationUnit(JSValueRef value);
+    short getDurationUnit(JSObjectRef object);
+    short toDurationUnit(std::string strUnit);
+    std::string toDurationUnitString(short unit);
+    long long convertDurationLength(DurationProperties duration, short unit);
+    double getTimeInMilliseconds(JSValueRef arg);
+    double getTimeInMilliseconds(JSObjectRef arg);
+    tm toTZDateTime(JSValueRef arg);
+    tm toTZDateTime(JSObjectRef arg);
+    JSObjectRef toJSValueRefTZDate(const double milliseconds, const std::string &timezone);
+    DurationProperties optimizedTimeDuration(DurationProperties origin);
+};
+
+} // Time
+} // DeviceAPI
+
+#endif /* _JS_TIZEN_TIMEUTIL_CONVERTER_H_ */
diff --git a/src/TimeUtil/TimeUtilTools.cpp b/src/TimeUtil/TimeUtilTools.cpp
new file mode 100755 (executable)
index 0000000..19e0db8
--- /dev/null
@@ -0,0 +1,464 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        TimeUtilTools.cpp
+*/
+
+#include <unicode/ustring.h>
+#include <unicode/udat.h>
+#include <unicode/dtptngen.h>
+#include <string.h>
+#include <vconf.h>
+#include <memory>
+#include <unistd.h>
+#include <Commons/Exception.h>
+#include <Logger.h>
+#include "TimeUtilTools.h"
+#include "JSUtil.h"
+
+using namespace DeviceAPI::Common;
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+using namespace WrtDeviceApis;
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+namespace DeviceAPI {
+namespace Time {
+
+std::string TimeUtilTools::toUTF8String(UnicodeString uniStr)
+{
+    LOGD("Entered");
+
+    int bufferLen = sizeof(UChar) * static_cast<int>(uniStr.length()) + 1;
+    char *resultBuffer = static_cast<char*>(malloc(bufferLen));
+    if (!resultBuffer) {
+        LOGE("memory allocation error");
+        throw Common::UnknownException("memory allocation error");
+    }
+    memset(resultBuffer, 0, bufferLen);
+    CheckedArrayByteSink sink(resultBuffer, bufferLen);
+    uniStr.toUTF8(sink);
+    if (sink.Overflowed()) {
+        LOGE("Converting error");
+        free(resultBuffer);
+        throw Common::UnknownException("Converting error");
+    }
+
+    std::string str(resultBuffer);
+    free(resultBuffer);
+
+    return str;
+}
+
+UnicodeString *TimeUtilTools::toUnicodeString(const std::string& str)
+{
+    LOGD("Entered");
+
+    UnicodeString *id = new UnicodeString(str.c_str());
+
+    return id;
+}
+
+int32_t TimeUtilTools::toint32_t(const long num)
+{
+    LOGD("Entered");
+
+    return static_cast<int32_t>(num);
+}
+
+long TimeUtilTools::tolong(const int32_t num)
+{
+    LOGD("Entered");
+
+    return static_cast<long>(num);
+}
+
+long long TimeUtilTools::tolonglong(const int32_t num)
+{
+    LOGD("Entered");
+
+    return static_cast<long long>(num);
+}
+
+const std::vector<std::string>& TimeUtilTools::getTimezonesArray()
+{
+    LOGD("Entered");
+
+    static bool initialized = false;
+    static std::vector <std::string> availableTimezones;
+    if (!initialized) {
+        initialized = true;
+        UErrorCode ec = U_ZERO_ERROR;
+        std::shared_ptr <StringEnumeration> tzen (TimeZone::createEnumeration());
+        const char *str = NULL;
+        int32_t count = tzen->count(ec);
+
+        if (U_SUCCESS(ec)) {
+            int i = 0;
+            do {
+                int32_t resultLen = 0;
+                str = tzen->next(&resultLen, ec);
+                if (U_SUCCESS(ec) && str != NULL) {
+                    std::string timezone = str;
+                    availableTimezones.push_back(timezone);
+                    i++;
+                }
+                else {
+                    LOGE("An error occured: %d, %s", ec, u_errorName(ec));
+                    throw Common::UnknownException("An error occured");
+                }
+            } while ((str != NULL) && (i < count));
+        }
+        else {
+            LOGE("Can't get timezones list: %d, %s", ec, u_errorName(ec));
+            throw Common::UnknownException("Can't get timezones list");
+        }
+    }
+    return availableTimezones;
+}
+
+std::string TimeUtilTools::getLocalTimeZone()
+{
+    LOGD("Entered");
+
+    UnicodeString id;
+    std::shared_ptr <TimeZone> zone (TimeZone::createDefault());
+    zone->getID(id);
+
+    std::string s_result = TimeUtilTools::toUTF8String(id);
+
+    return s_result;
+}
+
+std::string TimeUtilTools::getDefaultTimezone()
+{
+    LOGD("Entered");
+
+    enum { BUFFERSIZE = 1024 };
+    char buf[BUFFERSIZE];
+    std::string result;
+    ssize_t len = readlink("/opt/etc/localtime", buf, sizeof(buf)-1);
+    if (len != -1) {
+        buf[len] = '\0';
+    }
+    else {
+        /* handle error condition */
+        return result;
+    }
+    result = std::string(buf+20);
+
+    LOGD("tzpath = %s", result.c_str());
+    return result;
+}
+
+bool TimeUtilTools::isLeapyear(long year)
+{
+    LOGD("Entered");
+
+    if ((year % 400 == 0) or ((year % 4 == 0) and (year % 100 != 0))) {
+        return true;
+    }
+    return false;
+}
+
+bool TimeUtilTools::isInTimezonesArray(const std::string& timezone)
+{
+    LOGD("Entered");
+
+    UnicodeString *id = TimeUtilTools::toUnicodeString(timezone);
+    TimeZone *tz = TimeZone::createTimeZone(*id);
+
+    UnicodeString timezone_id;
+    tz->getID(timezone_id);
+
+    bool result = false;
+    if (TimeUtilTools::toUTF8String(timezone_id) != "Etc/Unknown")
+        result = true;
+
+    delete tz;
+    tz = NULL;
+
+    delete id;
+    id = NULL;
+
+    return result;
+}
+
+long long TimeUtilTools::getMilliseconds(JSContextRef ctx, JSValueRef value)
+{
+    LOGD("Entered");
+
+    JSObjectRef timeobj = NULL;
+    timeobj = JSUtil::JSValueToObject(ctx, value);
+    JSValueRef exception = NULL;
+    JSObjectRef getTime = NULL;
+    try {
+        getTime = JSUtil::JSValueToObject(ctx, JSUtil::getProperty(ctx, timeobj,
+                "getTime"));
+    } catch (const TypeMismatchException& err) {
+        throw TypeMismatchException("Value is not Date Object");
+    }
+
+    JSValueRef timevalue = JSObjectCallAsFunction(ctx, getTime, timeobj, 0,
+            NULL, &exception);
+    if (exception != NULL)
+        throw TypeMismatchException("Value is not Date Object");
+
+    long long millisecond = JSUtil::JSValueToLongLong(ctx, timevalue);
+    return millisecond;
+}
+
+Locale *TimeUtilTools::getDefaultLocale()
+{
+    LOGD("Entered");
+
+    char *tempstr = vconf_get_str(VCONFKEY_REGIONFORMAT);
+    if (NULL == tempstr) {
+        return NULL;
+    }
+
+    Locale *defaultLocale = NULL;
+
+    char *str_region = NULL;
+    char* p = strchr(tempstr, '.');
+    int len = strlen(tempstr) - strlen(".UTF-8");
+    if (p && len > 0) {
+        str_region = strndup(tempstr, len); //.UTF8 => 5
+        defaultLocale = new Locale(str_region);
+    }
+
+    free(tempstr);
+    free(str_region);
+
+    if (defaultLocale) {
+        if (defaultLocale->isBogus()) {
+            delete defaultLocale;
+            defaultLocale = NULL;
+        }
+    }
+
+    return defaultLocale;
+}
+
+UnicodeString TimeUtilTools::getDateTimeFormat(DateTimeFormatType type, bool bLocale)
+{
+    LOGD("Entered");
+
+    UErrorCode ec = U_ZERO_ERROR;
+    Locale *defaultLocale = getDefaultLocale();
+
+    DateTimePatternGenerator *dateTimepattern =
+        DateTimePatternGenerator::createInstance(
+        ((bLocale && defaultLocale) ? *defaultLocale : Locale::getEnglish())
+        , ec);
+
+    delete defaultLocale;
+    if (U_SUCCESS(ec)) {
+
+        UnicodeString patten;
+
+        if (DATE_FORMAT == type) {
+            patten = dateTimepattern->getBestPattern(UDAT_YEAR_MONTH_WEEKDAY_DAY, ec);
+        } else if (DATE_SHORT_FORMAT == type) {
+            patten = dateTimepattern->getBestPattern(UDAT_YEAR_NUM_MONTH_DAY, ec);
+        }
+        else {
+            int ret = 0;
+            int value = 0;
+            ret = vconf_get_int(VCONFKEY_REGIONFORMAT_TIME1224, &value);
+            // if failed, set default time format
+            if (-1 == ret) {
+                value = VCONFKEY_TIME_FORMAT_12;
+            }
+
+            std::string skeletone;
+            if (TIME_FORMAT != type) {
+                skeletone = UDAT_YEAR_MONTH_WEEKDAY_DAY;
+            }
+            if (VCONFKEY_TIME_FORMAT_12 == value) {
+                skeletone += "hhmmss";
+            } else {
+                skeletone += "HHmmss";
+            }
+
+            UnicodeString *skeletoneUniStr = toUnicodeString(skeletone);
+            patten = dateTimepattern->getBestPattern(*skeletoneUniStr, ec);
+            delete skeletoneUniStr;
+
+            if (!bLocale)
+                patten += " 'GMT'Z v'";
+        }
+
+    delete dateTimepattern;
+    return patten;
+
+    } else {
+        LOGE("Failed to create DateTimepattern: %d, %s", ec, u_errorName(ec));
+    }
+
+    delete dateTimepattern;
+    return "";
+}
+
+std::string TimeUtilTools::getDateFormat(bool shortformat)
+{
+    LOGD("Entered");
+
+    UnicodeString timeFormat =
+        TimeUtilTools::getDateTimeFormat(
+            (shortformat ?
+                    TimeUtilTools::DATE_SHORT_FORMAT :
+                    TimeUtilTools::DATE_FORMAT),
+            true);
+    timeFormat = timeFormat.findAndReplace("E", "D");
+
+    if (timeFormat.indexOf("MMM") > 0) {
+        if (timeFormat.indexOf("MMMM") > 0) {
+            timeFormat = timeFormat.findAndReplace("MMMM", "M");
+        } else {
+            timeFormat = timeFormat.findAndReplace("MMM", "M");
+        }
+    } else {
+        timeFormat = timeFormat.findAndReplace("M", "m");
+    }
+
+    int32_t i = 0;
+
+    while (i < timeFormat.length()-1) {
+        if (timeFormat[i] == timeFormat[i+1])
+            timeFormat.remove(i, 1);
+        else
+            i++;
+    }
+
+    return TimeUtilTools::toUTF8String(timeFormat);
+}
+
+std::string TimeUtilTools::getTimeFormat()
+{
+    LOGD("Entered");
+
+    UnicodeString timeFormat = TimeUtilTools::getDateTimeFormat(
+            TimeUtilTools::TIME_FORMAT, true);
+    timeFormat = timeFormat.findAndReplace("H", "h");
+    timeFormat = timeFormat.findAndReplace("K", "h");
+    timeFormat = timeFormat.findAndReplace("k", "h");
+    timeFormat = timeFormat.findAndReplace("a", "ap");
+
+    int32_t i = 0;
+
+    while (i < timeFormat.length()-1) {
+        if (timeFormat[i] == timeFormat[i+1]) {
+            timeFormat.remove(i, 1);
+        } else {
+            i++;
+        }
+    }
+    return TimeUtilTools::toUTF8String(timeFormat);
+}
+
+bool TimeUtilTools::compareTimeZoneName(const std::string& tz1, const std::string& tz2)
+{
+    LOGD("Entered");
+
+    if (tz1 != tz2) {
+        return false;
+    }
+    return true;
+}
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+
+int32_t TimeUtilTools::toint32_t(const long long num)
+{
+    LOGD("Entered");
+
+    return static_cast<int32_t>(num);
+}
+
+int32_t TimeUtilTools::toint32_t(const int num)
+{
+    LOGD("Entered");
+
+    return static_cast<int32_t>(num);
+}
+
+std::string TimeUtilTools::toString(UnicodeString uniStr)
+{
+    LOGD("Entered");
+
+    int bufferLen = sizeof(UChar)*static_cast<int>(uniStr.length()) + 1;
+    char *resultBuffer = (char *)malloc(bufferLen);
+    if (!resultBuffer) {
+        ThrowMsg(Commons::PlatformException, "memory allocation error");
+    }
+
+    memset(resultBuffer, 0, bufferLen);
+    CheckedArrayByteSink sink(resultBuffer, bufferLen);
+    uniStr.toUTF8(sink);
+    if (sink.Overflowed()) {
+        ThrowMsg(Commons::PlatformException, "Converting error");
+    }
+
+    std::string str(resultBuffer);
+    free(resultBuffer);
+    LOGD("%s", str.c_str());
+    return str;
+}
+
+TimeZone *TimeUtilTools::makeTimeZone(const std::string &name)
+{
+    LOGD("Entered,  timezone name : %s", name.c_str());
+
+    UnicodeString *id = toUnicodeString(name);
+
+    TimeZone *tz = TimeZone::createTimeZone(*id);
+    delete id;
+
+    return tz;
+}
+
+void TimeUtilTools::printDate(Calendar *cal)
+{
+    LOGD("Entered");
+
+    if (cal == NULL) {
+        return;
+    }
+
+    UErrorCode ec = U_ZERO_ERROR;
+
+    LOGI("year : %ld", tolong(cal->get(UCAL_YEAR, ec)));
+    LOGI("month : %ld", tolong(cal->get(UCAL_MONTH, ec)));
+    LOGI("day : %ld", tolong(cal->get(UCAL_DATE, ec)));
+    LOGI("hours : %ld", tolong(cal->get(UCAL_HOUR, ec)));
+    LOGI("hours of day : %ld", tolong(cal->get(UCAL_HOUR_OF_DAY, ec)));
+    LOGI("AM/PM : %ld", tolong(cal->get(UCAL_AM_PM, ec)));
+    LOGI("dayofweek : %ld", tolong(cal->get(UCAL_DAY_OF_WEEK, ec)));
+    LOGI("minues : %ld", tolong(cal->get(UCAL_MINUTE, ec)));
+    LOGI("seconds : %ld", tolong(cal->get(UCAL_SECOND, ec)));
+    LOGI("miliseconds : %ld", tolong(cal->get(UCAL_MILLISECOND, ec)));
+    LOGI("zone offset : %ld", tolong(cal->get(UCAL_ZONE_OFFSET, ec)));
+    LOGI("dst offset : %ld", tolong(cal->get(UCAL_DST_OFFSET, ec)));
+    LOGI("is leap month? : %ld", tolong(cal->get(UCAL_IS_LEAP_MONTH, ec)));
+}
+
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+} // Time
+} // DeviceAPI
diff --git a/src/TimeUtil/TimeUtilTools.h b/src/TimeUtil/TimeUtilTools.h
new file mode 100755 (executable)
index 0000000..d2ece17
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+* @file        TimeUtilTools.h
+*/
+
+#ifndef _TIMEUTILTOOLS_H_
+#define _TIMEUTILTOOLS_H_
+
+#include <unicode/unistr.h>
+#include <unicode/timezone.h>
+#include <unicode/calendar.h>
+#include <unicode/udat.h>
+#include <unicode/dtptngen.h>
+#include <string.h>
+#include <vconf.h>
+#include <memory>
+#include <ctime>
+#include <vector>
+#include <string>
+#include <PlatformException.h>
+#include <ArgumentValidator.h>
+
+namespace DeviceAPI {
+namespace Time {
+/**
+ * Contains function which are useful for TZDate and TimeUtil modules
+ */
+class TimeUtilTools
+{
+public:
+    enum DateTimeFormatType
+    {
+        TIME_FORMAT,
+        DATE_FORMAT,
+        DATE_SHORT_FORMAT,
+        DATETIME_FORMAT
+    };
+    static std::string toUTF8String(UnicodeString uniStr);
+    static UnicodeString* toUnicodeString(const std::string& str);
+    static long tolong(const int32_t num);
+    static long long tolonglong(const int32_t num);
+    static int32_t toint32_t(const long num);
+    static const std::vector<std::string>& getTimezonesArray();
+    static std::string getLocalTimeZone();
+    static std::string getDefaultTimezone();
+    static bool isLeapyear(long year);
+    static bool isInTimezonesArray(const std::string& timezone);
+    static long long getMilliseconds(JSContextRef ctx, JSValueRef value);
+    static UnicodeString getDateTimeFormat(DateTimeFormatType type, bool bLocale);
+    static Locale* getDefaultLocale();
+    static std::string getDateFormat(bool shortformat);
+    static std::string getTimeFormat();
+    static bool compareTimeZoneName(const std::string& tz1, const std::string& tz2);
+
+#ifdef IMPL_BACKWARD_COMPATIBLE
+    static int32_t toint32_t(const long long num);
+    static int32_t toint32_t(const int num);
+
+    static std::string toString(UnicodeString uniStr);
+
+    static TimeZone *makeTimeZone(const std::string &name);
+    static void printDate(icu::Calendar *cal);
+
+#endif // IMPL_BACKWARD_COMPATIBLE
+
+};
+
+} // Time
+} // DeviceAPI
+
+#endif /* _TIMEUTILTOOLS_H_ */
diff --git a/src/TimeUtil/config.xml b/src/TimeUtil/config.xml
new file mode 100755 (executable)
index 0000000..3120277
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-timeutil.so</library-name>
+    <feature-install-uri>time.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/time</name>
+        <device-capability>time</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/TimeUtil/plugin_config_impl.h b/src/TimeUtil/plugin_config_impl.h
new file mode 100755 (executable)
index 0000000..b81e695
--- /dev/null
@@ -0,0 +1,26 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2014 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIMEUTIL_PLUGIN_CONFIG_IMPL_H__
+#define __TIZEN_TIMEUTIL_PLUGIN_CONFIG_IMPL_H__
+
+//Names used in PLUGIN_CLASS_MAP (plugin_initializer.cpp) for classes and interfaces:
+#define TIZEN_TIME_TIME_UTIL_CLASS "time"
+#define TIZEN_TIME_TZDATE_INTERFACE "TZDate"
+#define TIZEN_TIME_TIME_DURATION_INTERFACE "TimeDuration"
+
+#endif // __TIZEN_TIMEUTIL_PLUGIN_CONFIG_IMPL_H__
diff --git a/src/TimeUtil/plugin_initializer.cpp b/src/TimeUtil/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..28d3e76
--- /dev/null
@@ -0,0 +1,104 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <GlobalContextManager.h>
+
+#include <Logger.h>
+#include "JSTimeDuration.h"
+#include "JSTimeUtil.h"
+#include "JSTZDate.h"
+#include "plugin_config_impl.h"
+
+namespace DeviceAPI {
+namespace Time {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+class_definition_options_t ConstructorClassOptions =
+{
+    JS_INTERFACE,
+    CREATE_INSTANCE,
+    NONE_NOTICE,
+    USE_OVERLAYED, //ignored
+    NULL,
+    NULL,
+    NULL
+};
+
+void on_widget_start_callback(int widgetId)
+{
+    LOGD("[TIZEN\\TimeUtil] on_widget_start_callback ( %d )", widgetId);
+    try {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    }
+    catch (...) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LOGD("[TIZEN\\TimeUtil] on_widget_stop_callback ( %d )", widgetId);
+    std::string name = "TimeUtil";
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    }
+    catch (...) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\TimeUtil] on_frame_load_callback ( %p )", context);
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\TimeUtil] on_frame_unload_callback ( %p )", context);
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_TIME_TIME_UTIL_CLASS,
+        (js_class_template_getter)JSTimeUtil::getClassRef,
+        NULL)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_TIME_TZDATE_INTERFACE,
+        (js_class_template_getter)JSTZDate::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSTZDate::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(WRT_JS_EXTENSION_OBJECT_TIZEN,
+        TIZEN_TIME_TIME_DURATION_INTERFACE,
+        (js_class_template_getter)JSTimeDuration::getClassRef,
+        reinterpret_cast<js_class_constructor_cb_t>(JSTimeDuration::constructor),
+        &ConstructorClassOptions)
+PLUGIN_CLASS_MAP_END
+
+} // Time
+} // DeviceAPI
diff --git a/src/Tizen/AbstractFilter.cpp b/src/Tizen/AbstractFilter.cpp
new file mode 100644 (file)
index 0000000..ae3a360
--- /dev/null
@@ -0,0 +1,260 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AbstractFilter.h"
+#include "JSAttributeFilter.h"
+#include "JSAttributeRangeFilter.h"
+#include "JSCompositeFilter.h"
+#include <PlatformException.h>
+#include <Logger.h>
+#include <JSUtil.h>
+#include <algorithm>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+using namespace Common;
+
+AbstractFilter::AbstractFilter(FilterType filter_type) :
+        m_filter_type(filter_type)
+{
+}
+
+AbstractFilter::~AbstractFilter()
+{
+}
+
+FilterType AbstractFilter::getFilterType() const
+{
+    return m_filter_type;
+}
+
+JSValueRef AbstractFilter::makeJSValue(JSContextRef context,
+        AbstractFilterPtr native)
+{
+    LOGD("Entered");
+
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    switch (native->getFilterType()) {
+        case ATTRIBUTE_FILTER:
+            return JSAttributeFilter::makeJSObject(context, native);
+        case ATTRIBUTE_RANGE_FILTER:
+            return JSAttributeRangeFilter::makeJSObject(context, native);
+        case COMPOSITE_FILTER:
+            return JSCompositeFilter::makeJSObject(context, native);
+        default:
+            LOGE("Unsupported filter type");
+            throw UnknownException("Unsupported filter type");
+    }
+}
+
+AbstractFilterPtr AbstractFilter::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+
+    if (!JSValueIsObjectOfClass(context, value, JSAttributeFilter::getClassRef()) &&
+        !JSValueIsObjectOfClass(context, value, JSAttributeRangeFilter::getClassRef()) &&
+        !JSValueIsObjectOfClass(context, value, JSCompositeFilter::getClassRef())) {
+        LOGE("JSObjectRef:%p - Object type is not JSAttributeFilter, "
+                "JSAttributeRangeFilter nor JSCompositeFilter", object);
+        throw TypeMismatchException("Object type is not valid filter");
+    }
+
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+
+bool AbstractFilter::isMatching(const FilterableObject* const tested_object) const
+{
+    LOGE("Calling isMatching on AbstractFilter!");
+    throw UnknownException("Method not supported");
+}
+
+AttributeFilterPtr castToAttributeFilter(AbstractFilterPtr from)
+{
+    if(ATTRIBUTE_FILTER != from->getFilterType()) {
+        LOGE("Trying to get AttributeFilterPtr but filter's type is: %d",
+                from->getFilterType());
+        return AttributeFilterPtr();
+    }
+
+    return std::dynamic_pointer_cast<AttributeFilter>(from);
+}
+
+AttributeRangeFilterPtr castToAttributeRangeFilter(AbstractFilterPtr from)
+{
+    if(ATTRIBUTE_RANGE_FILTER != from->getFilterType()) {
+        LOGE("Trying to get AttributeRangeFilterPtr but filter's type is: %d",
+                from->getFilterType());
+        return AttributeRangeFilterPtr();
+    }
+
+    return std::dynamic_pointer_cast<AttributeRangeFilter>(from);
+}
+
+CompositeFilterPtr castToCompositeFilter(AbstractFilterPtr from)
+{
+    if(COMPOSITE_FILTER != from->getFilterType()) {
+        LOGE("Trying to get CompositeFilterPtr but filter's type is: %d",
+                from->getFilterType());
+        return CompositeFilterPtr();
+    }
+
+    return std::dynamic_pointer_cast<CompositeFilter>(from);
+}
+
+namespace {
+
+inline std::string convertToLowerCase(const std::string& input_string)
+{
+    std::string output_string = input_string;
+    std::transform(output_string.begin(), output_string.end(), output_string.begin(),
+            ::tolower);
+    return output_string;
+}
+
+} // Anonymous namespace
+
+bool FilterUtils::isStringMatching(const std::string& key,
+        const std::string& value,
+        Tizen::FilterMatchFlag flag)
+{
+    switch(flag)
+    {
+        case Tizen::ENDSWITH: {
+            if (key.empty()) {
+                return false;
+            }
+            if (key.size() > value.size()) {
+                return false;
+            }
+            std::string lvalue = convertToLowerCase(value);
+            std::string lkey = convertToLowerCase(key);
+            return lvalue.substr(lvalue.size() - lkey.size(), lkey.size()) == lkey;
+        }
+
+        case Tizen::EXACTLY: {
+            return key == value;
+        }
+
+        case Tizen::STARTSWITH: {
+            if (key.empty()) {
+                return false;
+            }
+            if (key.size() > value.size()) {
+                return false;
+            }
+            std::string lvalue = convertToLowerCase(value);
+            std::string lkey = convertToLowerCase(key);
+            return lvalue.substr(0, lkey.size()) == lkey;
+        }
+
+        case Tizen::CONTAINS: {
+            if (key.empty()) {
+                return false;
+            }
+            if (key.size() > value.size()) {
+                return false;
+            }
+            std::string lvalue = convertToLowerCase(value);
+            std::string lkey = convertToLowerCase(key);
+            return lvalue.find(lkey) != std::string::npos;
+        }
+
+        default: {
+            LOGE("Unknown match flag");
+            return false;
+        }
+    }
+}
+
+bool FilterUtils::isAnyStringMatching(const std::string& key,
+        const std::vector<std::string>& values,
+        Tizen::FilterMatchFlag flag)
+{
+    for(auto it = values.begin(); it != values.end(); ++it) {
+        if(isStringMatching(key,*it,flag)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+bool FilterUtils::isTimeStampInRange(const time_t& time_stamp,
+        Tizen::AnyPtr& initial_value,
+        Tizen::AnyPtr& end_value)
+{
+    time_t from_time = 0;
+    time_t to_time = 0;
+
+    bool initial_is_valid_time_value = false;
+    if (initial_value && !initial_value->isNullOrUndefined()) {
+        try {
+            struct tm ftime = *initial_value->toDateTm();
+            from_time = mktime(&ftime);
+            initial_is_valid_time_value = true;
+        }
+        catch(...) {
+            LOGE("Unknown exception occured during execution of Any::toDateTm()");
+        }
+    }
+    if(!initial_is_valid_time_value) {
+        LOGE("initialValue is not Time!");
+        throw InvalidValuesException("initialValue is not Time!");
+    }
+
+    bool end_is_valid_time_value = false;
+    if (end_value && !end_value->isNullOrUndefined()) {
+        try {
+            struct tm ttime = *end_value->toDateTm();
+            to_time = mktime(&ttime);
+            end_is_valid_time_value = true;
+        }
+        catch(...) {
+            LOGE("Unknown exception occured during execution of Any::toDateTm()");
+        }
+    }
+    if(end_is_valid_time_value) {
+        LOGE("endValue is not Time!");
+        throw InvalidValuesException("endValue is not Time!");
+    }
+
+    bool is_in_range = FilterUtils::isBetweenTimeRange(time_stamp, from_time, to_time);
+
+    LOGD("%d is%s in time range <%d, %d>", time_stamp, (is_in_range ? "" : " NOT"),
+            from_time, to_time);
+
+    return is_in_range;
+}
+
+} //Tizen
+} //DeviceAPI
diff --git a/src/Tizen/AbstractFilter.h b/src/Tizen/AbstractFilter.h
new file mode 100644 (file)
index 0000000..f3d8a06
--- /dev/null
@@ -0,0 +1,160 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_ABSTRACT_FILTER_H__
+#define __TIZEN_TIZEN_ABSTRACT_FILTER_H__
+
+#include <memory>
+#include <vector>
+#include <sstream>
+#include <JSArray.h>
+
+#include "Any.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class AttributeFilter;
+typedef std::shared_ptr<AttributeFilter> AttributeFilterPtr;
+
+class AttributeRangeFilter;
+typedef std::shared_ptr<AttributeRangeFilter> AttributeRangeFilterPtr;
+
+class CompositeFilter;
+typedef std::shared_ptr<CompositeFilter> CompositeFilterPtr;
+
+class AbstractFilter;
+typedef std::shared_ptr<AbstractFilter> AbstractFilterPtr;
+typedef std::vector<AbstractFilterPtr> AbstractFilterPtrVector;
+
+struct AbstractFilterHolder {
+    AbstractFilterPtr ptr;
+};
+
+enum FilterType {
+    ABSTRACT_FILTER = 0,
+    ATTRIBUTE_FILTER,
+    ATTRIBUTE_RANGE_FILTER,
+    COMPOSITE_FILTER
+};
+
+enum FilterMatchFlag {
+    EXACTLY = 0,
+    FULLSTRING,
+    CONTAINS,
+    STARTSWITH,
+    ENDSWITH,
+    EXISTS
+};
+
+class FilterableObject {
+public:
+    virtual ~FilterableObject(){}
+
+    virtual bool isMatchingAttribute(const std::string& attribute_name,
+            const FilterMatchFlag match_flag,
+            AnyPtr match_value) const = 0;
+
+    virtual bool isMatchingAttributeRange(const std::string& attribute_name,
+            AnyPtr initial_value,
+            AnyPtr end_value) const = 0;
+};
+
+class AbstractFilter {
+public:
+    AbstractFilter(FilterType type = ABSTRACT_FILTER);
+    virtual ~AbstractFilter();
+
+    FilterType getFilterType() const;
+
+    static JSValueRef makeJSValue(JSContextRef context, AbstractFilterPtr priv);
+    static AbstractFilterPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    virtual bool isMatching(const FilterableObject* const filtered_object) const;
+
+protected:
+    FilterType m_filter_type;
+};
+
+/**
+ * Returns NULL shared_ptr if cast is not possible (incorrect type)
+ */
+AttributeFilterPtr castToAttributeFilter(AbstractFilterPtr from);
+AttributeRangeFilterPtr castToAttributeRangeFilter(AbstractFilterPtr from);
+CompositeFilterPtr castToCompositeFilter(AbstractFilterPtr from);
+
+
+class JSFilterArray : public Common::JSArray<AbstractFilterPtr> {
+public:
+    JSFilterArray(JSContextRef ctx, JSObjectRef array):
+            JSArray<AbstractFilterPtr>(ctx, array, AbstractFilter::getPrivateObject,
+                    AbstractFilter::makeJSValue)
+    {
+    }
+    JSFilterArray(JSContextRef ctx):
+            JSArray<AbstractFilterPtr>(ctx, AbstractFilter::getPrivateObject,
+                    AbstractFilter::makeJSValue)
+    {
+    }
+    void operator=(const std::vector<AbstractFilterPtr>& list)
+    {
+        overwrite(list);
+    }
+};
+
+
+
+class FilterUtils {
+public:
+    static bool isStringMatching(const std::string& key,
+            const std::string& value,
+            Tizen::FilterMatchFlag flag);
+    static bool isAnyStringMatching(const std::string& key,
+            const std::vector<std::string>& values,
+            Tizen::FilterMatchFlag flag);
+    static bool isTimeStampInRange(const time_t& time_stamp,
+            Tizen::AnyPtr& initial_value,
+            Tizen::AnyPtr& end_value);
+
+    static inline bool isBetweenTimeRange(const time_t current,
+            const time_t from,
+            const time_t to)
+    {
+        return ((current - from) >= 0 ) && ((to - current) >= 0);
+    }
+
+    static inline std::string boolToString(const bool src)
+    {
+        if(src) {
+            return "true";
+        }
+        else {
+            return "false";
+        }
+    }
+};
+
+} // Tizen
+} // DeviceAPI
+
+
+#include "AttributeFilter.h"
+#include "AttributeRangeFilter.h"
+#include "CompositeFilter.h"
+
+#endif // __TIZEN_TIZEN_ABSTRACT_FILTER_H__
diff --git a/src/Tizen/Any.cpp b/src/Tizen/Any.cpp
new file mode 100644 (file)
index 0000000..55143bc
--- /dev/null
@@ -0,0 +1,106 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "Any.h"
+#include <JSUtil.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+Any::Any(JSContextRef context, JSValueRef value) :
+        m_context(context),
+        m_value(value)
+{
+    JSValueProtect(m_context, m_value);
+}
+
+Any::~Any()
+{
+    JSValueUnprotect(m_context, m_value);
+}
+
+JSContextRef Any::getContext() const
+{
+    return m_context;
+}
+
+JSValueRef Any::getValue() const
+{
+    return m_value;
+}
+
+void Any::setValue(JSContextRef context, JSValueRef value)
+{
+    JSValueUnprotect(m_context, m_value);
+    m_context = context;
+    m_value = value;
+    JSValueProtect(m_context, m_value);
+}
+
+bool Any::isNullOrUndefined() const
+{
+    return JSValueIsUndefined(m_context, m_value) || JSValueIsNull(m_context, m_value);
+}
+
+bool Any::toBool() const
+{
+    return Common::JSUtil::JSValueToBoolean(m_context, m_value);
+}
+
+long Any::toLong() const
+{
+    return Common::JSUtil::JSValueToLong(m_context, m_value);
+}
+
+unsigned long Any::toULong() const
+{
+    return Common::JSUtil::JSValueToULong(m_context, m_value);
+}
+
+long long Any::toLongLong() const
+{
+    return Common::JSUtil::JSValueToLongLong(m_context, m_value);
+}
+
+unsigned long long Any::toULongLong() const
+{
+    return Common::JSUtil::JSValueToULongLong(m_context, m_value);
+}
+
+double Any::toDouble() const
+{
+    return Common::JSUtil::JSValueToDouble(m_context, m_value);
+}
+
+std::string Any::toString() const
+{
+    return Common::JSUtil::JSValueToString(m_context, m_value);
+}
+
+std::tm* Any::toDateTm() const
+{
+    std::time_t time = Common::JSUtil::JSValueToTimeT(m_context, m_value);
+    return gmtime(&time);
+}
+
+std::time_t Any::toTimeT() const
+{
+    return Common::JSUtil::JSValueToTimeT(m_context, m_value);
+}
+
+} // Tizen
+} // Device_API
diff --git a/src/Tizen/Any.h b/src/Tizen/Any.h
new file mode 100644 (file)
index 0000000..f2826ed
--- /dev/null
@@ -0,0 +1,76 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_ANY_H__
+#define __TIZEN_TIZEN_ANY_H__
+
+#include <memory>
+#include <JavaScriptCore/JavaScript.h>
+#include <string>
+#include <ctime>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+enum PrimitiveType {
+    PrimitiveType_NoType,
+    PrimitiveType_Null,
+    PrimitiveType_Boolean,
+    PrimitiveType_Long,
+    PrimitiveType_ULong,
+    PrimitiveType_LongLong,
+    PrimitiveType_ULongLong,
+    PrimitiveType_Double,
+    PrimitiveType_String,
+    PrimitiveType_Time,
+    PrimitiveType_Object,
+    PrimitiveType_PlatformObject
+};
+
+class Any;
+typedef std::shared_ptr<Any> AnyPtr;
+
+class Any {
+public:
+    Any(JSContextRef context, JSValueRef value);
+    virtual ~Any();
+
+    JSContextRef getContext() const;
+    JSValueRef getValue() const;
+    void setValue(JSContextRef context, JSValueRef value);
+
+    bool isNullOrUndefined() const;
+
+    bool toBool() const;
+    long toLong() const;
+    unsigned long toULong() const;
+    long long toLongLong() const;
+    unsigned long long toULongLong() const;
+    double toDouble() const;
+    std::string toString() const;
+    std::tm* toDateTm() const;
+    std::time_t toTimeT() const;
+
+private:
+    JSContextRef m_context;
+    JSValueRef m_value;
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_ANY_H__
diff --git a/src/Tizen/AttributeFilter.cpp b/src/Tizen/AttributeFilter.cpp
new file mode 100644 (file)
index 0000000..4bc2680
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AttributeFilter.h"
+#include <PlatformException.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+AttributeFilter::AttributeFilter(const std::string &attribute_name) :
+        AbstractFilter(ATTRIBUTE_FILTER),
+        m_attribute_name(attribute_name),
+        m_match_flag(EXACTLY)
+{
+}
+
+AttributeFilter::~AttributeFilter()
+{
+}
+
+std::string AttributeFilter::getAttributeName() const
+{
+    return m_attribute_name;
+}
+
+void AttributeFilter::setAttributeName(const std::string &attribute_name)
+{
+    m_attribute_name = attribute_name;
+}
+
+FilterMatchFlag AttributeFilter::getMatchFlag() const
+{
+    return m_match_flag;
+}
+
+void AttributeFilter::setMatchFlag(FilterMatchFlag match_flag)
+{
+    m_match_flag = match_flag;
+}
+
+AnyPtr AttributeFilter::getMatchValue() const
+{
+    return m_match_value;
+}
+
+void AttributeFilter::setMatchValue(AnyPtr match_value)
+{
+    m_match_value = match_value;
+}
+
+bool AttributeFilter::isMatching(const FilterableObject* const filtered_object) const
+{
+    if(!filtered_object) {
+        LOGE("Invalid object: NULL!");
+        throw Common::InvalidValuesException("Invalid object");
+    }
+
+    return filtered_object->isMatchingAttribute(m_attribute_name, m_match_flag,
+            m_match_value);
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/AttributeFilter.h b/src/Tizen/AttributeFilter.h
new file mode 100644 (file)
index 0000000..6d42434
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_ATTRIBUTE_FILTER_H__
+#define __TIZEN_TIZEN_ATTRIBUTE_FILTER_H__
+
+#include "AbstractFilter.h"
+#include "Any.h"
+#include <string>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class AttributeFilter;
+typedef std::shared_ptr<AttributeFilter> AttributeFilterPtr;
+
+class AttributeFilter: public AbstractFilter {
+public:
+    AttributeFilter(const std::string &attribute_name);
+    virtual ~AttributeFilter();
+
+    std::string getAttributeName() const;
+    void setAttributeName(const std::string &attribute_name);
+    FilterMatchFlag getMatchFlag() const;
+    void setMatchFlag(FilterMatchFlag match_flag);
+    AnyPtr getMatchValue() const;
+    void setMatchValue(AnyPtr match_value);
+
+    virtual bool isMatching(const FilterableObject* const filtered_object) const;
+private:
+    std::string m_attribute_name;
+    FilterMatchFlag m_match_flag;
+    AnyPtr m_match_value;
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_ABSTRACT_FILTER_H__
diff --git a/src/Tizen/AttributeRangeFilter.cpp b/src/Tizen/AttributeRangeFilter.cpp
new file mode 100644 (file)
index 0000000..798de87
--- /dev/null
@@ -0,0 +1,78 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "AttributeRangeFilter.h"
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+AttributeRangeFilter::AttributeRangeFilter(const std::string &attribute_name) :
+        m_attribute_name(attribute_name)
+{
+    m_filter_type = ATTRIBUTE_RANGE_FILTER;
+}
+
+AttributeRangeFilter::~AttributeRangeFilter()
+{
+
+}
+
+std::string AttributeRangeFilter::getAttributeName() const
+{
+    return m_attribute_name;
+}
+
+void AttributeRangeFilter::setAttributeName(const std::string &attribute_name)
+{
+    m_attribute_name = attribute_name;
+}
+
+
+AnyPtr AttributeRangeFilter::getInitialValue() const
+{
+    return m_initial_value;
+}
+
+void AttributeRangeFilter::setInitialValue(AnyPtr initial_value)
+{
+    m_initial_value = initial_value;
+}
+
+AnyPtr AttributeRangeFilter::getEndValue() const
+{
+    return m_end_value;
+}
+
+void AttributeRangeFilter::setEndValue(AnyPtr end_value)
+{
+    m_end_value = end_value;
+}
+
+bool AttributeRangeFilter::isMatching(const FilterableObject* const filtered_object) const
+{
+    if(!filtered_object) {
+        LOGE("Invalid object: NULL!");
+        throw Common::InvalidValuesException("Invalid object");
+    }
+
+    return filtered_object->isMatchingAttributeRange(m_attribute_name, m_initial_value,
+            m_end_value);
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/AttributeRangeFilter.h b/src/Tizen/AttributeRangeFilter.h
new file mode 100644 (file)
index 0000000..f49421f
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_ATTRIBUTE_RANGE_FILTER_H__
+#define __TIZEN_TIZEN_ATTRIBUTE_RANGE_FILTER_H__
+
+#include "AbstractFilter.h"
+#include "Any.h"
+#include <string>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class AttributeRangeFilter;
+typedef std::shared_ptr<AttributeRangeFilter> AttributeRangeFilterPtr;
+
+class AttributeRangeFilter: public AbstractFilter {
+public:
+    AttributeRangeFilter(const std::string &attribute_name);
+    virtual ~AttributeRangeFilter();
+
+    std::string getAttributeName() const;
+    void setAttributeName(const std::string &attribute_name);
+
+    AnyPtr getInitialValue() const;
+    void setInitialValue(AnyPtr initial_value);
+
+    AnyPtr getEndValue() const;
+    void setEndValue(AnyPtr end_value);
+
+    virtual bool isMatching(const FilterableObject* const filtered_object) const;
+private:
+    std::string m_attribute_name;
+    AnyPtr m_initial_value;
+    AnyPtr m_end_value;
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_ATTRIBUTE_RANGE_FILTER_H__
diff --git a/src/Tizen/CMakeLists.txt b/src/Tizen/CMakeLists.txt
new file mode 100644 (file)
index 0000000..aa1e49f
--- /dev/null
@@ -0,0 +1,70 @@
+SET(TARGET_NAME ${tizen_target})
+SET(DESTINATION_NAME ${tizen_dest})
+SET(TARGET_IMPL_NAME ${tizen_impl})
+SET(TARGET_CONFIG_NAME ${tizen_config})
+
+PKG_CHECK_MODULES(platform_pkgs_tizen REQUIRED wrt-plugins-plugin-manager)
+
+INCLUDE_DIRECTORIES(
+    ${TOP}/Common
+    ${platform_pkgs_tizen_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+    ${CMAKE_INSTALL_RPATH}
+    ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSTizen.cpp
+    PluginPriv.cpp
+    Any.cpp
+    AbstractFilter.cpp
+    JSAttributeFilter.cpp
+    AttributeFilter.cpp
+    JSAttributeRangeFilter.cpp
+    AttributeRangeFilter.cpp
+    JSCompositeFilter.cpp
+    CompositeFilter.cpp
+    JSSortMode.cpp
+    SortMode.cpp
+    JSSimpleCoordinates.cpp
+    SimpleCoordinates.cpp
+    FilterIterator.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+    ${LIBS_COMMON}
+    ${LIBS_WIDGETDB}
+    ${platform_pkgs_tizen_LIBRARIES}
+)
+
+SET(SRCS_CONFIG
+    plugin_config.cpp
+)
+
+ADD_LIBRARY(${TARGET_CONFIG_NAME} SHARED ${SRCS_CONFIG})
+
+TARGET_LINK_LIBRARIES(${TARGET_CONFIG_NAME}
+    ${LIBS_COMMON}
+)
+
+SET(SRCS
+    plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+    ${TARGET_IMPL_NAME}
+    ${TARGET_CONFIG_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_CONFIG_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+    DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/tizen
+    FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/Tizen/CompositeFilter.cpp b/src/Tizen/CompositeFilter.cpp
new file mode 100644 (file)
index 0000000..9270a66
--- /dev/null
@@ -0,0 +1,132 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        CompositeFilter.cpp
+ */
+
+#include "CompositeFilter.h"
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+#include <Logger.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+CompositeFilter::CompositeFilter(CompositeFilterType type):
+        AbstractFilter(COMPOSITE_FILTER),
+        m_type(type),
+        m_context(NULL)
+{
+}
+
+CompositeFilter::~CompositeFilter()
+{
+}
+
+CompositeFilterType CompositeFilter::getType() const
+{
+    return m_type;
+}
+
+void CompositeFilter::setType(CompositeFilterType type)
+{
+    m_type = type;
+}
+
+JSContextRef CompositeFilter::getContext() const
+{
+    return m_context;
+}
+
+const AbstractFilterPtrVector& CompositeFilter::getFilters() const
+{
+    return m_filters;
+}
+
+void CompositeFilter::setFilters(const AbstractFilterPtrVector &filters)
+{
+    if (Common::GlobalContextManager::getInstance()->isAliveGlobalContext(
+            m_context) && m_js_filters) {
+        *m_js_filters = filters;
+    }
+    m_filters = filters;
+}
+
+JSFilterArray CompositeFilter::getJSFilters(JSContextRef global_ctx)
+{
+    if (!m_context && !global_ctx) {
+        LOGE("Context is not set");
+        throw Common::UnknownException("Context is not set");
+    }
+    else if (!m_context && global_ctx) {
+        m_context = global_ctx;
+    }
+
+    if (!Common::GlobalContextManager::getInstance()->isAliveGlobalContext(
+            m_context)) {
+        LOGE("Context is not alive");
+        throw Common::UnknownException("Context is not alive");
+    }
+    else if (!m_js_filters) {
+        m_js_filters = std::shared_ptr<JSFilterArray>(new JSFilterArray(
+                m_context));
+        *m_js_filters = m_filters;
+        m_filters.clear();
+    }
+    return *m_js_filters;
+}
+
+
+bool CompositeFilter::isMatching(const FilterableObject* const filtered_object) const
+{
+    if(!filtered_object) {
+        LOGE("Invalid object: NULL!");
+        throw Common::InvalidValuesException("Invalid object");
+    }
+
+    bool composite_result = false;
+
+    const AbstractFilterPtrVector src_filters = getFilters();
+    if(src_filters.empty()) {
+        //No filters present -> object match composite filter
+        composite_result = true;
+    }
+    else {
+        AbstractFilterPtrVector::const_iterator it = src_filters.begin();
+        AbstractFilterPtrVector::const_iterator end_it = src_filters.end();
+        for(;it != end_it; it++) {
+
+            const bool last_result = (*it)->isMatching(filtered_object);
+            if(INTERSECTION == m_type) {
+                composite_result = last_result;
+                if(!last_result) {  //First false result causes whole composite
+                    break;                  //filter to be false -> object does not match
+                }
+            } else if(UNION == m_type && last_result) { //First true result causes
+                composite_result = true;                    //composite filter to be
+                break;                                      //true -> object match
+            }
+        }
+    }
+
+    return composite_result;
+}
+
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/CompositeFilter.h b/src/Tizen/CompositeFilter.h
new file mode 100644 (file)
index 0000000..aa76392
--- /dev/null
@@ -0,0 +1,63 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+/**
+ * @file        CompositeFilter.h
+ */
+
+#ifndef __TIZEN_TIZEN_COMPOSITE_FILTER_H__
+#define __TIZEN_TIZEN_COMPOSITE_FILTER_H__
+
+#include "AbstractFilter.h"
+#include <JSArray.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+enum CompositeFilterType {
+    UNION,
+    INTERSECTION
+};
+
+class CompositeFilter;
+typedef std::shared_ptr<CompositeFilter> CompositeFilterPtr;
+
+class CompositeFilter: public AbstractFilter {
+public:
+    CompositeFilter(CompositeFilterType type);
+    virtual ~CompositeFilter();
+
+    CompositeFilterType getType() const;
+    void setType(CompositeFilterType type);
+    const AbstractFilterPtrVector& getFilters() const;
+    void setFilters(const AbstractFilterPtrVector &filter);
+    JSFilterArray getJSFilters(JSContextRef ctx);
+    JSContextRef getContext() const;
+
+    virtual bool isMatching(const FilterableObject* const filtered_object) const;
+private:
+    CompositeFilterType m_type;
+    AbstractFilterPtrVector m_filters;
+    JSContextRef m_context;
+    std::shared_ptr<JSFilterArray> m_js_filters;
+
+};
+
+} //Tizen
+} //DeviceAPI
+
+#endif // __TIZEN_TIZEN_COMPOSITE_FILTER_H__
diff --git a/src/Tizen/FilterIterator.cpp b/src/Tizen/FilterIterator.cpp
new file mode 100644 (file)
index 0000000..39387c6
--- /dev/null
@@ -0,0 +1,179 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "FilterIterator.h"
+#include "PlatformException.h"
+#include <Logger.h>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI {
+namespace Tizen {
+
+FilterIterator::FilterIterator(AbstractFilterPtr filter) :
+        m_root_filter(filter),
+        m_current_state(FIS_NOT_VALID)
+{
+    if(!m_root_filter) {
+        LOGE("Cannot create FilterIterator for NULL filter");
+        throw UnknownException("filter is NULL");
+    }
+
+    goToNext(m_root_filter);
+}
+
+FilterIteratorState FilterIterator::getState() const
+{
+    return m_current_state;
+}
+
+AbstractFilterPtr FilterIterator::operator*() const
+{
+    return m_current_filter;
+}
+
+AbstractFilterPtr FilterIterator::getCurrentFilter() const
+{
+    return m_current_filter;
+}
+
+bool FilterIterator::isEnd() const
+{
+    return FIS_END == m_current_state;
+}
+
+bool FilterIterator::isInsideCompositeFilter() const
+{
+    return !m_composite_stack.empty();
+}
+
+CompositeFilterPtr FilterIterator::getCurrentCompositeFilter() const
+{
+    if(m_composite_stack.empty()) {
+        return CompositeFilterPtr();
+    }
+
+    return m_composite_stack.top().filter;
+}
+
+int FilterIterator::getCurrentCompositeSubFilterIndex() const
+{
+    if(!isInsideCompositeFilter()) {
+        return 0;
+    }
+
+    return m_composite_stack.top().cur_sub_filter_index;
+}
+
+bool FilterIterator::isLastCompositeSubFilter() const
+{
+    if(!isInsideCompositeFilter()) {
+        return false;
+    }
+
+    CompositeIterState cfilter = m_composite_stack.top();
+    return (cfilter.filter->getFilters().size() - 1) == cfilter.cur_sub_filter_index;
+}
+
+void FilterIterator::operator++(int)
+{
+    this->operator++();
+}
+
+void FilterIterator::operator++()
+{
+    if(FIS_ATTRIBUTE_FILTER == m_current_state ||
+            FIS_ATTRIBUTE_RANGE_FILTER == m_current_state) {
+
+        if(m_composite_stack.empty()) {
+            //We are not inside composite filter iteration -> reached THE END
+            setReachedEnd();
+        } else {
+            //We are inside a composite filter -> try move to next sub filter
+            goToNextInCurCompositeFilter();
+        }
+    }
+    else if(FIS_COMPOSITE_START == m_current_state) {
+        goToNextInCurCompositeFilter();
+    }
+    else if(FIS_COMPOSITE_END == m_current_state) {
+        m_composite_stack.pop();
+        if(m_composite_stack.empty()) {
+            //There is no parent composite filter -> reached THE END
+            setReachedEnd();
+        }
+        else {
+            //There is parent composite filter -> go back and try move to next sub filter
+            goToNextInCurCompositeFilter();
+        }
+    }
+    else if(FIS_NOT_VALID == m_current_state) {
+        //There is nothing to do -> reached THE END
+        setReachedEnd();
+    }
+}
+
+void FilterIterator::goToNextInCurCompositeFilter()
+{
+    CompositeIterState& cur_cs = m_composite_stack.top();
+    AbstractFilterPtrVector sub_filters = cur_cs.filter->getFilters();
+    const size_t next_filter_index = cur_cs.cur_sub_filter_index + 1;
+    if(next_filter_index >= sub_filters.size()) {
+        //Reached last item of composite filter
+        m_current_filter = cur_cs.filter;
+        m_current_state = FIS_COMPOSITE_END;
+    }
+    else {
+        cur_cs.cur_sub_filter_index = next_filter_index;
+        //There is next item inside this composite filter
+        goToNext(sub_filters[next_filter_index]);
+    }
+}
+
+void FilterIterator::setReachedEnd()
+{
+    m_current_state = FIS_END;
+    m_current_filter = AbstractFilterPtr();
+}
+
+void FilterIterator::goToNext(AbstractFilterPtr next)
+{
+    switch(next->getFilterType()) {
+        case ATTRIBUTE_FILTER: {
+            m_current_state = FIS_ATTRIBUTE_FILTER;
+        } break;
+        case ATTRIBUTE_RANGE_FILTER: {
+            m_current_state = FIS_ATTRIBUTE_RANGE_FILTER;
+        } break;
+        case COMPOSITE_FILTER: {
+            m_current_state = FIS_COMPOSITE_START;
+            CompositeIterState cf_state;
+            cf_state.filter = castToCompositeFilter(next);
+            cf_state.cur_sub_filter_index = -1;
+            m_composite_stack.push(cf_state);
+        } break;
+        case ABSTRACT_FILTER: {
+            LOGE("Reached AbstractFilter!!");
+            m_current_state = FIS_NOT_VALID;
+        } break;
+    }
+
+    m_current_filter = next;
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/FilterIterator.h b/src/Tizen/FilterIterator.h
new file mode 100644 (file)
index 0000000..23cae94
--- /dev/null
@@ -0,0 +1,102 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#ifndef __TIZEN_TIZEN_FILTER_ITERATOR_H__
+#define __TIZEN_TIZEN_FILTER_ITERATOR_H__
+
+#include "AbstractFilter.h"
+#include "AttributeFilter.h"
+#include "AttributeRangeFilter.h"
+#include "CompositeFilter.h"
+
+#include <stack>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+enum FilterIteratorState {
+    FIS_NOT_VALID = 0,
+    FIS_ATTRIBUTE_FILTER,
+    FIS_ATTRIBUTE_RANGE_FILTER,
+    FIS_COMPOSITE_START,
+    FIS_COMPOSITE_END,
+    FIS_END
+};
+
+class FilterIterator
+{
+public:
+    FilterIterator(AbstractFilterPtr filter);
+
+    FilterIteratorState getState() const;
+    AbstractFilterPtr operator*() const;
+    AbstractFilterPtr getCurrentFilter() const;
+    bool isEnd() const;
+
+    bool isInsideCompositeFilter() const;
+
+    /**
+     * Returns null shared pointer if we are not inside composite filter
+     */
+    CompositeFilterPtr getCurrentCompositeFilter() const;
+
+    /**
+     * Get index of current sub filter (inside composite filter)
+     * Returns 0 if we are not inside composite filter.
+     */
+    int getCurrentCompositeSubFilterIndex() const;
+
+    /**
+     * Return true if current sub filter is the last one in current composite filter
+     * Returns false if we are not inside composite filter.
+     */
+    bool isLastCompositeSubFilter() const;
+
+    void operator++();
+    void operator++(int);
+
+private:
+    void setReachedEnd();
+    void goToNext(AbstractFilterPtr next);
+    void goToNextInCurCompositeFilter();
+
+    AbstractFilterPtr m_root_filter;
+    FilterIteratorState m_current_state;
+    AbstractFilterPtr m_current_filter;
+
+    struct CompositeIterState {
+        CompositeIterState() :
+                cur_sub_filter_index(0)
+        {
+        }
+
+        CompositeIterState(const CompositeIterState& other) :
+                filter(other.filter),
+                cur_sub_filter_index(other.cur_sub_filter_index)
+        {
+        }
+
+        CompositeFilterPtr filter;
+        int cur_sub_filter_index;
+    };
+
+    std::stack<CompositeIterState> m_composite_stack;
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_FILTER_ITERATOR_H__
diff --git a/src/Tizen/JSAttributeFilter.cpp b/src/Tizen/JSAttributeFilter.cpp
new file mode 100644 (file)
index 0000000..50002f3
--- /dev/null
@@ -0,0 +1,433 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSAttributeFilter.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <Export.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <algorithm>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+using namespace DeviceAPI::Common;
+
+namespace {
+const char* TIZEN_ATTRIBUTE_FILTER = "AttributeFilter";
+
+const char* TIZEN_ATTRIBUTE_FILTER_ATTRIBUTE_NAME = "attributeName";
+const char* TIZEN_ATTRIBUTE_FILTER_MATCH_FLAG = "matchFlag";
+const char* TIZEN_ATTRIBUTE_FILTER_MATCH_VALUE = "matchValue";
+
+const char* TIZEN_FILTER_MATCH_FLAG_EXACTLY = "EXACTLY";
+const char* TIZEN_FILTER_MATCH_FLAG_FULLSTRING = "FULLSTRING";
+const char* TIZEN_FILTER_MATCH_FLAG_CONTAINS = "CONTAINS";
+const char* TIZEN_FILTER_MATCH_FLAG_STARTSWITH = "STARTSWITH";
+const char* TIZEN_FILTER_MATCH_FLAG_ENDSWITH = "ENDSWITH";
+const char* TIZEN_FILTER_MATCH_FLAG_EXISTS = "EXISTS";
+}
+
+JSClassDefinition JSAttributeFilter::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_ATTRIBUTE_FILTER,
+        NULL,
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSAttributeFilter::m_property[] = {
+    { TIZEN_ATTRIBUTE_FILTER_ATTRIBUTE_NAME, getAttributeName, setAttributeName,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { TIZEN_ATTRIBUTE_FILTER_MATCH_FLAG, getMatchFlag, setMatchFlag,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { TIZEN_ATTRIBUTE_FILTER_MATCH_VALUE, getMatchValue, setMatchValue,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSAttributeFilter::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSAttributeFilter::m_jsClassRef =
+        JSClassCreate(JSAttributeFilter::getClassInfo());
+
+JSClassRef JSAttributeFilter::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+AttributeFilterPtr JSAttributeFilter::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (ATTRIBUTE_FILTER != priv->ptr->getFilterType()) {
+        LOGE("Wrong filter type: %d", priv->ptr->getFilterType());
+        throw UnknownException("Wrong filter type");
+    }
+    AttributeFilterPtr attr_filter =
+            std::dynamic_pointer_cast<AttributeFilter>(priv->ptr);
+    if(!attr_filter) {
+        LOGE("Could not cast AbstractFilterPtr to AttributeFilterPtr");
+        throw UnknownException("Wrong filter type");
+    }
+
+    return attr_filter;
+}
+
+void JSAttributeFilter::setPrivateObject(JSObjectRef object,
+        AbstractFilterPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    if(ATTRIBUTE_FILTER != native->getFilterType()) {
+        LOGE("Incorrect filter type: %d", native->getFilterType());
+        throw UnknownException("Incorrect filter type");
+    }
+
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSAttributeFilter::makeJSObject(JSContextRef context,
+        AbstractFilterPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    if(ATTRIBUTE_FILTER != native->getFilterType()) {
+        LOGE("Incorrect filter type: %d", native->getFilterType());
+        throw UnknownException("Incorrect filter type");
+    }
+
+    AbstractFilterHolder* priv = new AbstractFilterHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj =
+            JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSAttributeFilter::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSAttributeFilter::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSAttributeFilter::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef js_obj_ref = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef constructor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, js_obj_ref, constructor_name, constructor,
+            kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(constructor_name);
+
+    try {
+        std::string attribute_name = validator.toString(0);
+        std::string str_match_flag = validator.toString(1, true,
+                TIZEN_FILTER_MATCH_FLAG_EXACTLY);
+        FilterMatchFlag match_flag = stringToFilterMatchFlag(str_match_flag);
+
+        AttributeFilterPtr priv = AttributeFilterPtr(
+                new AttributeFilter(attribute_name));
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        priv->setMatchFlag(match_flag);
+
+        JSValueRef value = validator.toJSValueRef(2, true);
+        JSContextRef global_context = GlobalContextManager::getInstance()->
+                getGlobalContext(context);
+        AnyPtr match_value = AnyPtr(new Any(global_context, value));
+        priv->setMatchValue(match_value);
+
+        AbstractFilterHolder* holder = new AbstractFilterHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = std::static_pointer_cast<AbstractFilter>(priv);
+        JSObjectSetPrivate(js_obj_ref, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Creation failed");
+    }
+    return js_obj_ref;
+}
+
+JSValueRef JSAttributeFilter::getAttributeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeFilterPtr priv =
+                JSAttributeFilter::getPrivateObject(context, object);
+        std::string attribute_name = priv->getAttributeName();
+        return JSUtil::toJSValueRef(context, attribute_name);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSAttributeFilter::setAttributeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeFilterPtr priv =
+                JSAttributeFilter::getPrivateObject(context, object);
+        std::string attribute_name = JSUtil::JSValueToString(context, value);
+        priv->setAttributeName(attribute_name);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSAttributeFilter::getMatchFlag(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeFilterPtr priv =
+                JSAttributeFilter::getPrivateObject(context, object);
+        FilterMatchFlag match_flag = priv->getMatchFlag();
+        return JSUtil::toJSValueRef(context,
+                filterMatchFlagToString(match_flag));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSAttributeFilter::setMatchFlag(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeFilterPtr priv =
+                JSAttributeFilter::getPrivateObject(context, object);
+        std::string str_match_flag = JSUtil::JSValueToString(context, value);
+        FilterMatchFlag match_flag = stringToFilterMatchFlag(str_match_flag);
+        priv->setMatchFlag(match_flag);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSAttributeFilter::getMatchValue(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeFilterPtr priv =
+                JSAttributeFilter::getPrivateObject(context, object);
+        AnyPtr match_value = priv->getMatchValue();
+        return match_value->getValue();
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSAttributeFilter::setMatchValue(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeFilterPtr priv =
+                JSAttributeFilter::getPrivateObject(context, object);
+        JSContextRef global_context = GlobalContextManager::getInstance()->
+                getGlobalContext(context);
+        AnyPtr match_value = AnyPtr(new Any(global_context, value));
+        priv->setMatchValue(match_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+FilterMatchFlag JSAttributeFilter::stringToFilterMatchFlag(
+        std::string str_match_flag)
+{
+    if (TIZEN_FILTER_MATCH_FLAG_EXACTLY == str_match_flag) {
+        return FilterMatchFlag::EXACTLY;
+    }
+    if (TIZEN_FILTER_MATCH_FLAG_FULLSTRING == str_match_flag) {
+        return FilterMatchFlag::FULLSTRING;
+    }
+    if (TIZEN_FILTER_MATCH_FLAG_CONTAINS == str_match_flag) {
+        return FilterMatchFlag::CONTAINS;
+    }
+    if (TIZEN_FILTER_MATCH_FLAG_STARTSWITH == str_match_flag) {
+        return FilterMatchFlag::STARTSWITH;
+    }
+    if (TIZEN_FILTER_MATCH_FLAG_ENDSWITH == str_match_flag) {
+        return FilterMatchFlag::ENDSWITH;
+    }
+    if (TIZEN_FILTER_MATCH_FLAG_EXISTS == str_match_flag) {
+        return FilterMatchFlag::EXISTS;
+    }
+    std::string str_warn = "Not supported match flag: ";
+    str_warn += str_match_flag;
+    LOGW("%s", str_warn.c_str());
+    LOGW("Setting the default value: EXACTLY");
+    return FilterMatchFlag::EXACTLY;
+}
+
+std::string JSAttributeFilter::filterMatchFlagToString(
+        FilterMatchFlag match_flag)
+{
+    switch (match_flag) {
+        case FilterMatchFlag::EXACTLY:
+            return TIZEN_FILTER_MATCH_FLAG_EXACTLY;
+        case FilterMatchFlag::FULLSTRING:
+            return TIZEN_FILTER_MATCH_FLAG_FULLSTRING;
+        case FilterMatchFlag::CONTAINS:
+            return TIZEN_FILTER_MATCH_FLAG_CONTAINS;
+        case FilterMatchFlag::STARTSWITH:
+            return TIZEN_FILTER_MATCH_FLAG_STARTSWITH;
+        case FilterMatchFlag::ENDSWITH:
+            return TIZEN_FILTER_MATCH_FLAG_ENDSWITH;
+        case FilterMatchFlag::EXISTS:
+            return TIZEN_FILTER_MATCH_FLAG_EXISTS;
+        default:
+            std::string str_exception = "Not supported match flag: ";
+            str_exception += match_flag;
+            throw TypeMismatchException(str_exception.c_str());
+    }
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/JSAttributeFilter.h b/src/Tizen/JSAttributeFilter.h
new file mode 100644 (file)
index 0000000..a0148cc
--- /dev/null
@@ -0,0 +1,114 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_JS_ATTRIBUTE_FILTER_H__
+#define __TIZEN_TIZEN_JS_ATTRIBUTE_FILTER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "AttributeFilter.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class JSAttributeFilter {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static AttributeFilterPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            AbstractFilterPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            AbstractFilterPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static
+     * properties of this class.
+     * The values are given according to the data structure JSPropertySpec.
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getAttributeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setAttributeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getMatchFlag(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setMatchFlag(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getMatchValue(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setMatchValue(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static FilterMatchFlag stringToFilterMatchFlag(std::string str_match_flag);
+    static std::string filterMatchFlagToString(FilterMatchFlag match_flag);
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_JS_ATTRIBUTE_FILTER_H__
diff --git a/src/Tizen/JSAttributeRangeFilter.cpp b/src/Tizen/JSAttributeRangeFilter.cpp
new file mode 100644 (file)
index 0000000..43a831b
--- /dev/null
@@ -0,0 +1,378 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSAttributeRangeFilter.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <Export.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+using namespace DeviceAPI::Common;
+
+namespace {
+const char* TIZEN_ATTRIBUTE_RANGE_FILTER = "AttributeRangeFilter";
+
+const char* TIZEN_ATTRIBUTE_RANGE_FILTER_ATTRIBUTE_NAME = "attributeName";
+const char* TIZEN_ATTRIBUTE_RANGE_FILTER_INITIAL_VALUE = "initialValue";
+const char* TIZEN_ATTRIBUTE_RANGE_FILTER_END_VALUE = "endValue";
+}
+
+JSClassDefinition JSAttributeRangeFilter::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_ATTRIBUTE_RANGE_FILTER,
+        NULL,
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSAttributeRangeFilter::m_property[] = {
+    { TIZEN_ATTRIBUTE_RANGE_FILTER_ATTRIBUTE_NAME, getAttributeName, setAttributeName,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { TIZEN_ATTRIBUTE_RANGE_FILTER_INITIAL_VALUE, getInitialValue, setInitialValue,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { TIZEN_ATTRIBUTE_RANGE_FILTER_END_VALUE, getEndValue, setEndValue,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSAttributeRangeFilter::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSAttributeRangeFilter::m_jsClassRef =
+        JSClassCreate(JSAttributeRangeFilter::getClassInfo());
+
+JSClassRef JSAttributeRangeFilter::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+AttributeRangeFilterPtr JSAttributeRangeFilter::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (ATTRIBUTE_RANGE_FILTER != priv->ptr->getFilterType()) {
+        LOGE("Wrong filter type: %d", priv->ptr->getFilterType());
+        throw UnknownException("Wrong filter type");
+    }
+
+    AttributeRangeFilterPtr attr_range_filter =
+            std::dynamic_pointer_cast<AttributeRangeFilter>(priv->ptr);
+    if(!attr_range_filter) {
+        LOGE("Could not cast AbstractFilterPtr to AttributeRangeFilterPtr");
+        throw UnknownException("Wrong filter type");
+    }
+    return attr_range_filter;
+}
+
+void JSAttributeRangeFilter::setPrivateObject(JSObjectRef object,
+        AbstractFilterPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    if(ATTRIBUTE_RANGE_FILTER != native->getFilterType()) {
+        LOGE("Incorrect filter type: %d", native->getFilterType());
+        throw UnknownException("Incorrect filter type");
+    }
+
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSAttributeRangeFilter::makeJSObject(JSContextRef context,
+        AbstractFilterPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    if(ATTRIBUTE_RANGE_FILTER != native->getFilterType()) {
+        LOGE("Incorrect filter type: %d", native->getFilterType());
+        throw UnknownException("Incorrect filter type");
+    }
+
+    AbstractFilterHolder* priv = new AbstractFilterHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj =
+            JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+
+void JSAttributeRangeFilter::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSAttributeRangeFilter::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSAttributeRangeFilter::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef js_obj_ref = JSObjectMake(context, getClassRef(), NULL);
+    JSStringRef constructor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, js_obj_ref, constructor_name, constructor,
+            kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(constructor_name);
+
+    try {
+        //
+        //[Constructor(DOMString attributeName,
+        //        optional any initialValue,
+        //        optional any endValue)]
+        std::string attribute_name = validator.toString(0);
+        AttributeRangeFilterPtr priv = AttributeRangeFilterPtr(
+                new AttributeRangeFilter(attribute_name));
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        JSContextRef global_context = GlobalContextManager::getInstance()->
+                getGlobalContext(context);
+
+        JSValueRef value = validator.toJSValueRef(1, true);
+        AnyPtr initial_value = AnyPtr(new Any(global_context, value));
+        priv->setInitialValue(initial_value);
+
+        value = validator.toJSValueRef(2, true);
+        AnyPtr end_value = AnyPtr(new Any(global_context, value));
+        priv->setEndValue(end_value);
+
+        AbstractFilterHolder* holder = new AbstractFilterHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = std::static_pointer_cast<AbstractFilter>(priv);
+        JSObjectSetPrivate(js_obj_ref, static_cast<void*>(holder));
+
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Creation failed");
+    }
+    return js_obj_ref;
+}
+
+JSValueRef JSAttributeRangeFilter::getAttributeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeRangeFilterPtr priv =
+                JSAttributeRangeFilter::getPrivateObject(context, object);
+        std::string attribute_name = priv->getAttributeName();
+        return JSUtil::toJSValueRef(context, attribute_name);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSAttributeRangeFilter::setAttributeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeRangeFilterPtr priv =
+                JSAttributeRangeFilter::getPrivateObject(context, object);
+        std::string attribute_name = JSUtil::JSValueToString(context, value);
+        priv->setAttributeName(attribute_name);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSAttributeRangeFilter::getInitialValue(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeRangeFilterPtr priv =
+                JSAttributeRangeFilter::getPrivateObject(context, object);
+        AnyPtr initial_value = priv->getInitialValue();
+        return initial_value->getValue();
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSAttributeRangeFilter::setInitialValue(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeRangeFilterPtr priv =
+                JSAttributeRangeFilter::getPrivateObject(context, object);
+        JSContextRef global_context = GlobalContextManager::getInstance()->
+                getGlobalContext(context);
+        AnyPtr initial_value = AnyPtr(new Any(global_context, value));
+        priv->setInitialValue(initial_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSAttributeRangeFilter::getEndValue(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeRangeFilterPtr priv =
+                JSAttributeRangeFilter::getPrivateObject(context, object);
+        AnyPtr end_value = priv->getEndValue();
+        return end_value->getValue();
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSAttributeRangeFilter::setEndValue(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        AttributeRangeFilterPtr priv =
+                JSAttributeRangeFilter::getPrivateObject(context, object);
+        JSContextRef global_context = GlobalContextManager::getInstance()->
+                getGlobalContext(context);
+        AnyPtr end_value = AnyPtr(new Any(global_context, value));
+        priv->setEndValue(end_value);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/JSAttributeRangeFilter.h b/src/Tizen/JSAttributeRangeFilter.h
new file mode 100644 (file)
index 0000000..c2d963c
--- /dev/null
@@ -0,0 +1,111 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_JS_ATTRIBUTE_RANGE_FILTER_H__
+#define __TIZEN_TIZEN_JS_ATTRIBUTE_RANGE_FILTER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "AttributeRangeFilter.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class JSAttributeRangeFilter {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static AttributeRangeFilterPtr getPrivateObject(JSContextRef context,
+        JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            AbstractFilterPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            AbstractFilterPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static
+     * properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getAttributeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setAttributeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getInitialValue(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setInitialValue(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getEndValue(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setEndValue(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_JS_ATTRIBUTE_RANGE_FILTER_H__
diff --git a/src/Tizen/JSCompositeFilter.cpp b/src/Tizen/JSCompositeFilter.cpp
new file mode 100644 (file)
index 0000000..2b99296
--- /dev/null
@@ -0,0 +1,359 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSCompositeFilter.h"
+#include "CompositeFilter.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <Export.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <algorithm>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+using namespace DeviceAPI::Common;
+
+namespace {
+const char* TIZEN_COMPOSITE_FILTER = "CompositeFilter";
+
+const char* TIZEN_COMPOSITE_FILTER_TYPE = "type";
+const char* TIZEN_COMPOSITE_FILTER_FILTERS = "filters";
+
+const char* TIZEN_COMPOSITE_FILTER_TYPE_UNION = "UNION";
+const char* TIZEN_COMPOSITE_FILTER_TYPE_INTERSECTION = "INTERSECTION";
+}
+
+JSClassDefinition JSCompositeFilter::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_COMPOSITE_FILTER,
+        NULL,
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSCompositeFilter::m_property[] = {
+    { TIZEN_COMPOSITE_FILTER_TYPE, getType, setType,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { TIZEN_COMPOSITE_FILTER_FILTERS, getFilters, setFilters,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSCompositeFilter::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSCompositeFilter::m_jsClassRef =
+        JSClassCreate(JSCompositeFilter::getClassInfo());
+
+JSClassRef JSCompositeFilter::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+CompositeFilterPtr JSCompositeFilter::getPrivateObject(JSContextRef context,
+            JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    if (COMPOSITE_FILTER != priv->ptr->getFilterType()) {
+        LOGE("Wrong filter type: %d", priv->ptr->getFilterType());
+        throw UnknownException("Wrong filter type");
+    }
+    CompositeFilterPtr composite_filter =
+            std::dynamic_pointer_cast<CompositeFilter>(priv->ptr);
+    if(!composite_filter) {
+        LOGE("Could not cast AbstractFilterPtr to CompositeFilterPtr");
+        throw UnknownException("Wrong filter type");
+    }
+    return composite_filter;
+}
+
+void JSCompositeFilter::setPrivateObject(JSObjectRef object,
+        AbstractFilterPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    if(COMPOSITE_FILTER != native->getFilterType()) {
+        LOGE("Incorrect filter type: %d", native->getFilterType());
+        throw UnknownException("Incorrect filter type");
+    }
+
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSCompositeFilter::makeJSObject(JSContextRef context,
+        AbstractFilterPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    if(COMPOSITE_FILTER != native->getFilterType()) {
+        LOGE("Incorrect filter type: %d", native->getFilterType());
+        throw UnknownException("Incorrect filter type");
+    }
+
+    AbstractFilterHolder* priv = new AbstractFilterHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj =
+            JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSCompositeFilter::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSCompositeFilter::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    AbstractFilterHolder* priv =
+            static_cast<AbstractFilterHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSCompositeFilter::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef js_obj_ref = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef constructor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, js_obj_ref, constructor_name, constructor,
+            kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(constructor_name);
+
+    try {
+        std::string str_type = validator.toString(0);
+        CompositeFilterType type =
+                stringToCompositeFilterType(str_type);
+
+        CompositeFilterPtr priv = CompositeFilterPtr(
+                new CompositeFilter(type));
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        JSObjectRef js_filters = validator.toArrayObject(1, true);
+
+        if (js_filters) {
+            std::vector<AbstractFilterPtr> filters = JSUtil::JSArrayToType_(context,
+                    js_filters, AbstractFilter::getPrivateObject);
+            priv->setFilters(filters);
+        }
+
+        AbstractFilterHolder* holder = new AbstractFilterHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = std::static_pointer_cast<AbstractFilter>(priv);
+        JSObjectSetPrivate(js_obj_ref, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Creation failed");
+    }
+    return js_obj_ref;
+}
+
+JSValueRef JSCompositeFilter::getType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CompositeFilterPtr priv =
+                JSCompositeFilter::getPrivateObject(context, object);
+        CompositeFilterType type = priv->getType();
+        return JSUtil::toJSValueRef(context,
+                compositeFilterTypeToString(type));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSCompositeFilter::setType(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CompositeFilterPtr priv =
+                JSCompositeFilter::getPrivateObject(context, object);
+        std::string str_type = JSUtil::JSValueToString(context, value);
+        CompositeFilterType type = stringToCompositeFilterType(str_type);
+        priv->setType(type);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSCompositeFilter::getFilters(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CompositeFilterPtr priv =
+                JSCompositeFilter::getPrivateObject(context, object);
+        return priv->getJSFilters(
+                GlobalContextManager::getInstance()->getGlobalContext(context));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSCompositeFilter::setFilters(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        CompositeFilterPtr priv =
+                JSCompositeFilter::getPrivateObject(context, object);
+        AbstractFilterPtrVector filters =
+                JSUtil::JSArrayToType_(context, value,
+                        AbstractFilter::getPrivateObject);
+        priv->setFilters(filters);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+CompositeFilterType JSCompositeFilter::stringToCompositeFilterType(std::string str_type)
+{
+    if (TIZEN_COMPOSITE_FILTER_TYPE_UNION == str_type) {
+        return UNION;
+    }
+    if (TIZEN_COMPOSITE_FILTER_TYPE_INTERSECTION == str_type) {
+        return INTERSECTION;
+    }
+
+    std::string str_exception = "Not supported composite filter type: ";
+    str_exception += str_type;
+    throw Common::TypeMismatchException(str_exception.c_str());
+}
+
+std::string JSCompositeFilter::compositeFilterTypeToString(CompositeFilterType type)
+{
+    switch (type) {
+        case CompositeFilterType::UNION:
+            return TIZEN_COMPOSITE_FILTER_TYPE_UNION;
+        case CompositeFilterType::INTERSECTION:
+            return TIZEN_COMPOSITE_FILTER_TYPE_INTERSECTION;
+        default:
+            std::string str_exception = "Not supported composite filter type: ";
+            str_exception += type;
+            throw Common::TypeMismatchException(str_exception.c_str());
+    }
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/JSCompositeFilter.h b/src/Tizen/JSCompositeFilter.h
new file mode 100644 (file)
index 0000000..ab01bb1
--- /dev/null
@@ -0,0 +1,103 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_JS_COMPOSITE_FILTER_H__
+#define __TIZEN_TIZEN_JS_COMPOSITE_FILTER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "CompositeFilter.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class JSCompositeFilter {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static CompositeFilterPtr getPrivateObject(JSContextRef context,
+                JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            AbstractFilterPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            AbstractFilterPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static
+     * properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setType(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getFilters(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setFilters(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static CompositeFilterType stringToCompositeFilterType(std::string str_type);
+    static std::string compositeFilterTypeToString(CompositeFilterType type);
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_JS_COMPOSITE_FILTER_H__
diff --git a/src/Tizen/JSSimpleCoordinates.cpp b/src/Tizen/JSSimpleCoordinates.cpp
new file mode 100644 (file)
index 0000000..4348a2c
--- /dev/null
@@ -0,0 +1,293 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSimpleCoordinates.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <Export.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+using namespace DeviceAPI::Common;
+
+struct SimpleCoordinatesHolder {
+    SimpleCoordinatesPtr ptr;
+};
+
+namespace {
+const char* TIZEN_SIMPLE_COORDINATES = "SimpleCoordinates";
+
+const char* TIZEN_SIMPLE_COORDINATES_LATITUDE = "latitude";
+const char* TIZEN_SIMPLE_COORDINATES_LONGITUDE = "longitude";
+}
+
+JSClassDefinition JSSimpleCoordinates::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_SIMPLE_COORDINATES,
+        NULL,
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSSimpleCoordinates::m_property[] = {
+    { TIZEN_SIMPLE_COORDINATES_LATITUDE, getLatitude, setLatitude,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { TIZEN_SIMPLE_COORDINATES_LONGITUDE, getLongitude, setLongitude,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSimpleCoordinates::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSimpleCoordinates::m_jsClassRef =
+        JSClassCreate(JSSimpleCoordinates::getClassInfo());
+
+JSClassRef JSSimpleCoordinates::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SimpleCoordinatesPtr JSSimpleCoordinates::getPrivateObject(JSContextRef context,
+        JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SimpleCoordinatesHolder* priv =
+            static_cast<SimpleCoordinatesHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSimpleCoordinates::setPrivateObject(JSObjectRef object,
+        SimpleCoordinatesPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    SimpleCoordinatesHolder* priv =
+            static_cast<SimpleCoordinatesHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSimpleCoordinates::makeJSObject(JSContextRef context,
+        SimpleCoordinatesPtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    SimpleCoordinatesHolder* priv = new SimpleCoordinatesHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj = JSObjectMake(context, getClassRef(),
+            static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSimpleCoordinates::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSimpleCoordinates::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SimpleCoordinatesHolder* priv =
+            static_cast<SimpleCoordinatesHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSSimpleCoordinates::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef js_obj_ref = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef constructor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, js_obj_ref, constructor_name, constructor,
+            kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(constructor_name);
+
+    try {
+        double latitude = validator.toDouble(0);
+        double longitude = validator.toDouble(1);
+
+        SimpleCoordinatesPtr priv = SimpleCoordinatesPtr(
+                new SimpleCoordinates(latitude, longitude));
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        SimpleCoordinatesHolder* holder = new SimpleCoordinatesHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(js_obj_ref, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Creation failed");
+    }
+    return js_obj_ref;
+}
+
+JSValueRef JSSimpleCoordinates::getLatitude(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SimpleCoordinatesPtr priv =
+                JSSimpleCoordinates::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getLatitude());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSSimpleCoordinates::setLatitude(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SimpleCoordinatesPtr priv =
+                JSSimpleCoordinates::getPrivateObject(context, object);
+        double latitude = JSUtil::JSValueToDouble(context, value);
+        priv->setLatitude(latitude);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSSimpleCoordinates::getLongitude(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SimpleCoordinatesPtr priv =
+                JSSimpleCoordinates::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getLongitude());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSSimpleCoordinates::setLongitude(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SimpleCoordinatesPtr priv =
+                JSSimpleCoordinates::getPrivateObject(context, object);
+        double longitude = JSUtil::JSValueToDouble(context, value);
+        priv->setLongitude(longitude);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/JSSimpleCoordinates.h b/src/Tizen/JSSimpleCoordinates.h
new file mode 100644 (file)
index 0000000..370efb0
--- /dev/null
@@ -0,0 +1,100 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_JS_SIMPLE_COORDINATES_H__
+#define __TIZEN_TIZEN_JS_SIMPLE_COORDINATES_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SimpleCoordinates.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class JSSimpleCoordinates {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SimpleCoordinatesPtr getPrivateObject(JSContextRef context,
+            JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object,
+            SimpleCoordinatesPtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context,
+            SimpleCoordinatesPtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static
+     * properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getLatitude(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setLatitude(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getLongitude(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setLongitude(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_JS_SIMPLE_COORDINATES_H__
diff --git a/src/Tizen/JSSortMode.cpp b/src/Tizen/JSSortMode.cpp
new file mode 100644 (file)
index 0000000..7b15a55
--- /dev/null
@@ -0,0 +1,319 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSSortMode.h"
+
+#include <Logger.h>
+#include <PlatformException.h>
+#include <Export.h>
+#include <JSUtil.h>
+#include <ArgumentValidator.h>
+#include <algorithm>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+using namespace DeviceAPI::Common;
+
+struct SortModeHolder {
+    SortModePtr ptr;
+};
+
+namespace {
+const char* TIZEN_SORT_MODE = "SortMode";
+
+const char* TIZEN_SORT_MODE_ATTRIBUTE_NAME = "attributeName";
+const char* TIZEN_SORT_MODE_ORDER = "order";
+
+const char* TIZEN_SORT_MODE_ORDER_ASC = "ASC";
+const char* TIZEN_SORT_MODE_ORDER_DESC = "DESC";
+}
+
+JSClassDefinition JSSortMode::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_SORT_MODE,
+        NULL,
+        m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        NULL, //hasProperty,
+        NULL, //getProperty,
+        NULL, //setProperty,
+        NULL, //deleteProperty,
+        NULL, //getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+JSStaticValue JSSortMode::m_property[] = {
+    { TIZEN_SORT_MODE_ATTRIBUTE_NAME, getAttributeName, setAttributeName,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { TIZEN_SORT_MODE_ORDER, getOrder, setOrder,
+            kJSPropertyAttributeDontDelete | kJSPropertyAttributeNone },
+    { 0, 0, 0, 0 }
+};
+
+const JSClassDefinition* JSSortMode::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSSortMode::m_jsClassRef =
+        JSClassCreate(JSSortMode::getClassInfo());
+
+JSClassRef JSSortMode::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+SortModePtr JSSortMode::getPrivateObject(JSContextRef context, JSValueRef value)
+{
+    if (!JSValueIsObjectOfClass(context, value, getClassRef())) {
+        LOGE("Type mismatch");
+        throw TypeMismatchException("Type mismatch");
+    }
+
+    JSObjectRef object = JSUtil::JSValueToObject(context, value);
+    SortModeHolder* priv =
+            static_cast<SortModeHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Holder is null");
+        throw UnknownException("Holder is null");
+    }
+    if (!(priv->ptr)) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    return priv->ptr;
+}
+
+void JSSortMode::setPrivateObject(JSObjectRef object, SortModePtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+    SortModeHolder* priv =
+            static_cast<SortModeHolder*>(JSObjectGetPrivate(object));
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+}
+
+JSObjectRef JSSortMode::makeJSObject(JSContextRef context, SortModePtr native)
+{
+    if (!native) {
+        LOGE("Native is null");
+        throw UnknownException("Native is null");
+    }
+
+    SortModeHolder* priv = new SortModeHolder();
+    if (!priv) {
+        LOGE("Priv is null");
+        throw UnknownException("Priv is null");
+    }
+    priv->ptr = native;
+
+    JSObjectRef obj =
+            JSObjectMake(context, getClassRef(), static_cast<void*>(priv));
+    return obj;
+}
+
+void JSSortMode::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+}
+
+void JSSortMode::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    SortModeHolder* priv = static_cast<SortModeHolder*>(JSObjectGetPrivate(object));
+    if (priv) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+JSObjectRef DLL_EXPORT JSSortMode::constructor(JSContextRef context,
+        JSObjectRef constructor,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+
+    ArgumentValidator validator(context, argumentCount, arguments);
+
+    JSObjectRef js_obj_ref = JSObjectMake(context, getClassRef(), NULL);
+
+    JSStringRef constructor_name = JSStringCreateWithUTF8CString("constructor");
+    JSObjectSetProperty(context, js_obj_ref, constructor_name, constructor,
+            kJSPropertyAttributeReadOnly
+            | kJSPropertyAttributeDontDelete
+            | kJSPropertyAttributeDontEnum, NULL);
+    JSStringRelease(constructor_name);
+
+    try {
+        std::string attribute_name = validator.toString(0);
+        std::string str_order = validator.toString(1, true, "ASC");
+        SortModeOrder order = stringToSortModeOrder(str_order);
+
+        SortModePtr priv = SortModePtr(new SortMode(attribute_name, order));
+        if (!priv) {
+            LOGE("Priv is null");
+            throw UnknownException("Priv is null");
+        }
+
+        SortModeHolder* holder = new SortModeHolder();
+        if (!holder) {
+            LOGE("Holder is null");
+            throw UnknownException("Holder is null");
+        }
+        holder->ptr = priv;
+        JSObjectSetPrivate(js_obj_ref, static_cast<void*>(holder));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Creation failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Creation failed");
+    }
+    return js_obj_ref;
+}
+
+JSValueRef JSSortMode::getAttributeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SortModePtr priv = JSSortMode::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context, priv->getAttributeName());
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSSortMode::setAttributeName(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SortModePtr priv = JSSortMode::getPrivateObject(context, object);
+        std::string attribute_name = JSUtil::JSValueToString(context, value);
+        priv->setAttributeName(attribute_name);
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+JSValueRef JSSortMode::getOrder(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SortModePtr priv = JSSortMode::getPrivateObject(context, object);
+        return JSUtil::toJSValueRef(context,
+                sortModeOrderToString(priv->getOrder()));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute get failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute get failed");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSSortMode::setOrder(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    LOGD("Entered");
+    try {
+        SortModePtr priv = JSSortMode::getPrivateObject(context, object);
+        std::string str_order = JSUtil::JSValueToString(context, value);
+        priv->setOrder(stringToSortModeOrder(str_order));
+    }
+    catch (const BasePlatformException &error) {
+        LOGE("Attribute set failed: %s", error.getMessage().c_str());
+    }
+    catch (...) {
+        LOGE("Attribute set failed");
+    }
+    return true;
+}
+
+SortModeOrder JSSortMode::stringToSortModeOrder(std::string str_order)
+{
+    std::transform(str_order.begin(), str_order.end(), str_order.begin(),
+            ::toupper);
+    if (TIZEN_SORT_MODE_ORDER_ASC == str_order) {
+        return SortModeOrder::ASC;
+    }
+    if (TIZEN_SORT_MODE_ORDER_DESC == str_order) {
+        return SortModeOrder::DESC;
+    }
+    std::string str_exception = "Not supported order: ";
+    str_exception += str_order;
+    throw TypeMismatchException(str_exception.c_str());
+}
+
+std::string JSSortMode::sortModeOrderToString(SortModeOrder order)
+{
+    switch (order) {
+        case SortModeOrder::ASC:
+            return TIZEN_SORT_MODE_ORDER_ASC;
+        case SortModeOrder::DESC:
+            return TIZEN_SORT_MODE_ORDER_DESC;
+        default:
+            std::string str_exception = "Not supported order: ";
+            str_exception += order;
+            throw TypeMismatchException(str_exception.c_str());
+    }
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/JSSortMode.h b/src/Tizen/JSSortMode.h
new file mode 100644 (file)
index 0000000..84ac596
--- /dev/null
@@ -0,0 +1,100 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_JS_SORT_MODE_H__
+#define __TIZEN_TIZEN_JS_SORT_MODE_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include "SortMode.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class JSSortMode {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+    static SortModePtr getPrivateObject(JSContextRef context, JSValueRef value);
+
+    static void setPrivateObject(JSObjectRef object, SortModePtr native);
+
+    static JSObjectRef makeJSObject(JSContextRef context, SortModePtr native);
+
+    static JSObjectRef constructor(JSContextRef context,
+            JSObjectRef constructor,
+            size_t argumentCount,
+            const JSValueRef arguments[],
+            JSValueRef* exception);
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This member variable contains the initialization values for the static
+     * properties of this class.
+     * The values are given according to the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef getAttributeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setAttributeName(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static JSValueRef getOrder(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setOrder(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static SortModeOrder stringToSortModeOrder(std::string str_order);
+    static std::string sortModeOrderToString(SortModeOrder order);
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_JS_SORT_MODE_H__
diff --git a/src/Tizen/JSTizen.cpp b/src/Tizen/JSTizen.cpp
new file mode 100644 (file)
index 0000000..9174afe
--- /dev/null
@@ -0,0 +1,207 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "JSTizen.h"
+
+#include <Logger.h>
+#include <Export.h>
+#include <PluginManager/PluginManagerFactory.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <CommonsJavaScript/Converter.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace WrtDeviceApis::PluginManager::Api;
+
+namespace {
+const char* TIZEN_TIZEN = "tizen";
+}
+
+JSClassDefinition JSTizen::m_classInfo = {
+        0,
+        kJSClassAttributeNone,
+        TIZEN_TIZEN,
+        NULL,
+        NULL, //m_property,
+        NULL, //m_function,
+        initialize,
+        finalize,
+        hasProperty,
+        getProperty,
+        setProperty,
+        NULL, //deleteProperty,
+        getPropertyNames,
+        NULL, //function,
+        NULL, //constructor,
+        NULL, //hasInstance,
+        NULL, //convertToType,
+};
+
+const JSClassDefinition* JSTizen::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+JSClassRef JSTizen::m_jsClassRef =
+        JSClassCreate(JSTizen::getClassInfo());
+
+JSClassRef DLL_EXPORT JSTizen::getClassRef()
+{
+    if (!m_jsClassRef) {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+void JSTizen::initialize(JSContextRef context, JSObjectRef object)
+{
+    LOGD("Entered");
+    TizenPriv* priv = static_cast<TizenPriv*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    if (priv) {
+        delete priv;
+        priv = NULL;
+    }
+
+    int widget_id = WrtAccessSingleton::Instance().getWidgetId();
+    PluginPrivPtr priv_object(
+            new PluginPriv(PluginManagerFactory::getInstance().getPluginManager(
+                    widget_id, TIZEN_TIZEN, object, context)));
+
+    priv = new TizenPriv(context, priv_object);
+    if (!JSObjectSetPrivate(object, static_cast<void*>(priv))) {
+        JSObjectSetPrivate(object, NULL);
+        delete priv;
+        priv = NULL;
+    }
+}
+
+void JSTizen::finalize(JSObjectRef object)
+{
+    LOGD("Entered");
+    TizenPriv* priv = static_cast<TizenPriv*>(JSObjectGetPrivate(object));
+    JSObjectSetPrivate(object, NULL);
+    delete priv;
+    priv = NULL;
+}
+
+bool JSTizen::hasProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName)
+{
+    try {
+        TizenPriv* priv = static_cast<TizenPriv*>(JSObjectGetPrivate(object));
+        if (!priv || !priv->getObject()) {
+            LOGE("Priv is null");
+            return false;
+        }
+
+        return priv->getObject()->getPluginManager()->hasChild(
+                CommonsJavaScript::Converter(context).toString(propertyName));
+    }
+    catch (Exception) {
+        LOGE("Error occurred");
+    }
+    return false;
+}
+
+JSValueRef JSTizen::getProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef* exception)
+{
+    try {
+        TizenPriv* priv = static_cast<TizenPriv*>(JSObjectGetPrivate(object));
+        if (!priv || !priv->getObject()) {
+            LOGE("Priv is null");
+            return false;
+        }
+
+        return priv->getObject()->getPluginManager()->getProperty(
+                CommonsJavaScript::Converter(context).toString(propertyName));
+    }
+    catch (Exception) {
+        LOGE("Error occurred");
+    }
+    return JSValueMakeUndefined(context);
+}
+
+bool JSTizen::setProperty(JSContextRef context,
+        JSObjectRef object,
+        JSStringRef propertyName,
+        JSValueRef value,
+        JSValueRef* exception)
+{
+    try {
+        TizenPriv* priv = static_cast<TizenPriv*>(JSObjectGetPrivate(object));
+        if (!priv || !priv->getObject()) {
+            LOGE("Priv is null");
+            return false;
+        }
+        std::string str_property_name =
+                CommonsJavaScript::Converter(context).toString(propertyName);
+        if (!priv->getObject()->propertyInitialized(str_property_name)) {
+            priv->getObject()->getPluginManager()->setProperty(str_property_name,
+                    value);
+        }
+    }
+    catch (Exception) {
+        LOGE("Error occurred");
+    }
+    return false;
+}
+
+void JSTizen::getPropertyNames(JSContextRef context,
+        JSObjectRef object,
+        JSPropertyNameAccumulatorRef propertyNames)
+{
+    try {
+        TizenPriv* priv = static_cast<TizenPriv*>(JSObjectGetPrivate(object));
+        if (!priv || !priv->getObject()) {
+            LOGE("Priv is null");
+            return;
+        }
+        PluginPrivPtr priv_obj = priv->getObject();
+        priv_obj->getPluginManager()->addPropertiesToList(propertyNames);
+
+    }
+    catch (Exception) {
+        LOGE("Error occurred");
+    }
+}
+
+//bool JSTizen::hasInstance(JSContextRef context,
+//        JSObjectRef constructor,
+//        JSValueRef possibleInstance,
+//        JSValueRef* exception)
+//{
+//    return true;
+//}
+//
+//JSValueRef JSTizen::convertToType(JSContextRef context,
+//        JSObjectRef object,
+//        JSType type,
+//        JSValueRef* exception)
+//{
+//    return JSValueMakeUndefined(context);
+//}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/JSTizen.h b/src/Tizen/JSTizen.h
new file mode 100644 (file)
index 0000000..07c6d44
--- /dev/null
@@ -0,0 +1,93 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_JS_TIZEN_H__
+#define __TIZEN_TIZEN_JS_TIZEN_H__
+
+#include <JavaScriptCore/JavaScript.h>
+#include <CommonsJavaScript/PrivateObject.h>
+#include "PluginPriv.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+typedef WrtDeviceApis::CommonsJavaScript::PrivateObjectT<PluginPrivPtr>::Type TizenPriv;
+
+class JSTizen {
+public:
+    static JSClassRef getClassRef();
+
+    static const JSClassDefinition* getClassInfo();
+
+private:
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    static JSClassRef m_jsClassRef;
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context, JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static bool hasProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName);
+
+    static JSValueRef getProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef* exception);
+
+    static bool setProperty(JSContextRef context,
+            JSObjectRef object,
+            JSStringRef propertyName,
+            JSValueRef value,
+            JSValueRef* exception);
+
+    static void getPropertyNames(JSContextRef context,
+            JSObjectRef object,
+            JSPropertyNameAccumulatorRef propertyNames);
+
+//    static bool hasInstance(JSContextRef context,
+//            JSObjectRef constructor,
+//            JSValueRef possibleInstance,
+//            JSValueRef* exception);
+//
+//    static JSValueRef convertToType(JSContextRef context,
+//            JSObjectRef object,
+//            JSType type,
+//            JSValueRef* exception);
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_JS_TIZEN_H__
diff --git a/src/Tizen/PluginPriv.cpp b/src/Tizen/PluginPriv.cpp
new file mode 100644 (file)
index 0000000..0a95964
--- /dev/null
@@ -0,0 +1,51 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "PluginPriv.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+using namespace WrtDeviceApis::PluginManager::Api;
+
+PluginPriv::PluginPriv(const IPluginManagerPtr &plugin_manager) :
+        m_plugin_manager(plugin_manager)
+{
+}
+
+PluginPriv::~PluginPriv()
+{
+}
+
+IPluginManagerPtr PluginPriv::getPluginManager() const
+{
+    return m_plugin_manager;
+}
+
+bool PluginPriv::propertyInitialized(std::string &property_name)
+{
+    if (m_initialized_properties.find(property_name) ==
+            m_initialized_properties.end()) {
+        m_initialized_properties.insert(property_name);
+        return false;
+    }
+
+    return true;
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/PluginPriv.h b/src/Tizen/PluginPriv.h
new file mode 100644 (file)
index 0000000..09b133d
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_PLUGIN_PRIV_H__
+#define __TIZEN_TIZEN_PLUGIN_PRIV_H__
+
+#include <map>
+#include <set>
+#include <memory>
+#include <JavaScriptCore/JavaScript.h>
+#include <PluginManager/IPluginManager.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+/**
+ * This class is used to store WrtDeviceApis::PluginManager in tizen object
+ * and to attach to it other plugins which are it's children.
+ */
+class PluginPriv {
+public:
+    PluginPriv(
+            const WrtDeviceApis::PluginManager::Api::IPluginManagerPtr &plugin_manager);
+    virtual ~PluginPriv();
+
+    WrtDeviceApis::PluginManager::Api::IPluginManagerPtr getPluginManager() const;
+    bool propertyInitialized(std::string &property_name);
+
+private:
+    WrtDeviceApis::PluginManager::Api::IPluginManagerPtr m_plugin_manager;
+    std::set<std::string> m_initialized_properties;
+};
+
+typedef std::shared_ptr<PluginPriv> PluginPrivPtr;
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_PLUGIN_PRIV_H__
diff --git a/src/Tizen/SimpleCoordinates.cpp b/src/Tizen/SimpleCoordinates.cpp
new file mode 100644 (file)
index 0000000..05a6be2
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "SimpleCoordinates.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+SimpleCoordinates::SimpleCoordinates(double latitude, double longitude):
+        m_latitude(latitude),
+        m_longitude(longitude)
+{
+
+}
+
+SimpleCoordinates::~SimpleCoordinates()
+{
+
+}
+
+double SimpleCoordinates::getLatitude() const
+{
+    return m_latitude;
+}
+
+void SimpleCoordinates::setLatitude(double latitude)
+{
+    m_latitude = latitude;
+}
+
+double SimpleCoordinates::getLongitude() const
+{
+    return m_longitude;
+}
+
+void SimpleCoordinates::setLongitude(double longitude)
+{
+    m_longitude = longitude;
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/SimpleCoordinates.h b/src/Tizen/SimpleCoordinates.h
new file mode 100644 (file)
index 0000000..dfc05ea
--- /dev/null
@@ -0,0 +1,47 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_SIMPLE_COORDINATES_H__
+#define __TIZEN_TIZEN_SIMPLE_COORDINATES_H__
+
+#include <memory>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class SimpleCoordinates;
+typedef std::shared_ptr<SimpleCoordinates> SimpleCoordinatesPtr;
+
+class SimpleCoordinates {
+public:
+    SimpleCoordinates(double latitude, double longitude);
+    virtual ~SimpleCoordinates();
+
+    double getLatitude() const;
+    void setLatitude(double latitude);
+    double getLongitude() const;
+    void setLongitude(double longitude);
+
+private:
+    double m_latitude;
+    double m_longitude;
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_SIMPLE_COORDINATES_H__
diff --git a/src/Tizen/SortMode.cpp b/src/Tizen/SortMode.cpp
new file mode 100644 (file)
index 0000000..f412c89
--- /dev/null
@@ -0,0 +1,55 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#include "SortMode.h"
+
+namespace DeviceAPI {
+namespace Tizen {
+
+SortMode::SortMode(const std::string &attribute_name, SortModeOrder order) :
+        m_attribute_name(attribute_name),
+        m_order(order)
+{
+
+}
+
+SortMode::~SortMode()
+{
+
+}
+
+std::string SortMode::getAttributeName() const
+{
+    return m_attribute_name;
+}
+
+void SortMode::setAttributeName(const std::string &attribute_name)
+{
+    m_attribute_name = attribute_name;
+}
+
+SortModeOrder SortMode::getOrder() const
+{
+    return m_order;
+}
+
+void SortMode::setOrder(SortModeOrder order)
+{
+    m_order = order;
+}
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/Tizen/SortMode.h b/src/Tizen/SortMode.h
new file mode 100644 (file)
index 0000000..ea5a98d
--- /dev/null
@@ -0,0 +1,53 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_SORT_MODE_H__
+#define __TIZEN_TIZEN_SORT_MODE_H__
+
+#include <memory>
+#include <string>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+class SortMode;
+typedef std::shared_ptr<SortMode> SortModePtr;
+
+enum SortModeOrder {
+    ASC,
+    DESC
+};
+
+class SortMode {
+public:
+    SortMode(const std::string &attribute_name, SortModeOrder order);
+    virtual ~SortMode();
+
+    std::string getAttributeName() const;
+    void setAttributeName(const std::string &attribute_name);
+    SortModeOrder getOrder() const;
+    void setOrder(SortModeOrder order);
+
+private:
+    std::string m_attribute_name;
+    SortModeOrder m_order;
+};
+
+} // Tizen
+} // DeviceAPI
+
+#endif // __TIZEN_TIZEN_SORT_MODE_H__
diff --git a/src/Tizen/config.xml b/src/Tizen/config.xml
new file mode 100644 (file)
index 0000000..2273ac3
--- /dev/null
@@ -0,0 +1,22 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-tizen.so</library-name>
+    <feature-install-uri>tizen.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/tizen</name>
+        <!--
+            <Object name="tizen">
+                <Function name="listAvailableFeatures"/>
+                <Function name="listActivatedFeatures"/>
+                <Function name="createCompositeFilter"/>
+                <Function name="createAttributeFilter"/>
+                <Function name="createAttributeRangeFilter"/>
+                <Function name="createIDFilter"/>
+                <Function name="createSortMode"/>
+            </Object>
+        -->
+    </api-feature>
+</plugin-properties>
+
diff --git a/src/Tizen/plugin_config.cpp b/src/Tizen/plugin_config.cpp
new file mode 100644 (file)
index 0000000..9bc8ee0
--- /dev/null
@@ -0,0 +1,91 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+//#include <map>
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+
+#include "plugin_config.h"
+
+#define TIZEN_FEATURE_API "http://tizen.org/privilege/tizen"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI {
+namespace Tizen {
+
+//const char* TIZEN_FUNCTION_API_LIST_AVAIL_FEATURES = "listAvailableFeatures";
+//const char* TIZEN_FUNCTION_API_LIST_ACTIV_FEATURES = "listActivatedFeatures";
+
+static FunctionMapping createDeviceApisFunctions();
+
+static FunctionMapping DeviceApisFunctions =
+        createDeviceApisFunctions();
+
+DEFINE_FUNCTION_GETTER(DeviceApis, DeviceApisFunctions);
+
+static FunctionMapping createDeviceApisFunctions()
+{
+    FunctionMapping DeviceApisMapping;
+
+//    /**
+//     * Device capabilities
+//     */
+//    ACE_CREATE_DEVICE_CAPS_LIST(EMPTY_DEVICE_LIST);
+//
+//    /**
+//     * Api Features
+//     */
+//    ACE_CREATE_FEATURE(FEATURE_TIZEN, TIZEN_FEATURE_API);
+//
+//    ACE_CREATE_FEATURE_LIST(FEATURE_LIST_TIZEN);
+//    ACE_ADD_API_FEATURE(FEATURE_LIST_TIZEN, FEATURE_TIZEN);
+//
+//    /**
+//     * Functions
+//     */
+//
+//    //LIST_AVAIL
+//    AceFunction listAvailableFeaturesFuncs =
+//            ACE_CREATE_FUNCTION(FUNCTION_LIST_AVAILABLE_FEATURES,
+//                    TIZEN_FUNCTION_API_LIST_AVAIL_FEATURES,
+//                    FEATURE_LIST_TIZEN,
+//                    EMPTY_DEVICE_LIST);
+//
+//    DeviceApisMapping.insert(
+//            std::make_pair(TIZEN_FUNCTION_API_LIST_AVAIL_FEATURES,
+//                    listAvailableFeaturesFuncs));
+//
+//    //LIST_ACTIV
+//    AceFunction listActivatedFeaturesFunc =
+//            ACE_CREATE_FUNCTION(FUNCTION_LIST_ACTIVATED_FEATURES,
+//                    TIZEN_FUNCTION_API_LIST_ACTIV_FEATURES,
+//                    FEATURE_LIST_TIZEN,
+//                    EMPTY_DEVICE_LIST);
+//
+//    DeviceApisMapping.insert(
+//            std::make_pair(TIZEN_FUNCTION_API_LIST_ACTIV_FEATURES,
+//                    listActivatedFeaturesFunc));
+
+    return DeviceApisMapping;
+}
+
+} // Tizen
+} // DeviceAPI
+
+#undef TIZEN_FEATURE_API
diff --git a/src/Tizen/plugin_config.h b/src/Tizen/plugin_config.h
new file mode 100644 (file)
index 0000000..b86d7a5
--- /dev/null
@@ -0,0 +1,38 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_TIZEN_PLUGIN_CONFIG_H__
+#define __TIZEN_TIZEN_PLUGIN_CONFIG_H__
+
+#include <Commons/FunctionDeclaration.h>
+#include <Security.h>
+
+namespace DeviceAPI {
+namespace Tizen {
+
+//extern const char* TIZEN_FUNCTION_API_LIST_AVAIL_FEATURES;
+//extern const char* TIZEN_FUNCTION_API_LIST_ACTIV_FEATURES;
+//extern const char* TIZEN_FUNCTION_API_CREATE_COMPOSITE_FILTER;
+//extern const char* TIZEN_FUNCTION_API_CREATE_ATTRIBUTE_FILTER;
+//extern const char* TIZEN_FUNCTION_API_CREATE_ATTRIBUTE_RANGE_FILTER;
+//extern const char* TIZEN_FUNCTION_API_CREATE_ID_FILTER;
+//extern const char* TIZEN_FUNCTION_API_CREATE_SORT_MODE;
+
+}
+}
+
+#endif // __TIZEN_TIZEN_PLUGIN_CONFIG_H__
diff --git a/src/Tizen/plugin_initializer.cpp b/src/Tizen/plugin_initializer.cpp
new file mode 100644 (file)
index 0000000..7153bce
--- /dev/null
@@ -0,0 +1,140 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+#include <Commons/Exception.h>
+#include <Logger.h>
+#include <GlobalContextManager.h>
+
+#include "JSTizen.h"
+#include "JSAttributeFilter.h"
+#include "JSAttributeRangeFilter.h"
+#include "JSCompositeFilter.h"
+#include "JSSortMode.h"
+#include "JSSimpleCoordinates.h"
+
+#define TIZEN_TIZEN "tizen"
+#define TIZEN_ATTRIBUTE_FILTER "AttributeFilter"
+#define TIZEN_ATTRIBUTE_RANGE_FILTER "AttributeRangeFilter"
+#define TIZEN_COMPOSITE_FILTER "CompositeFilter"
+#define TIZEN_SORT_MODE "SortMode"
+#define TIZEN_SIMPLE_COORDINATES "SimpleCoordinates"
+
+namespace Options {
+class_definition_options_t TizenOptions = {
+        JS_CLASS,
+        CREATE_INSTANCE,
+        NONE_NOTICE,
+        USE_OVERLAYED,
+        NULL,
+        NULL,
+        NULL };
+
+class_definition_options_t TizenInterfaceOptions = {
+        JS_INTERFACE,
+        CREATE_INSTANCE,
+        NONE_NOTICE,
+        USE_OVERLAYED,
+        NULL,
+        NULL,
+        NULL };
+}
+
+namespace DeviceAPI {
+namespace Tizen {
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+
+void on_widget_start_callback(int widget_id)
+{
+    LOGD("[Tizen\\xxx] on_widget_start_callback (%d)", widget_id);
+    try {
+        WrtAccessSingleton::Instance().initialize(widget_id);
+    }
+    catch (Exception) {
+        LOGE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widget_id)
+{
+    LOGD("[Tizen\\xxx] on_widget_start_callback (%d)", widget_id);
+    try {
+        WrtAccessSingleton::Instance().deinitialize(widget_id);
+    }
+    catch (Exception) {
+        LOGE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    LOGD("[Tizen\\xxx] on_frame_load_callback (%p)", context);
+    Common::GlobalContextManager::getInstance()->
+            addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    LOGD("[Tizen\\xxx] on_frame_unload_callback (%p)", context);
+    Common::GlobalContextManager::getInstance()->
+            removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START (on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP (on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_GLOBAL,
+        TIZEN_TIZEN,
+        (js_class_template_getter)DeviceAPI::Tizen::JSTizen::getClassRef,
+        &Options::TizenOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(TIZEN_TIZEN,
+        TIZEN_ATTRIBUTE_FILTER,
+        (js_class_template_getter)DeviceAPI::Tizen::JSAttributeFilter::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Tizen::JSAttributeFilter::constructor,
+        &Options::TizenInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(TIZEN_TIZEN,
+        TIZEN_ATTRIBUTE_RANGE_FILTER,
+        (js_class_template_getter)DeviceAPI::Tizen::JSAttributeRangeFilter::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Tizen::JSAttributeRangeFilter::constructor,
+        &Options::TizenInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(TIZEN_TIZEN,
+        TIZEN_COMPOSITE_FILTER,
+        (js_class_template_getter)DeviceAPI::Tizen::JSCompositeFilter::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Tizen::JSCompositeFilter::constructor,
+        &Options::TizenInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(TIZEN_TIZEN,
+        TIZEN_SORT_MODE,
+        (js_class_template_getter)DeviceAPI::Tizen::JSSortMode::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Tizen::JSSortMode::constructor,
+        &Options::TizenInterfaceOptions)
+PLUGIN_CLASS_MAP_ADD_INTERFACE(TIZEN_TIZEN,
+        TIZEN_SIMPLE_COORDINATES,
+        (js_class_template_getter)DeviceAPI::Tizen::JSSimpleCoordinates::getClassRef,
+        (js_class_constructor_cb_t)DeviceAPI::Tizen::JSSimpleCoordinates::constructor,
+        &Options::TizenInterfaceOptions)
+PLUGIN_CLASS_MAP_END
+
+//#undef OBJECT_TIZEN
+
+} // Tizen
+} // DeviceAPI
diff --git a/src/WebSetting/CMakeLists.txt b/src/WebSetting/CMakeLists.txt
new file mode 100755 (executable)
index 0000000..7afa65a
--- /dev/null
@@ -0,0 +1,50 @@
+
+SET(TARGET_NAME ${websetting_target})
+SET(DESTINATION_NAME ${websetting_dest})
+SET(TARGET_IMPL_NAME ${websetting_impl})
+
+PKG_CHECK_MODULES(platform_pkgs_websetting REQUIRED
+       wrt-plugins-ipc-message
+)
+
+INCLUDE_DIRECTORIES(
+       ${INCLUDE_COMMON}
+       ${platform_pkgs_websetting_INCLUDE_DIRS}
+)
+
+SET(CMAKE_INSTALL_RPATH
+       ${CMAKE_INSTALL_RPATH}
+       ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${tizen_dest}
+       ${CMAKE_INSTALL_PREFIX}/${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME}
+)
+
+SET(SRCS_IMPL
+    JSWebSettingManager.cpp
+    WebSettingManager.cpp
+)
+
+ADD_LIBRARY(${TARGET_IMPL_NAME} SHARED ${SRCS_IMPL})
+
+TARGET_LINK_LIBRARIES(${TARGET_IMPL_NAME}
+       ${LIBS_COMMON}
+       ${tizen_impl}
+       ${platform_pkgs_websetting_LIBRARIES}
+)
+
+SET(SRCS
+       plugin_config.cpp
+       plugin_initializer.cpp
+)
+
+ADD_LIBRARY(${TARGET_NAME} SHARED ${SRCS})
+
+TARGET_LINK_LIBRARIES(${TARGET_NAME}
+       ${TARGET_IMPL_NAME}
+)
+
+INSTALL(TARGETS ${TARGET_NAME} ${TARGET_IMPL_NAME} LIBRARY DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/config.xml DESTINATION ${DESTINATION_LIB_PREFIX}/${DESTINATION_NAME})
+INSTALL(
+        DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/ DESTINATION ${DESTINATION_HEADER_PREFIX}/websetting
+        FILES_MATCHING PATTERN "*.h" PATTERN "CMakeFiles" EXCLUDE
+)
diff --git a/src/WebSetting/JSWebSettingManager.cpp b/src/WebSetting/JSWebSettingManager.cpp
new file mode 100755 (executable)
index 0000000..bf1726b
--- /dev/null
@@ -0,0 +1,209 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <ArgumentValidator.h>
+#include <GlobalContextManager.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <Logger.h>
+#include <MultiCallbackUserData.h>
+#include <PlatformException.h>
+#include <SecurityExceptions.h>
+
+#include "plugin_config.h"
+#include "JSWebSettingManager.h"
+
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI
+{
+namespace WebSetting
+{
+
+JSClassDefinition JSWebSettingManager::m_classInfo =
+{
+    0,
+    kJSClassAttributeNone,
+    "WebSettingManager",
+    NULL, //ParentClass
+    NULL, //StaticValues
+    m_function, //StaticFunctions
+    initialize, //Initialize
+    finalize, //Finalize
+    NULL, //HasProperty,
+    NULL, //GetProperty,
+    NULL, //SetProperty,
+    NULL, //DeleteProperty,
+    NULL, //GetPropertyNames,
+    NULL, //CallAsFunction,
+    NULL, //CallAsConstructor,
+    NULL, //HasInstance,
+    NULL //ConvertToType
+};
+
+JSStaticFunction JSWebSettingManager::m_function[] =
+{
+    { WEB_SETTING_MANAGER_API_SET_USER_AGENT_STRING, setUserAgentString, kJSPropertyAttributeNone },
+    { WEB_SETTING_MANAGER_API_REMOVE_ALL_COOKIES, removeAllCookies, kJSPropertyAttributeNone },
+    { 0, 0, 0 }
+};
+
+JSClassRef JSWebSettingManager::m_jsClassRef = JSClassCreate(JSWebSettingManager::getClassInfo());
+
+const JSClassRef JSWebSettingManager::getClassRef()
+{
+    if (!m_jsClassRef)
+    {
+        m_jsClassRef = JSClassCreate(&m_classInfo);
+    }
+    return m_jsClassRef;
+}
+
+const JSClassDefinition* JSWebSettingManager::getClassInfo()
+{
+    return &m_classInfo;
+}
+
+void JSWebSettingManager::initialize(JSContextRef context, JSObjectRef object)
+{
+    if (!JSObjectGetPrivate(object))
+    {
+        WebSettingManager *priv = WebSettingManager::getInstance();
+        JSObjectSetPrivate(object, static_cast<void*>(priv));
+    }
+}
+
+void JSWebSettingManager::finalize(JSObjectRef object)
+{
+    WebSettingManager *priv = static_cast<WebSettingManager*>(JSObjectGetPrivate(object));
+    if (priv)
+    {
+        JSObjectSetPrivate(object, NULL);
+    }
+}
+
+JSValueRef JSWebSettingManager::setUserAgentString(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    LoggerD("setUserAgentString");
+    try
+    {
+        // Private Object
+        WebSettingManager *priv = static_cast<WebSettingManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv)
+        {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+        ArgumentValidator validator(context, argumentCount, arguments);
+        MultiCallbackUserData* callbacks = new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        // userAgent
+        std::string userAgent = validator.toString(0);
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(1, true);
+        if (successCallbackObj)
+        {
+            callbacks->setCallback("onsuccess", successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(2, true);
+
+        if (errorCallbackObj)
+        {
+            callbacks->setCallback("onerror", errorCallbackObj);
+        }
+
+        priv->setUserAgentString(userAgent, callbacks);
+
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err)
+    {
+        SLoggerE(err.getName().c_str() << ":" << err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...)
+    {
+        DeviceAPI::Common::UnknownException err("Unknown Error in WebSettingManager.setUserAgentString().");
+        SLoggerE(err.getName().c_str() << ":" <<  err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+JSValueRef JSWebSettingManager::removeAllCookies(JSContextRef context,
+        JSObjectRef object,
+        JSObjectRef thisObject,
+        size_t argumentCount,
+        const JSValueRef arguments[],
+        JSValueRef* exception)
+{
+    AceSecurityStatus status = WEB_SETTING_CHECK_ACCESS(WEB_SETTING_MANAGER_API_REMOVE_ALL_COOKIES);
+    TIZEN_SYNC_ACCESS_HANDLER(status, context, exception);
+    LoggerD("removeAllCookies::TIZEN_SYNC_ACCESS_HANDLER succeeded.");
+
+    try
+    {
+        // Private Object
+        WebSettingManager *priv = static_cast<WebSettingManager*>(JSObjectGetPrivate(thisObject));
+        if (!priv)
+        {
+            throw TypeMismatchException("Private object is NULL.");
+        }
+
+        ArgumentValidator validator(context, argumentCount, arguments);
+        MultiCallbackUserData* callbacks = new MultiCallbackUserData(GlobalContextManager::getInstance()->getGlobalContext(context));
+
+        // successCallback
+        JSObjectRef successCallbackObj = validator.toFunction(0, true);
+        if (successCallbackObj)
+        {
+            callbacks->setCallback("onsuccess", successCallbackObj);
+        }
+
+        // errorCallback
+        JSObjectRef errorCallbackObj = validator.toFunction(1, true);
+        if (errorCallbackObj)
+        {
+            callbacks->setCallback("onerror", errorCallbackObj);
+        }
+        priv->removeAllCookies(callbacks);
+        return JSValueMakeUndefined(context);
+    }
+    catch (const BasePlatformException &err)
+    {
+        SLoggerE(err.getName().c_str() << ":" << err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+    catch (...)
+    {
+        DeviceAPI::Common::UnknownException err("Unknown Error in WebSettingManager.removeAllCookies().");
+        SLoggerE(err.getName().c_str() << ":" << err.getMessage().c_str());
+        return JSWebAPIErrorFactory::postException(context, exception, err);
+    }
+}
+
+
+} // WebSetting
+} // DeviceAPI
diff --git a/src/WebSetting/JSWebSettingManager.h b/src/WebSetting/JSWebSettingManager.h
new file mode 100755 (executable)
index 0000000..b3c6f24
--- /dev/null
@@ -0,0 +1,88 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_JS_WEB_SETTING_MANAGER_H__
+#define __TIZEN_JS_WEB_SETTING_MANAGER_H__
+
+#include <JavaScriptCore/JavaScript.h>
+
+#include "WebSettingManager.h"
+
+namespace DeviceAPI
+{
+namespace WebSetting
+{
+
+class JSWebSettingManager
+{
+public:
+    static const JSClassDefinition* getClassInfo();
+    static const JSClassRef getClassRef();
+private:
+
+    /**
+     * The callback invoked when an object is first created.
+     */
+    static void initialize(JSContextRef context,
+                           JSObjectRef object);
+
+    /**
+     * The callback invoked when an object is finalized.
+     */
+    static void finalize(JSObjectRef object);
+
+    static JSValueRef setUserAgentString(JSContextRef context,
+                                         JSObjectRef object,
+                                         JSObjectRef thisObject,
+                                         size_t argumentCount,
+                                         const JSValueRef arguments[],
+                                         JSValueRef* exception);
+
+    static JSValueRef removeAllCookies(JSContextRef context,
+                                       JSObjectRef object,
+                                       JSObjectRef thisObject,
+                                       size_t argumentCount,
+                                       const JSValueRef arguments[],
+                                       JSValueRef* exception);
+
+    /**
+     * This member variable contains the values which has to be passed
+     * when the this class is embedded into JS Engine.
+     */
+    static JSClassDefinition m_classInfo;
+
+    /**
+     * This structure describes a statically declared function property.
+     */
+    static JSStaticFunction m_function[];
+
+    /**
+     * This member variable contains the initialization values for the
+     * properties of this class. The values are given according to
+     * the data structure JSPropertySpec
+     */
+    static JSStaticValue m_property[];
+
+    static JSClassRef m_jsClassRef;
+};
+
+
+
+} // WebSetting
+} // DeviceAPI
+
+#endif // __TIZEN_JS_DOWNLOAD_MANAGER_H__
diff --git a/src/WebSetting/WebSettingManager.cpp b/src/WebSetting/WebSettingManager.cpp
new file mode 100755 (executable)
index 0000000..b01dbc0
--- /dev/null
@@ -0,0 +1,119 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <PlatformException.h>
+#include <Logger.h>
+#include "WebSettingManager.h"
+#include <glib.h>
+#include <Ecore.h>
+#include <JSUtil.h>
+#include <JSWebAPIError.h>
+#include <PlatformException.h>
+#include <GlobalContextManager.h>
+#include <plugins-ipc-message/ipc_message_support.h>
+
+namespace DeviceAPI
+{
+namespace WebSetting
+{
+
+std::list<Common::MultiCallbackUserData *> WebSettingManager::mUserAgentCallbacks;
+std::list<Common::MultiCallbackUserData *> WebSettingManager::mDeleteAllCookiesCallbacks;
+
+WebSettingManager::WebSettingManager()
+{
+    LoggerD("Constructor of WebSettingManager...");
+}
+
+WebSettingManager::~WebSettingManager()
+{
+    LoggerD("Destructor of WebSettingManager...");
+}
+
+WebSettingManager* WebSettingManager::getInstance()
+{
+    static WebSettingManager instance;
+    return &instance;
+}
+
+void WebSettingManager::onAsyncUAStringReplyCallback(unsigned int num, void* user_data, const char* result)
+{
+    MultiCallbackUserData* multiPointer = static_cast<MultiCallbackUserData *>(user_data);
+    if (multiPointer != NULL)
+    {
+        CHECK_CURRENT_CONTEXT_ALIVE(multiPointer->getContext());
+       
+        unsigned int successStrLength = strlen("success");
+        if ((strncmp(result,"success", successStrLength) == 0) && (strlen(result) == successStrLength))
+        {
+            multiPointer->invokeCallback("onsuccess", NULL);
+        }
+        else
+        {
+            UnknownException error("Unknown");
+            JSObjectRef errorObj = JSWebAPIErrorFactory::makeErrorObject(multiPointer->getContext(), error);
+            multiPointer->invokeCallback("onerror", errorObj);
+        }
+        WebSettingManager::mUserAgentCallbacks.remove(multiPointer);
+        delete multiPointer;;
+    }
+    else
+    {
+        LoggerD("MultiCallbackUserData is NULL.");;
+    }
+}
+
+void WebSettingManager::onAsyncReplyRemoveAllCookiesCallback(unsigned int num, void* user_data, const char* result)
+{
+    MultiCallbackUserData* multiPointer = static_cast<MultiCallbackUserData *>(user_data);
+    if (multiPointer != NULL)
+    {
+        CHECK_CURRENT_CONTEXT_ALIVE(multiPointer->getContext());
+        unsigned int successStrLength = strlen("success");
+        if ((strncmp(result,"success", successStrLength)== 0) && (strlen(result) == successStrLength))
+        {
+            multiPointer->invokeCallback("onsuccess", NULL);
+        }
+        else
+        {
+            UnknownException error("Unknown");
+            JSObjectRef errorObj = JSWebAPIErrorFactory::makeErrorObject(multiPointer->getContext(), error);
+            multiPointer->invokeCallback("onerror", errorObj);
+        }
+        WebSettingManager::mDeleteAllCookiesCallbacks.remove(multiPointer);
+        delete multiPointer;;
+    }
+    else
+    {
+        LoggerD("MultiCallbackUserData is NULL." );;
+    }
+}
+
+void WebSettingManager::setUserAgentString(std::string userAgent, MultiCallbackUserData* callbacks)
+{
+    WebSettingManager::mUserAgentCallbacks.push_back(callbacks);
+    IPCMessageSupport::sendAsyncMessageToUiProcess(IPCMessageSupport::TIZEN_CHANGE_USERAGENT, userAgent.c_str(), WebSettingManager::onAsyncUAStringReplyCallback, callbacks);
+}
+
+void WebSettingManager::removeAllCookies(MultiCallbackUserData* callbacks)
+{
+    WebSettingManager::mDeleteAllCookiesCallbacks.push_back(callbacks);
+    IPCMessageSupport::sendAsyncMessageToUiProcess(IPCMessageSupport::TIZEN_DELETE_ALL_COOKIES, NULL, WebSettingManager::onAsyncReplyRemoveAllCookiesCallback, callbacks);
+}
+
+}
+}
diff --git a/src/WebSetting/WebSettingManager.h b/src/WebSetting/WebSettingManager.h
new file mode 100755 (executable)
index 0000000..f9316e3
--- /dev/null
@@ -0,0 +1,52 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef __TIZEN_WEB_SETTING_MANAGER_H__
+#define __TIZEN_WEB_SETTING_MANAGER_H__
+
+#include <MultiCallbackUserData.h>
+#include "WebSettingTypes.h"
+#include <list>
+
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI
+{
+namespace WebSetting
+{
+
+class WebSettingManager
+{
+public:
+    void setUserAgentString(std::string userAgent, MultiCallbackUserData* callbacks);
+    void removeAllCookies(MultiCallbackUserData* callbacks);
+
+    static std::list<Common::MultiCallbackUserData *> mUserAgentCallbacks;
+    static std::list<Common::MultiCallbackUserData *> mDeleteAllCookiesCallbacks;
+
+    static void onAsyncUAStringReplyCallback(unsigned int num, void* user_data, const char* result);
+    static void onAsyncReplyRemoveAllCookiesCallback(unsigned int num, void* user_data, const char* result);
+    static WebSettingManager* getInstance();
+private:
+    WebSettingManager();
+    virtual ~WebSettingManager();
+};
+
+} // WebSetting
+} // DeviceAPI
+
+#endif // __TIZEN_WEB_SETTING_MANAGER_H__
diff --git a/src/WebSetting/WebSettingTypes.h b/src/WebSetting/WebSettingTypes.h
new file mode 100755 (executable)
index 0000000..6c4f54e
--- /dev/null
@@ -0,0 +1,34 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef _WEB_SETTING_TYPES_H_
+#define _WEB_SETTING_TYPES_H_
+
+#include <string>
+#include <vector>
+#include <map>
+
+namespace DeviceAPI
+{
+namespace WebSetting
+{
+
+
+} // WebSetting
+} // DeviceAPI
+
+#endif // _WEB_SETTING_TYPES_H_
diff --git a/src/WebSetting/config.xml b/src/WebSetting/config.xml
new file mode 100644 (file)
index 0000000..6ec8526
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" ?>
+<!DOCTYPE plugin-properties SYSTEM "/usr/etc/tizen-apis/config.dtd">
+<plugin-properties>
+    <library-name>libwrt-plugins-tizen-websetting.so</library-name>
+    <feature-install-uri>websetting.install.uri</feature-install-uri>
+
+    <api-feature>
+        <name>http://tizen.org/privilege/websetting</name>
+        <device-capability>websetting</device-capability>
+    </api-feature>
+
+</plugin-properties>
diff --git a/src/WebSetting/plugin_config.cpp b/src/WebSetting/plugin_config.cpp
new file mode 100755 (executable)
index 0000000..3ceef6b
--- /dev/null
@@ -0,0 +1,82 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/FunctionDefinition.h>
+#include <Commons/FunctionDeclaration.h>
+#include <Commons/Exception.h>
+#include <map>
+
+#include "plugin_config.h"
+
+#define WEBSETTING_FEATURE_API "http://tizen.org/privilege/websetting"
+#define WEBSETTING_DEVICE_CAP "websetting"
+
+using namespace WrtDeviceApis::Commons;
+
+namespace DeviceAPI
+{
+namespace WebSetting
+{
+
+static FunctionMapping createWebSettingFunctions();
+static FunctionMapping WebSettingFunctions = createWebSettingFunctions();
+
+#pragma GCC visibility push(default)
+
+DEFINE_FUNCTION_GETTER(WebSetting, WebSettingFunctions);
+
+#pragma GCC visibility pop
+
+static FunctionMapping createWebSettingFunctions()
+{
+    /**
+     * Device capabilities
+     */
+    ACE_CREATE_DEVICE_CAP(DEVICE_CAP_WEBSETTING, WEBSETTING_DEVICE_CAP);
+    ACE_CREATE_DEVICE_CAPS_LIST(DEVICE_LIST_WEBSETTING);
+    ACE_ADD_DEVICE_CAP(DEVICE_LIST_WEBSETTING, DEVICE_CAP_WEBSETTING);
+
+    /**
+     * Api Features
+     */
+    ACE_CREATE_FEATURE(FEATURE_WEBSETTING, WEBSETTING_FEATURE_API);
+    ACE_CREATE_FEATURE_LIST(WEBSETTING_FEATURES);
+    ACE_ADD_API_FEATURE(WEBSETTING_FEATURES, FEATURE_WEBSETTING);
+
+    /**
+     * Functions
+     */
+    FunctionMapping websettingMapping;
+
+    // remove cookies
+    AceFunction removeAllCookiesFunc = ACE_CREATE_FUNCTION(
+                                           FUNCTION_REMOVE_ALL_COOKIES,
+                                           WEB_SETTING_MANAGER_API_REMOVE_ALL_COOKIES,
+                                           WEBSETTING_FEATURES,
+                                           DEVICE_LIST_WEBSETTING);
+
+    websettingMapping.insert(std::make_pair(
+                                 WEB_SETTING_MANAGER_API_REMOVE_ALL_COOKIES,
+                                 removeAllCookiesFunc));
+
+    return websettingMapping;
+}
+
+} // WebSetting
+} // DeviceAPI
+
diff --git a/src/WebSetting/plugin_config.h b/src/WebSetting/plugin_config.h
new file mode 100755 (executable)
index 0000000..fafd85f
--- /dev/null
@@ -0,0 +1,48 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#ifndef _WEB_SETTING_PLUGIN_CONFIG_H_
+#define _WEB_SETTING_PLUGIN_CONFIG_H_
+
+#include <string>
+#include <Commons/FunctionDeclaration.h>
+
+#include <Logger.h>
+
+namespace DeviceAPI
+{
+namespace WebSetting
+{
+
+// attributes
+
+// functions
+#define WEB_SETTING_MANAGER_API_SET_USER_AGENT_STRING "setUserAgentString"
+#define WEB_SETTING_MANAGER_API_REMOVE_ALL_COOKIES "removeAllCookies"
+
+DECLARE_FUNCTION_GETTER(WebSetting);
+
+#define WEB_SETTING_CHECK_ACCESS(functionName) \
+    aceCheckAccess<AceFunctionGetter, DefaultArgsVerifier<> >( \
+    getWebSettingFunctionData, \
+    functionName)
+
+}
+}
+
+#endif // _WEB_SETTING_PLUGIN_CONFIG_H_
\ No newline at end of file
diff --git a/src/WebSetting/plugin_initializer.cpp b/src/WebSetting/plugin_initializer.cpp
new file mode 100755 (executable)
index 0000000..0620473
--- /dev/null
@@ -0,0 +1,87 @@
+//
+// Tizen Web Device API
+// Copyright (c) 2012 Samsung Electronics Co., Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the License);
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+
+#include <Commons/plugin_initializer_def.h>
+#include <Commons/WrtAccess/WrtAccess.h>
+
+#include <GlobalContextManager.h>
+
+#include "JSWebSettingManager.h"
+
+#include <Logger.h>
+
+using namespace WrtDeviceApis;
+using namespace WrtDeviceApis::Commons;
+using namespace DeviceAPI::Common;
+
+namespace DeviceAPI
+{
+namespace WebSetting
+{
+
+
+void on_widget_start_callback(int widgetId)
+{
+    LoggerD("[Tizen\\WebSetting] on_widget_start_callback");
+    try
+    {
+        WrtAccessSingleton::Instance().initialize(widgetId);
+    }
+    catch (...)
+    {
+        LoggerE("WrtAccess initialization failed");
+    }
+}
+
+void on_widget_stop_callback(int widgetId)
+{
+    LoggerD("[Tizen\\WebSetting] on_widget_stop_callback");
+    try
+    {
+        WrtAccessSingleton::Instance().deinitialize(widgetId);
+    }
+    catch (...)
+    {
+        LoggerE("WrtAccess deinitialization failed");
+    }
+}
+
+void on_frame_load_callback(const void * context)
+{
+    GlobalContextManager::getInstance()->addGlobalContext(static_cast<JSContextRef>(context));
+}
+
+void on_frame_unload_callback(const void * context)
+{
+    GlobalContextManager::getInstance()->removeGlobalContext(static_cast<JSContextRef>(context));
+}
+
+PLUGIN_ON_WIDGET_START(on_widget_start_callback)
+PLUGIN_ON_WIDGET_STOP(on_widget_stop_callback)
+PLUGIN_ON_FRAME_LOAD(on_frame_load_callback)
+PLUGIN_ON_FRAME_UNLOAD(on_frame_unload_callback)
+
+PLUGIN_CLASS_MAP_BEGIN
+PLUGIN_CLASS_MAP_ADD_CLASS(WRT_JS_EXTENSION_OBJECT_TIZEN,
+                           "websetting",
+                           (js_class_template_getter)JSWebSettingManager::getClassRef,
+                           NULL)
+PLUGIN_CLASS_MAP_END
+
+} // WebSetting
+} // DeviceAPI
diff --git a/wrt-plugins-tizen.manifest b/wrt-plugins-tizen.manifest
new file mode 100644 (file)
index 0000000..81ace0c
--- /dev/null
@@ -0,0 +1,6 @@
+<manifest>
+       <request>
+               <domain name="_"/>
+       </request>
+</manifest>
+